Métodos de estructuras en c. Estructuras. Accediendo a elementos de estructura

Antes de comenzar a estudiar clases en C++, veremos un tipo de datos similar a una clase: estructuras. Las estructuras son útiles cuando necesitamos combinar múltiples variables con diferentes tipos bajo un mismo nombre. Esto hace que el programa sea más compacto y más flexible para realizar cambios. Las estructuras también son indispensables cuando es necesario agrupar algún dato, por ejemplo, un registro de una base de datos o un contacto de una libreta de direcciones. En este último caso, la estructura contendrá datos de contacto como nombre, dirección, número de teléfono, etc.

Sintaxis

Mientras escribe un programa, es posible que necesite agrupar diferentes datos. Por ejemplo, es posible que desees almacenar las coordenadas de algunos objetos y sus nombres. Puedes hacer esto con:

Int x_coor; int y_coor; nombres de cadenas;

Pero como cada elemento de una matriz está conectado a otro, cuando cambies uno, tendrás que cambiar el resto también. Y cuantos más datos necesite combinar, más complejo será dicho programa. Por lo tanto, para combinar diferentes datos, utilizamos estructuras .

Formato de anuncio la estructura se ve así:

Estructura de coche (int x_coor; int y_coor; nombre de cadena;);

Al declarar una estructura, introducimos nuestra propio tipo datos que podemos utilizar, así como tipos estándar, es decir. La declaración de una variable de nuestro tipo será así:

Nombre de estructura nombre de variable;

structName es el nombre de la estructura, variableName es el nombre de la variable.

x_coor, y_coor y nombre - campos nuestra estructura. Al declarar una estructura creamos tipo compuesto datos, con los que puedes crear variables que combinen múltiples valores (por ejemplo, coordenadas y nombre). Dentro de la estructura, le damos un nombre a cada campo para luego poder acceder a este valor por su nombre.

Para acceder a los campos de la estructura, utilice un punto:

// declarar la variable Coche miCoche; // y úsalo myCar.x_coor = 40; miCar.y_coor = 40; miCoche.nombre = "Porche";

Como puedes ver, puedes almacenar tantos campos como quieras en la estructura y pueden ser de diferentes tipos.

Veamos un ejemplo que demuestra la combinación de matrices y estructuras.

#incluir usando el espacio de nombres estándar; struct PlayerInfo (int nivel_habilidad; nombre de cadena;); usando el espacio de nombres estándar; int main() ( // igual que con tipos regulares, puedes declarar una matriz de estructuras PlayerInfo player;< 5; i++) { cout << "Please enter the name for player: " << i << "\n"; // сперва получим доступ к элементу массива, используя // обычный синтаксис для массивов, затем обратимся к полю структуры // с помощью точки cin >para (int i = 0; i<< "Please enter the skill level for " << players[ i ].name << "\n"; cin >> jugadores[ i ].skill_level;< 5; ++i) { cout << players[ i ].name << " is at skill level " << players[i].skill_level << "\n"; } }

) para (int i = 0; i

Al igual que con los tipos simples (int, por ejemplo), puedes crear matrices de estructuras. Y trabaje con cada elemento de esta matriz de la misma manera que con una variable separada. Para acceder al campo de nombre del primer elemento de una matriz de estructuras, simplemente escriba:

Jugadores[ 0 ].nombre

Estructuras y funciones

Muy a menudo es necesario escribir funciones que tomen estructuras como argumentos o devuelvan una estructura. Por ejemplo, si necesitas escribir un pequeño juego de arcade espacial, es posible que necesites una función para inicializar un nuevo enemigo:

Estructura EnemySpaceShip ( int x_coordinate; int y_coordinate; int arma_power; ); Nave espacial enemiga getNewEnemy();

La función getNewEnemy debería devolver una estructura con campos inicializados:

EnemySpaceShip getNewEnemy() ( nave EnemySpaceShip; ship.x_coordinate = 0; ship.y_coordinate = 0; ship.weapon_power = 20; nave de regreso; )

Esta función en realidad devolverá una copia de la variable local creada. Esto significa que cada campo de la estructura se copiará en una nueva variable. En nuestro caso, copiar una pequeña cantidad de campos no se nota, pero cuando trabajas con grandes cantidades de datos, debes evitar acciones innecesarias; hablaremos más sobre esto en el artículo sobre punteros;

Así, para obtener una nueva variable usaremos el siguiente código:

Nave espacial enemiga = getNewEnemy();

Ahora esta variable se puede utilizar como una estructura regular.

Puedes pasar estructuras a una función como esta:

Actualización de EnemySpaceShipArmas (barco EnemySpaceShip) ( ship.weapon_power += 10; barco de regreso; )

Cuando pasamos una estructura a una función, se copia, al igual que cuando devolvemos una estructura. Por lo tanto, cualquier cambio realizado dentro de la función se perderá, por lo que devolvemos la estructura después del cambio.

Usando la función:

Barco = actualizarArmas(barco);

Cuando se llama a una función, la variable de envío se copia y modifica en la función, y cuando se devuelve la variable, se copia nuevamente y sobrescribe los campos de la variable original.

Y finalmente, un programa para crear y mejorar un barco:

Estructura EnemySpaceShip ( int x_coordinate; int y_coordinate; int arma_power; ); EnemySpaceShip getNewEnemy() ( nave EnemySpaceShip; ship.x_coordinate = 0; ship.y_coordinate = 0; ship.weapon_power = 20; nave de regreso; ) actualización de EnemySpaceShipWeapons(nave EnemySpaceShip) ( ship.weapon_power += 10; nave de regreso; ) int main () (EnemySpaceShip enemigo = getNewEnemy(); enemigo = actualizarArmas(enemigo); )

Si está trabajando con una estructura, para acceder a las variables necesita usar el operador "->" en lugar de un punto. Todas las propiedades del puntero no cambian. Ejemplo:

#incluir usando el espacio de nombres estándar; estructura xampl(int x;); int main() ( estructura xampl; xampl *ptr; estructura.x = 12; ptr = cout<< ptr->incógnita; cin.get(); )

El tipo de variable determina: su tamaño en memoria, el tipo de datos que puede almacenar y las operaciones que se pueden realizar sobre la variable.

El tipo de datos es categoría. En C++, un programador puede crear cualquier tipo de datos basándose en los tipos base. Es necesario crear nuevos tipos de datos para resolver problemas prácticos específicos. Por ejemplo: implementación del trabajo del decano.

El éxito de un programa depende a menudo de la elección exitosa del método de presentación de datos. Utilizando estructuras es posible modelar objetos complejos que surgen al resolver problemas. Las estructuras proporcionan un medio para acceder a registros que contienen campos de uno o más tipos.

Para utilizar la estructura necesitas:
1. establecer una plantilla para la estructura
2. declarar una variable que coincida con este patrón
3. acceder a los componentes de la estructura.

Plantilla de estructura

Una plantilla es un diagrama que describe el contenido de una estructura. Instalación de una plantilla de estructura de directorio telefónico:

estructura esparcida (
char fio;
número largo;
};

Esta plantilla describe una estructura con el nombre tipo de estructura sprav, que consta de dos componentes: la cadena fio y la variable entera num de tipo long. El nombre del tipo de estructura sprav es opcional y se utiliza para hacer referencia a esa estructura. Los componentes de la estructura son datos de cualquier tipo, incluidas otras estructuras. El nombre dentro de una estructura puede ser el mismo que el nombre de un objeto fuera de la estructura. Si una plantilla se describe dentro de una función, está disponible solo para esta función; si una plantilla se describe fuera de una función, está disponible para cualquier función del programa. La instalación de una plantilla no provoca ninguna acción en el programa.

Variables estructurales

La declaración de variables de estructura da como resultado la asignación de memoria para los componentes de la estructura donde se pueden escribir o leer datos. Hay varias formas de declarar variables de estructura.

1. Configure una plantilla de estructura:

estructura esparcida (
char fio;
número largo;
};

Declare una variable simple, una matriz de estructuras, un puntero a una estructura: estructura sprav tel1, tel2, *tel3;

2. Configure la plantilla estructural usando una definición de macro:

#definir SPRAV estructura sprav
SPRAV (
char fio;
número largo;
};

Declarar variables:

SPRAV sp1, sp2, *sp3;

3. Declare variables al mismo tiempo que configura la plantilla (si ya no hace referencia a esta estructura):

estructura (
char fio;
número largo;
) tel1, tel2, *tel3;

4. Introduzca un nuevo tipo de datos (TEL): una estructura de cierto tipo:

estructura typedef(
char fio;
número largo;
) TELÉFONO;

Declarar variables de un nuevo tipo:

TEL tel1, tel2, *tel3;

Si el programa es lo suficientemente grande, el cuarto método parece más conveniente.

Inicializando la estructura

Sólo se pueden inicializar estructuras externas o estáticas.

estructura estática (
char fio;
número largo;
) teléfono=(
"Ivanov F.A.", 456756,
"Petrov vicepresidente", 632345
};

Acceder a los componentes de la estructura

Demostraremos el acceso a los componentes de la estructura mediante ejemplos.

/* Accediendo a elementos de estructura mediante nombre de variable */
#incluir
#incluir
vacío principal (vacío)
{
estructura (
char fio; /* apellido */
número largo; /* teléfono */
) tel1, tel2;

puts("ingrese el nombre del suscriptor-");
obtiene(tel1.fio);
puts("ingrese su numero-");
scanf("%ld",&tel1.num);
tel2=tel1; /* tampoco puedes comparar estructuras */
pone("Ingresado:");
printf("Apellido:%s número: %ld\n",tel2.fio,tel2.num);
}

/* Asignar memoria dinámicamente para una estructura */

#incluir
#incluir
#incluir
estructura esparcida (
char fio;
número largo;
};

vacío principal (vacío)
{
estructura sprav *tel1, *tel2;

clrscr();
/* Asigna memoria para la estructura */
tel1=(struct sprav *)malloc(sizeof(struct sprav));
tel2=(struct sprav *)malloc(sizeof(struct sprav));

obtiene(tel1->fio);
puts("ingrese su numero-");
scanf("%ld",&tel1->num);
*tel2= *tel1;
pone("Ingresado:");
printf("Apellido:%s número: %ld\n",(*tel2).fio,(*tel2).num);
}

Conjunto de estructuras

/* Matriz de estructuras. Accediendo a elementos de estructura a través de */
/* nombre del elemento de la matriz */
#incluir
#incluir
#incluir
#definir SPRAV estructura sprav

vacío principal (vacío)
{
SPRAV(
char fio;
número largo;
};

SPRAV tel; /* conjunto de estructuras - 5 elementos */
char fio_tek;
ent i;

clrscr();
/* ingresando datos en una matriz de estructuras */
para(yo=0; yo<5; i++)
{
puts("ingrese el nombre del suscriptor-");
obtiene(tel[i].fio);
puts("ingrese su numero-");
scanf("%ld",&tel[i].num);
getchar();
}

obtiene(fio_tek);
/* busca una estructura por el apellido del suscriptor */
para(yo=0; yo<5; i++)
if(!strcmp(fio_tek,tel[i].fio)) descanso;
if(i!=5) /* el bucle terminó con una interrupción */

tel[i].num);
else /* bucle completado completamente */
puts("Suscriptor no encontrado");
}

/* Matriz de estructuras. La memoria se asigna dinámicamente. */
/* Accediendo a elementos de la estructura mediante un puntero */
#incluir
#incluir
#incluir
#incluir

estructura typedef(
char fio;
número largo;
) TELÉFONO;

vacío principal (vacío)
{
TEL *tel;
char fio_tek;
ent i;

clrscr();
/* Asignación de memoria para matriz - 3 elementos */
tel=(TEL *)malloc(tamaño de(TEL)*3);
para(yo=0; yo<3; i++)
{
puts("ingrese el nombre del suscriptor-");
obtiene((tel+i)->fio);
puts("ingrese su numero-");
scanf("%ld",&(tel+i)->núm);
getchar();
}
puts("Seleccione teléfono por apellido");
obtiene(fio_tek);
para(yo=0; yo<5; i++,tel++)
if(!strcmp(fio_tek,tel->fio)) descanso;
si(yo!=5)
printf("el número de suscriptor %s es %ld\n",fio_tek, \
tel->num);
demás
puts("Suscriptor no encontrado");
}

Pasar una estructura a una función.

El acceso directo a los componentes de la estructura es un mal estilo de programación. Todas las operaciones permitidas en relación con una estructura deben implementarse como funciones separadas. No todos los compiladores de lenguaje C permiten pasar estructuras a una función por valor, por lo que en los ejemplos la estructura se pasa a través de un puntero.

/* Pasar una estructura a una función mediante un puntero a una estructura */
/* Definición de un número complejo mediante estructura y acciones */
/* sobre números complejos (entrada, salida, cálculo de suma) */

#incluir
estructura typedef ( float a; /* parte real */
flotador b; /* parte imaginaria */
) COMPLEJO;
void vvod(COMPLEJO *,flotante,flotante);
suma nula(COMPLEJO *,COMPLEJO *,COMPLEJO *);
anular(COMPLEJO *);
vacío principal (vacío)
{
COMPLEJO x,y,z;
vvod(&x,2.5,6.7);
vvod(&y,6.89,8.45);
puts("Números ingresados:");
fuera(&x);
fuera(&y);
suma(&x,&y,&z);
puts("La suma de los números complejos es:");
fuera(&z);
}
/* Genera un número complejo */
anular(COMPLEJO *p)
{
printf("(%.2f,%.2f)\n", (*p).a,(*p).b);
devolver;
}

/* Calcula la suma de dos números complejos */
suma nula(COMPLEJO *p1,COMPLEJO *p2,COMPLEJO *p3)
{
(*p3).a=(*p1).a+(*p2).a;
(*p3).b=(*p1).b+(*p2).b;
devolver;
}

/* Ingresando valores para elementos de estructura */
vvod vacío(COMPLEJO *p,flotante a, flotante b)
{
pa->a=a;
p->b=b;
devolver;
}

Estructuras anidadas

Una estructura que es componente de otra estructura se llama anidada.

/* Dados cuatro puntos: los centros de cuatro círculos. Llene una estructura circular si todos los círculos pasan por el origen. */

#incluir
#incluir
#incluir
#incluir
estructura PUNTO (
flotar x;
flotar y;
};
estructura CÍRCULO (
estructura PUNTO punto; /* estructura anidada */
doble r;
) círculo, *p;
vacío principal (vacío)
{
int i, j;
flotar a,b,c,d;
clrscr();
gotoxi(17,1);
cputs("INGRESAR COORDENADAS DE PUNTO:\r\n");
para(i=0;yo<2;i++)
{
cprintf("\n\n INGRESE X: ");
cprintf("X[%d]= ",i+1);
cscanf("%f",&circle[i].point.x);
cprintf("\n ENTRAR Y: ");
cprintf("Y[%d]= ",i+1);
cscanf("%f",&circle[i].punto.y);
}
p=círculo;
gotoxi(17,12);
cputs("RESULTADO:\r\n\n");
para(i=0;yo<2;i++)
{
a=p->punto.x;
b=p->punto.y;
c=sqrt(a*a+b*b);
p->r=c;
cprintf("\nRADIO: %lf CENTRO (%f,%f)\r\n",p->r,a,b);
p++;
}

Una estructura en C es un tipo de datos diseñado para acomodar valores de diferentes tipos en un objeto. Útil cuando necesitas combinar varias variables de diferentes tipos bajo un mismo nombre. Hacen que el programa sea más compacto y más fácil de gestionar. La estructura tiene características similares a las matrices y clases.

matrices

Antes de hablar de estructura en C, necesitamos describir una matriz.

Hay matrices unidimensionales, bidimensionales y tridimensionales. Unidimensional es aquel que tiene una sola fila con los valores rellenados. Bidimensional: una matriz unidimensional, dentro de la cual hay otras matrices unidimensionales.

Una matriz regular en C se escribe así: int a = (1, 2, 3, 4).

Vemos que a es el nombre, int es el tipo de datos, los valores están dentro de las llaves ( ), y entre corchetes se indica la longitud, es decir, el número de elementos. El número de elementos es estático, establecido en 4. Esto significa que si el usuario agrega un quinto valor en este ejemplo, el compilador arrojará un error. Si inicialmente no se conoce la cantidad, se pueden agregar más tarde, pero corchetes no se asigna ningún valor.

De forma similar se declara bidimensional. Por ejemplo, una matriz que contiene 5 elementos de matriz, cada uno de los cuales contiene 3 elementos, se declara así: int a. Por analogía con una matriz unidimensional, no se puede agregar nada para no generar un error de compilación.

Los hay dinámicos y estáticos. Estático es aquel que contiene una cantidad fija de datos, es decir, tiene una longitud constante. Por dinámico nos referimos a aquel cuyo tamaño no está limitado; puede cambiar durante la ejecución del programa. La matriz dinámica se inicializa sin especificar la cantidad exacta.

Clases

La clase y la estructura son similares entre sí, pero difieren en algunos matices. ¿Qué es? Esta es una abstracción que describe métodos que aún no objeto existente. Después de la creación, un objeto o, como se le llama de otra manera, una instancia de una clase tiene propiedades específicas. Los métodos se pueden utilizar interna, externamente o por herencia.

La clase se declara así:

clase /*nombre de clase*/

/* especificador acceso privado significa que los métodos sólo se pueden controlar dentro de la clase*/

/* pone las propiedades a disposición de otras partes del código */

/* las clases heredadas obtienen la capacidad de utilizar estas propiedades */

¿Qué es la estructura en lenguaje C?

Diseñado para almacenar varios tipos de datos. Por ejemplo, para crear un directorio de registro, necesita tener una lista con los siguientes parámetros:

  • fecha de publicación;
  • Número de emisión;
  • Nombre;
  • precio.

Se podrían utilizar matrices para resolver este problema.

Declaramos una matriz con fechas int fecha, números int número, nombres título char, costo int precio.

Accediendo al índice obtenemos la información requerida. La salida de información sobre el trabajo número 3 se ve así: cout<< “дата выпуска: ” date “, номер: ” number “, название: ” title “, стоимость: “ price).

La estructura facilita la escritura y se describe a continuación:

Vemos una de las principales ventajas: existen diferentes tipos de variables. El programador no sólo ahorra tiempo: simplifica el código y, en el futuro, le resultará mucho más fácil trabajar.

Anuncio

Las estructuras en C juegan un papel muy importante: combinar datos de varios tipos.

Primero debe especificar el nombre de la estructura y las propiedades.

Estructura es una palabra clave, comienza la declaración, nombre es el nombre, tipo es el tipo de datos, miembro es el nombre del elemento.

Se declara así:

nombre nombre2, donde nombre es el nombre especificado al crear la estructura y nombre2 es el nombre de la variable.

Puede declarar variables en la etapa de creación.

El primer y segundo ejemplo son equivalentes entre sí.

Si es necesario declarar varias variables, se enumeran separadas por comas.

) nombre2, nombre3, nombre4.

Inicialización

Después de la declaración, se debe inicializar la estructura en C.

nombre2.miembro=”a”;

La inicialización puede ocurrir en el momento de la creación.

miembro char = “a”;

Una estructura tiene la misma sintaxis que una clase. Tienen casi el mismo comportamiento y capacidades. Todo lo que está en el cuerpo de una clase, de forma predeterminada, no está disponible para que lo utilicen otros objetos.

Para una estructura, todo es al revés: todos los campos y métodos son públicos. Puede configurar manualmente el modificador de acceso privado y así abrir el acceso a otras funciones o clases.

Las matrices son muchos componentes del mismo tipo. Están ubicados uno al lado del otro, a cada uno de ellos se accede mediante un índice numérico. Hay matrices unidimensionales, bidimensionales y tridimensionales.

Unidimensional tiene solo una fila y un número n-e de elementos. El anuncio se ve así:

Una serie de estructuras en C se declara así:

En este ejemplo, creamos MyStruct con un elemento entero llamado "a". Declaramos la variable obj1: es una matriz que consta de 10 elementos.

Al declarar varias matrices del mismo tipo, se utiliza MyStruct obj1, obj2, la inicialización se produce durante la declaración. Se parece a esto:

Crear una matriz de estructuras con asignación de memoria dinámica tiene exactamente el mismo aspecto que crear una matriz dinámica simple. Para ello se utiliza un puntero a una estructura C.

Un puntero es una variable que no contiene un valor, pero apunta a una variable que tiene algún valor. En consecuencia, el puntero contiene la dirección de esta variable a la que se hace referencia. Por ejemplo, ptr = &var1 significa que a una variable con un signo comercial se le asigna solo la dirección de la variable, pero no el valor en sí. Ahora todos los valores de var1 están disponibles a través de la variable de puntero ptr.

La operación * se refiere al contenido de la celda a la que apunta la variable después de este carácter. Por ejemplo, *ptr significa que contiene valores tomados de la celda con la dirección ptr.

Para asignar memoria para variables dinámicas, utilice la nueva operación.

Tenemos

Seleccionamos una sección de memoria, ingresamos un valor determinado MyStruct * point = new MyStruct;

Para eliminar variables dinámicas utilizamos la operación de eliminación. Para liberar espacio, ingrese eliminar p;

Acceso

Todos los elementos son públicos por defecto, por lo que otras clases pueden usarlos. Para establecer o cambiar algunos valores, primero debe acceder al elemento y solo luego realizar las acciones apropiadas.

Cree myStruct con el nombre de la variable b.

estructura miEstructura (

Fio de contacto:

y establecer un valor arbitrario. Por ejemplo, b.fio = "Ivanov".

Consideremos este ejemplo.

estructura miEstructura (

("Ivánov", 456756),

("Petrov", 632345)

En este ejemplo, tenemos una serie de estructuras con cadenas y números. Para mostrar el apellido Ivanov, utilice lo siguiente:

corte<< myStruct tel.fio;

Cuando queremos obtener el valor 456756, ejecutamos cout<< myStruct tel.num.

Estructura y funciones

Se puede utilizar como argumento de función en una estructura C.

estructura miEstructura (

Tenemos una variable de valor, una cadena de texto de 100 caracteres. Cree una variable de menú de tipo myStruct: menú myStruct. En el siguiente ejemplo, la función toma un puntero a una estructura como argumento y el cuerpo de la función sin nombre inicializa estas variables.

elemento anulado (menú myStruct)

sprintf(menu.text,"Un elemento");

Conclusión

Una estructura es un conjunto, como una matriz, pero todos los elementos pueden ser de diferentes tipos. Muy similar a una clase, pero se diferencia en que las propiedades predeterminadas están disponibles para que las utilicen otras clases, es decir, tienen el especificador público.

Se crea utilizando la palabra clave struct y las propiedades se especifican entre llaves ().

El anuncio se produce en la etapa de creación o después.

Hasta ahora hemos considerado una estructura compleja (tipo complejo): una matriz; Una de las principales propiedades de una matriz es la uniformidad de sus componentes. Muchas tareas de información y lógicas están asociadas con el procesamiento de documentos que contienen información de diversos tipos (numérica, simbólica, etc.). Ejemplos de tales documentos: nóminas (apellidos y nombres - información simbólica, cantidades monetarias - numéricas), tarjetas de pacientes en la clínica, información de la biblioteca. Para programar algoritmos para procesar dicha información, es necesario tener un tipo complejo que combine diferentes tipos de componentes. Este tipo es estructura en C (en notación Pascal).

Una variable de estructura, o simplemente estructura, consta de varias variables (llamadas campos), posiblemente de diferentes tipos.

Estructura

escriba "estructura" (plantilla)

variable de tipo "estructura""

Descripción de la plantilla:

Descripción de la variable de estructura.

estructura typedef( Tipo1 Lista1Nombres de campo;

estructura Nombre de plantilla Nombre de variable

Type2List2FieldNames;

Escriba N ListNFieldNames;

llave estructura no se necesita palabra

) Nombre de plantilla

usar definición de tipo

o estructura Nombre de plantilla

( Tipo1 Lista1Nombres de campo;¦

Type2List2FieldNames;

Escriba N ListNFieldNames;

estructura typedef (autor char; título char;/*descripción*/

año entero; precio flotante) LIBRO; /*plantilla de LIBRO*/

/*o puedes describir el mismo patrón así:

estructura LIBRO (autor char; título char;

año entero; precio flotante);*/

struct BOOK b;/*descripción de la variable estructural b*/

La memoria ocupada por la estructura es igual a la suma de los volúmenes de memoria de los campos (si excluimos de la consideración las características relacionadas con la alineación). En cualquier caso, la operación sizeof() se puede utilizar para determinar el tamaño de la memoria de una estructura. El patrón BOOC, por ejemplo, describe una estructura con un tamaño de memoria de 70.

Accediendo a un campo de una variable de estructura:

NombreEstructura.NombreCampo o DirecciónEstructura->Nombre del campo

. (punto) y -> son operaciones, respectivamente, de selección directa e indirecta de un componente de una variable estructurada.

Por ejemplo,

estructura LIBRO a,*pnta=...

a.autor="Byron"; pnta->autor="Byron"; /*operadores equivalentes*/

Ejemplo. La tarea del ejemplo 2 del párrafo 3.1.4 del programa siguiente se realiza utilizando estructuras (no cadenas).

#incluir

#incluir

#incluir

( /*estructura de la información sobre juguetes*/

estructura typedef (int nu;/*número*/

nombre de char;/*nombre*/

int minage,maxage;/*min. y máx. edad del niño*/

doble frotamiento /*costo*/;)JUGUETES;

JUGUETES juguete;/*variable de tipo de registroJUGUETES */

doble máximo; /*coste máximo*/

char namemax;/*nombre del constructor más caro*/

int n /*número de juguetes*/,i/*número de juguete*/;

puts("Ingrese el número de juguetes");

para (i=0; yo

/*en el bucle ingresamos información sobre los juguetes y verificamos las condiciones*/

descarga(stdin); /*borrar el buffer del dispositivo de entrada después de scanf */

printf(" Ingrese información sobre el juguete con el número %2d\n",toy.nu);

pone("nombre");

puts("edad y costo mínimo y máximo");

scanf("%d%d%lf",&toy.minage,&toy.maxage,&toy.rub);

if ((strstr(juguete.nombre,"constructor")!=NULL ||

strstr(nombre.juguete,"Constructor")!=NULL) &&

(juguete.maxage<= 7) &&

(juguete.rub>max))

strcpy(nombremax,juguete.nombre);

puts("No existen juguetes de construcción para niños menores de siete años");

( printf("El set de construcción más caro para niños menores de siete años\n");

printf(" %s cuesta %8,0f rublos\n",namemax,max);

Hay otro tipo complejo en C, cuya descripción es formalmente similar a una estructura. Este es el tipo (y variable) asociación.

Una unión es una variable que contiene campos de diferentes tipos colocados en la misma ubicación de memoria. Esencialmente, la concatenación proporciona una manera de interpretar los contenidos de la memoria de manera diferente. La descripción de una plantilla de unión (tipo) y una variable de este tipo se realiza de la misma manera que para una estructura, solo que en lugar de la palabra clave estructura usado unión. El tamaño de la memoria ocupada por la unión es igual al máximo de los tamaños de campo.

Una estructura es un almacenamiento conveniente para datos heterogéneos que desea combinar. Por ejemplo, puede crear una estructura que describa los parámetros de su dispositivo: configuración de red, tiempo de suspensión, su identificador, etc., como algún tipo de línea de bienvenida y estado del LED. Dado que todos los parámetros se almacenarán en un solo lugar, siempre estarán visibles y los IDE normales le solicitarán los campos de la estructura al acceder a ellos. También veremos el almacenamiento y restauración de estructuras de un archivo, así como su transmisión a través de la red.

Declarando una estructura como esta:

Estructura (uint32_t ID; char IP; uint16_t tiempo de espera; bool led; char text;) params;

¿Cómo funciona esto?

En C, la sintaxis es bastante conveniente, en el sentido de que muchas cosas se escriben como “variable de tipo_datos”, comenzando con “int i” y terminando con “void main() ()”. Entonces, aquí, la palabra clave struct comienza la declaración de la estructura, y todo el código "struct (...)" simplemente define un nuevo tipo. En consecuencia, params es una variable preparada (una instancia de un tipo) que se puede utilizar. Dentro de las llaves, se enumeran todos los campos de la estructura, a los que luego se podrá acceder de esta manera: params.ID o params.IP. La longitud de los campos debe ser fija, por lo que no se pueden utilizar cadenas del formulario *texto, solo matrices del formulario texto.

Se podría haber hecho de manera un poco diferente: declarar solo el tipo y crear una variable más tarde. Para hacer esto usaríamos la palabra clave typedef y la escribiríamos así:

Estructura Typedef (uint32_t ID; char IP; uint16_t tiempo de espera; bool led; char text;) params_struct; parámetros params_struct;

Esto permite dejar todas las declaraciones de tipos estructurales en un archivo separado (encabezado) y, en el archivo principal, simplemente usar tipos estructurales ya preparados para declarar estructuras directamente en su lugar.

Por supuesto, en ambas opciones puedes declarar tantas instancias de estructuras como quieras, o crear una matriz de ellas:

Estructura (uint32_t ID; char IP; uint16_t tiempo de espera; bool led; char text;) params1, params2, params;

La opción de matriz es especialmente conveniente para un servidor en una topología de red cliente-servidor: cada cliente almacena sus propios parámetros en una estructura y el dispositivo maestro contiene una tabla de parámetros de todos los clientes en forma de una matriz de estructuras.

En principio no hay nada complicado en las estructuras, y con el tema de servidores y clientes poco a poco nos acercamos a un tema más interesante:

Almacenamiento, transferencia y sincronización de estructuras.

Para muchos será una sorpresa que estas estructuras se almacenen en la memoria como una lista plana; todos los campos de la estructura simplemente se suceden unos a otros en la memoria. Por lo tanto, es posible tratar esta estructura como una simple matriz de bytes. Comprobemos y creemos una matriz "encima" de esta estructura.

Obtenemos el desplazamiento inicial así:

Carácter *Bytes =

Declaramos un puntero char y le pusimos la dirección de parámetros. Ahora Bytes apunta al primer byte de la estructura, y con la lectura secuencial leeremos todo el byte de la estructura. ¿Pero cuántos bytes hay que leer? Para ello, considere dos funciones interesantes.

tamaño de y compensación de

Estas ni siquiera son funciones, sino macros integradas en el lenguaje C. Empecemos por uno más sencillo, tamaño de.

El compilador reemplaza todas las entradas del formulario sizeof X con el valor de longitud X. X puede ser un tipo o una instancia de un tipo, es decir en nuestro caso, podemos sustituir el tamaño de tanto el tipo de estructura (si lo configuramos usando typedef) como la variable de estructura misma de esta manera: sizeof params_struct o sizeof params. Recorrerá todos los campos de la estructura, sumará sus longitudes y devolverá la suma, que será la longitud de la estructura.

compensación de- una macro real que toma dos parámetros (la estructura _s_ y el campo _m_) y devuelve la posición de este campo en la estructura, su desplazamiento con respecto al comienzo de la estructura. Esta macro parece muy simple:

Desplazamiento de(s, m) (size_t)&(((s *)0)-›m).

¿Cómo funciona?

  1. toma el numero 0
  2. Convirtámoslo al tipo “puntero a estructura s”: (s*)0
  3. Accedemos al campo m desde esta estructura: ((s*)0)->m
  4. Calculamos su dirección: &(((s*)0)->m)
  5. Convierta la dirección a un número entero: (size_t)&(((s*)0)->m)

La magia está precisamente en el primer paso, en el que tomamos 0. Gracias a esto, en el cuarto paso, la dirección absoluta del campo, calculada por el compilador, se cuenta en relación con el comienzo de la estructura: ponemos la estructura en la dirección 0. Por lo tanto, después de ejecutar esta macro, en realidad tenemos campos de desplazamiento relativos al comienzo de la estructura. Está claro que esta macro determinará correctamente los desplazamientos incluso en estructuras complejas y anidadas.

Aquí debemos hacer una pequeña digresión. El hecho es que consideré el caso más simple, cuando los campos se empaquetan exactamente uno detrás del otro. Existen otros métodos de embalaje llamados "aplanamiento". Por ejemplo, puede asignar a cada campo una "ranura" que sea múltiplo de 4 bytes u 8 bytes. Entonces incluso char ocupará 8 bytes y tamaño total la estructura crecerá y todos los desplazamientos cambiarán y se convertirán en un múltiplo de la alineación. Esto es útil al programar una computadora, porque debido a la granulación de la RAM, el procesador puede recuperar datos alineados de la memoria mucho más rápido y requiere menos operaciones.

Trabajar con una matriz a partir de una estructura

Bien, ahora podemos representar cualquier estructura como una matriz de bytes y viceversa. ¿Entendiste el punto? Ahora tenemos la misma área de memoria con los roles "estructura" y "matriz". Cambiamos algo en la estructura - la matriz cambia, cambiamos la matriz - la estructura cambia.

¡Esta es la esencia del proceso! No tenemos una matriz separada porque la estructura en sí ya es una matriz y solo estamos accediendo a la memoria. diferentes metodos. Y no tenemos ningún bucle de copia por campos o bytes; este bucle estará inmediatamente en la función de transferencia.

Ahora sólo queda aprender a trabajar cómodamente con todo ello.

Estructura de almacenamiento y transmisión.

para crear copia de archivo estructura, para su transmisión a través de la red o para almacenarla en un lugar seguro: proporcione la dirección de esta matriz a su función de transferencia de datos. Por ejemplo, mi función para escribir una matriz de datos en EEPROM se ve así: I2C_burst_write (I2Cx, HW_address, addr, n_data, *data). Sólo necesitas pasar sizeof params en lugar de n_data, y ¶ms en lugar de *data:

I2C_burst_write (I2Cx, dirección_HW, dirección, tamaño de parámetros y parámetros)

Las funciones de transferencia de datos de red suelen verse así. Pase ¶ms como datos y sizeof params como longitud de los datos.

Recepción y restauración de la estructura.

Todo es exactamente igual. Mi función para leer una matriz desde EEPROM: I2C_burst_read (I2Cx, HW_address, addr, n_data, *data). n_data = tamaño de parámetros, *datos = &parámetros:

I2C_burst_read (I2Cx, dirección_HW, dirección, tamaño de parámetros y parámetros)

No olvides que escribes inmediatamente los bytes recibidos directamente en la estructura. Si la transferencia es lenta o poco confiable, tiene sentido escribir los datos en un búfer temporal y, después de verificarlos, transferirlos a la estructura a través de

Memcpy(¶ms, &temp_buffer, tamaño de parámetros).

Al implementar estos métodos, implementaremos sincronización conveniente dos estructuras ubicadas en diferentes computadoras: el microcontrolador cliente puede estar al menos en el otro lado globo desde el servidor, pero transferir estructuras seguirá siendo igual de fácil.

Almacenamiento/recuperación de campos individuales

¿Y por qué dedicamos tanto tiempo a analizar la compensación macroeconómica? Es muy conveniente usarlo para leer y escribir campos individuales de una estructura, por ejemplo así:

I2C_burst_write (I2Cx, dirección_HW, dirección + desplazamiento de (params, IP), tamaño de parámetros.IP, y parámetros.IP) I2C_burst_read (I2Cx, dirección_HW, dirección + desplazamiento de (params, IP), tamaño de parámetros.IP, y parámetros.IP)

Bueno, en general, sería bueno crear macros contenedoras convenientes para este propósito.

#definir tienda (estructura, campo) I2C_burst_write (I2Cx, dirección_HW, dirección + desplazamiento de (estructura, campo), tamaño de (estructura.campo), &(estructura.campo)) #definir carga (estructura, campo) I2C_burst_read (I2Cx, dirección_HW , dirección + desplazamiento de (estructura, campo), tamaño de (estructura.campo), &(estructura.campo))




Arriba