Union
Estructura de archivos:
📁 03_Union
└── 📁 Union-NN
├── 📄 main.c
└── 📄 Makefile
Ejercicios:
Union 01
Makefile
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra -pedantic
PROG = main
OBJ = main.o
$(PROG): $(OBJ)
$(CC) $(OBJ) -o $(PROG)
$(OBJ): main.c
$(CC) $(CFLAGS) -c main.c
.PHONY: clean
clean:
del $(OBJ) $(PROG).exe
Código:
// gcc -std=c11 -Wall -Wextra -pedantic main.c -o main
#include <stdio.h>
/* Declaracion de estructura
* Cada miembro posee su propia region en memoria.
* Los campos pueden utilizarse simultaneamente.
*/
struct Beta
{
int A;
char B;
};
/* Declaracion de union
* Todos los miembros comparten la misma region de memoria.
* Solo uno de los campos puede considerarse valido a la vez.
*/
union Alfa
{
int A;
char B;
};
int main(void)
{
/* Declaracion de variables tipo union Alfa y struct Beta*/
union Alfa Ua;
struct Beta Sb;
/* Asignaciones de los campos de la estructura */
Sb.A = 297;
Sb.B = 'K';
/* Asignacion de los campos de la union,
* como comparten la memoria, al declararse B, deja de ser valido A,
* Tras esto el unico campo valido es B,
* Leer Ua.A luego de esta linea implicaria comportamiento indefinido (UB). */
Ua.A = 297;
Ua.B = 'K';
return 0;
}
Union 02
Makefile
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra -pedantic
PROG = main
OBJ = main.o
$(PROG): $(OBJ)
$(CC) $(OBJ) -o $(PROG)
$(OBJ): main.c
$(CC) $(CFLAGS) -c main.c
.PHONY: clean
clean:
del $(OBJ) $(PROG).exe
Código:
// gcc -std=c11 -Wall -Wextra -pedantic main.c -o main
#include <stdio.h>
/* Declaracion de union
* Al compartir la misma region en memoria
* La dimension de la union sera la del miembro mas grande.
*/
union Gamma
{
int A;
char B[4];
float C;
};
int main(void)
{
/* Declaracion de variable de tipo union Gamma*/
union Gamma Ug;
/* Asignacion de campos de la union */
Ug.C = 27.892E-5; // A partir de aqui, el unico miembro valido es C.
Ug.B[2]++; // El valor de C deja de ser valido por el incremento de B.
/* El valor valor de B deja de ser valido,
* A tambien comparte memoria con los otros miembros.
* Esta operacion interpreta los mismos bytes ahora como si fueran un int.
* Esto constituye comportamiento indefinido segun el estandar,
* ya que se esta leyendo un miembro distinto al ultimo escrito.
* El resultado depende de la arquitectura,
* representacion interna (IEEE 754), y endianness del sistema.
*/
Ug.A *= 2;
return 0;
}
Union 03
Makefile
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra -pedantic
PROG = main
OBJ = main.o
$(PROG): $(OBJ)
$(CC) $(OBJ) -o $(PROG)
$(OBJ): main.c
$(CC) $(CFLAGS) -c main.c
.PHONY: clean
clean:
del $(OBJ) $(PROG).exe
Código:
// gcc -std=c11 -Wall -Wextra -pedantic main.c -o main
#include <stdio.h>
#include <conio.h> // No pertenece al estandar ISO C. clrscr() no esta disponible en GCC/MinGW.
#include <stdlib.h> // system("cls"); al no poder compilar con clrscr()
/* Declaracion de la union
* En este caso probablemente 10 bytes por y[10] sera la dimension minima,
* aunque puede haber padding por alineacion.
* Padding por alineacion:
* - Es memoria extra que el compilador agrega automaticamente
* para que los datos respeten los requisitos de alineacion de la arquitectura
* En una struct:
* - Puede haber padding entre miembros.
* - Puede haber padding al final.
*
* En una union:
* - No hay padding entre miembros (todos comienzan en la misma direccion)
* - Puede haber padding al final para que la dimension total
* cumpla con la alineacion mas estricta de sus miembros.
*/
union alfa
{
int x;
char y[10];
float z;
};
/* Prototipos de funciones */
int suma(int, int);
int ingreso(void);
int main(void)
{
/* Declaracion de variables tipo union alfa*/
union alfa A, B;
/* No estandar. Solo disponible en algunos compiladores. No es portable. Puede usarse system("cls") */
clrscr(); // Comentar y usar system("cls") de stdlib.h
//system("cls"); // Descomentar y comentar la linea previa para compilar
/* Se almacenan enteros en el miembro x, devueltos por la llamada a la funcion */
A.x = ingreso();
B.x = ingreso();
/* Mostrar la suma entre los miembros x como cuenta */
printf("\n%d + %d = ", A.x, B.x);
/* Asignar al miembro x de A la suma entre los miembros x de A y B */
A.x = suma(A.x, B.x);
/* Mostrar el resultado de la suma */
printf("%d\n", A.x);
/* fflush(stdin) es comportamiento indefinido segun el estandar.
* fflush solo esta definido para streams de salida fflush(stdout)
* Algunos compiladores lo aceptan como extension, pero no es portable.
*/
fflush(stdin);
/* gets() fue eliminada del estandar C11 (El cual se esta usando para compilar)
* Es insegura porque no controla la dimension del buffer.
* Puede provocar desbordamiento (buffer overflow). */
gets(A.y); // Se reemplazo con fgets(buffer, sizeof(buffer), stdin)
//fgets(A.y, sizeof(A.y), stdin); // Comentar la linea anterior y descomentar esta para que el programa compile
/* Se accede al tercer caracter del vector de la union.
* No se verifica que el usuario haya ingresado al menos 3 caracteres,
* Lo que podria provocar acceso a memoria no inicializada.
* Esto sobreescribe la memoria previamente usada por x.
* A partir de aca, x deja de ser valido. */
if (A.y[2] > 'F')
{
/* Se escribe el campo z, esto vuelve a sobreescribir
* la memoria compartida. Ahora el unico miembro valido es z. */
A.z = 3.14;
/* Se lee un float en B.z
* B.x deja de ser valido luego de esta operacion. */
scanf("%f", &B.z);
/* Se muestra como perimetro el producto de los miembros z */
printf("\n\nPerimetro = %f", A.z * B.z);
}
return 0;
}
/* Declaracion de funcion ingreso:
* Lee un entero y lo devuelve*/
int ingreso(void)
{
/* Declaracion de variable local no inicializada */
int a;
/* Se lee el valor de la variable */
scanf("%d", &a);
/* Se retorna el valor de la variable */
return (a);
}
/* Declaracion de funcion suma:
* Recibe dos enteros.
* Devuelve la suma de los dos enteros.
*/
int suma(int a, int b)
{
/* Declaracion de variable local no inicializada */
int c;
/* Se asigna a la variable la suma de los argumentos ingresados al llamar a la funcion */
c = a + b;
/* Se devuelve la variable con el resultado de la suma */
return (c);
}
Union 04
Makefile
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra -pedantic
PROG = main
OBJ = main.o
$(PROG): $(OBJ)
$(CC) $(OBJ) -o $(PROG)
$(OBJ): main.c
$(CC) $(CFLAGS) -c main.c
.PHONY: clean
clean:
del $(OBJ) $(PROG).exe
Código:
// gcc -std=c11 -Wall -Wextra -pedantic main.c -o main
#include <stdio.h>
#include <conio.h> // getche() y crlscr() esta ultima no viene en GCC/MinGW
#include <math.h> // No se usa nada de la biblioteca, podria borrarse.
/* Para reemplazar a clrscr() con system("cls");*/
#include <stdlib.h> // system("cls");
/*
Se define una union con dos campos uno "int" y el otro "char"
*/
union alfa
{
int x;
char y;
};
/*
Se declaran los prototipos de las funciones
*/
union alfa ingreso(char);
void imprime(union alfa, char);
int main(void)
{
/* Se declaran las variables */
union alfa A;
char c;
do
{
/* Menu de opciones */
//clrscr(); // No existe en GCC/MinGW reemplazar con system("cls");
system("cls"); // Comentar la linea anterior y descomentar esta linea para compilar
printf("\n\n\t\t\tIngrese una opcion");
printf("\n\n (C) ingreso de un caracter");
printf("\n\n (E) ingreso de un entero \n\n");
// Almacena en la variable c el ingreso del usuario, si apreto ENTER queda un \n en el buffer. Puede provocar comportamiento raro en la siguiente lectura
c = getche(); // Se puede reemplazar con getchar() que pertenece al estandar, pero requiere ese ENTER.
printf("\n\n");
/* Se invoca a la funcion "ingreso" */
A = ingreso(c);
/* Se invoca a la funcion "imprime" */
imprime(A, c);
printf("\n\n\nDesea ingresar otro valor (S/N): ");
c = getche();
}
while((c == 's') || (c == 'S'));
return 0;
}
/* Se define a la funcion "ingreso" *
* Devuelde una union de tipo "alfa" *
* Recibe un "char" */
union alfa ingreso(char b)
{
union alfa C;
printf("Ingrese un ");
if ((b == 'c') || (b == 'C'))
{
printf(" caracter ");
C.y = getche();
}
else
{
printf(" entero ");
scanf("%d", &C.x);
}
printf("\n\n");
/* Devuelve el valor de la union */
return (C);
}
/* Se define la funcion "imprime" *
* Recibe una union de tipo alfa llamada "B" *
* Y un char denominado "c", devuelve "void" */
void imprime(union alfa B, char c)
{
if ((c == 'c') || (c == 'C'))
printf("\n\nUsted ingreso el caracter %c", B.y);
else
printf("\n\nUsted ingreso el entero %d", B.x);
}
Union 05
Makefile
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra -pedantic
PROG = main
OBJ = main.o
$(PROG): $(OBJ)
$(CC) $(OBJ) -o $(PROG)
$(OBJ): main.c
$(CC) $(CFLAGS) -c main.c
.PHONY: clean
clean:
del $(OBJ) $(PROG).exe
Código:
// gcc -std=c11 -Wall -Wextra -pedantic main.c -o main
//////////// Es Union-04 sin comentarios /////////////
#include <stdio.h>
#include <conio.h>// No pertenece al estandar ISO C. clrscr() no esta disponible en GCC/MinGW.
#include <stdlib.h> // system("cls"); al no poder compilar con clrscr()
#include <math.h>
union alfa
{
int x;
char y;
};
union alfa ingreso(char);
void imprime(union alfa, char);
int main(void)
{
union alfa A;
char c;
do
{
clrscr();
printf("\n\n\t\t\tIngrese una opcion ");
printf("\n\n (C) ingreso de un caracter");
printf("\n\n (E) ingreso de un entero ");
c = getche();
printf("\n\n");
A = ingreso(c);
imprime(A, c);
printf("\n\nDesea ingresar otro valor (S/N) ");
c = getche();
}
while((c == 's') || (c == 'S'));
return 0;
}
union alfa ingreso(char b)
{
union alfa C;
printf("Ingrese un ");
if ((b == 'c') || (b == 'C'))
{
printf(" caracter ");
c.y = getche();
}
else
{
printf(" entero ");
scanf("%d", &C.x);
}
printf("\n\n");
return (C);
}
void imprime(union alfa B, char c)
{
if ((c == 'c') || (c == 'C'))
{
printf("\n\nUsted ingreso el caracter %c", B.y);
}
else
{
printf("\n\nUsted ingreso el entero %d", B.x);
}
}
Union 06
Makefile
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra -pedantic
PROG = main
OBJ = main.o
$(PROG): $(OBJ)
$(CC) $(OBJ) -o $(PROG)
$(OBJ): main.c
$(CC) $(CFLAGS) -c main.c
.PHONY: clean
clean:
del $(OBJ) $(PROG).exe
Código:
// gcc -std=c11 -Wall -Wextra -pedantic main.c -o main
#include <stdio.h>
#include <conio.h> // Se usa getche() puede ser reemplazado por getchar() que pertenece al estandar, clrscr() no existe en GCC/MinGW se reemplaza agregando stdlib.h y usando system("cls")
/* Agregado para reemplazar clrscr() */
#include <stdlib.h> // Se usa system("cls")
/* MAX determina el largo maximo del vector */
#define MAX 100
/* Declaracion de estructuras */
struct coupe
{
char nro_cil;
int cilind, veloc_max;
char marchas;
};
struct sedan
{
char puertas, color[10], familiar;
};
struct cuotas
{
int cant;
float val;
};
/* Declaracion union de estructuras */
union clase
{
struct coupe dat;
struct sedan dat1;
};
/* Declaracion union que contiene tipo primitivo y estructura */
union fina
{
float contado;
struct cuotas pagos;
};
/* Declaracion de estructura que contiene union */
struct autos
{
char marca[10];
int modelo;
char tipo;
union clase caract;
char vendido, cont;
union fina valor;
};
/* Se declaran los prototipos de las funciones */
int ingreso(struct autos stock[], int);
void listado(struct autos stock[], int);
int main(void)
{
/* Se declaran las variables a utilizar */
struct autos stock[MAX];
int i, j = 0;
/* Impresion del menu de opciones */
do
{
clrscr(); // No existe en GCC/MinGW, reemplazar por system("cls") de stdlib.h
//system("cls");
/* Menu principal */
printf("\n\n\t\t\tMenu principal");
printf("\n\n1 - Ingreso de datos");
printf("\n\n2 - Listado de datos");
printf("\n\n3 - Salir");
printf("\n\nIngrese una opcion (1 - 3): ");
/* Leer el valor intriducido */
scanf("%d", &i);
/* Caso 1: llamar a la funcion ingreso con los argumentos vector de estructura stock y la variable entera j y almacenar lo que devuelve en j
* Caso 2: llamar a la funcion listado con los argumentos vector de estructura stock y la variable entera j.
*/
switch(i)
{
case 1:
j = ingreso(stock, j);
break;
case 2:
listado(stock, j);
}
}
while(i != 3); // Mientras la variable sea distinta de 3.
return 0;
}
/* Funcion para permitir el ingreso de los datos */
int ingreso(struct autos stock[], int j)
{
/* Declaracion de las variables a utilizar para *
* realizar el ingreso de los valores de tipo *
* "char" con formato numerico y para poder *
* ingresar los valores de tipo "float" */
int i;
float f;
/* Verifica que no se exceda el maximo del vector */
if (j == MAX)
return (j);
/* Comienzo del ingreso de los datos */
do
{
clrscr(); // No existe en GCC/MinGW, reemplazar por system("cls") de stdlib.h
//system("cls");
printf("\n\t\t\tINGRESO DE DATOS");
printf("\n\n\tMarca: ");
fflush(stdin); // Produce comportamiento indefinido, puede ser remplazaodo por las 2 siguientes lineas
//int basura;
//while ((basura = getchar()) != '\n' && basura != EOF);
gets(stock[j].marca); // Eliminado en C11, reemplazar con fgets(), comentar esta linea y descomentar la siguiente
//fgets(stock[j].marca, sizeof(stock[j].marca), stdin);
printf("\n\n\tModelo: ");
scanf("%d", &stock[j].modelo);
fflush(stdin); // Produce comportamiento indefinido, puede ser remplazaodo por la siguiente linea
//while ((basura = getchar()) != '\n' && basura != EOF);
printf("\tTipo (C - S): ");
/* Ingreso de datos selectivo segun el tipo elegido */
do
{
stock[j].tipo = getche(); // Puede ser reemplazada con getchar() pero requiere ENTER
if (stock[j].tipo == 'C' || stock[j].tipo == 'c')
{
printf("\n\tNumero de cilindros: ");
/* Utilizacion de una variable auxiliar para *
* ingresar un valor con formato numerico en *
* una variable de tipo "char" */
scanf("%d", &i);
/* Almacenar en struct autos => union clase caract => struct coupe dat => char nro_cil el valor almacenado en la variable entera i */
stock[j].caract.dat.nro_cil = i;
printf("\tCilindrada: ");
scanf("%d", &stock[j].caract.dat.cilind);
printf("\tVelocidad maxima: ");
scanf("%d", &stock[j].caract.dat.veloc_max);
printf("\tCantidad de marchas: ");
scanf("%d", &i); // Se sobreescribe el valor de la variable entera i
/* Almacenar en struct autos => union clase caract => struct coupe dat => char marchas el valor almacenado en la variable entera i */
stock[j].caract.dat.marchas = i;
}
if (stock[j].tipo == 'S' || stock[j].tipo == 's')
{
printf("\n\tCantidad de puertas: ");
scanf("%d", &i); // Se sobreescribe el valor de la variable entera i
/* Almacenar en struct autos => union clase caract => struct sedan dat1 => char puertas el valor almacenado en la variable entera i */
stock[j].caract.dat1.puertas = i;
fflush(stdin); // Produce comportamiento indefinido, puede ser remplazaodo por la siguiente linea
//while ((basura = getchar()) != '\n' && basura != EOF);
printf("\tColor: ");
gets(stock[j].caract.dat1.color); // Eliminado en C11, reemplazar con fgets(), comentar esta linea y descomentar la siguiente
//fgets(stock[j].caract.dat1.color, sizeof(stock[j].caract.dat1.color), stdin);
printf("\tFamiliar (S/N): ");
stock[j].caract.dat1.familiar = getche(); // Puede ser reemplazada con getchar() pero requiere ENTER
printf("\n");
}
} /* Mientras que tipo sea uno de los caracartere C, c, S, s el programa seguira */
while(!(stock[j].tipo != 'C' || stock[j].tipo != 'c' || stock[j].tipo != 'S' || stock[j].tipo != 's')); // Cambiada la logica de !(tipo != caracter || tipo != caracter) a (tipo != caracter && tipo != caracter) para que funcione
//while(stock[j].tipo != 'C' && stock[j].tipo != 'c' && stock[j].tipo != 'S' && stock[j].tipo != 's');
printf("\tVendido (S/N): ");
/* Ingreso selectivo de los datos de venta */
do
{
stock[j].vendido = getche(); // Puede ser reemplazada con getchar() pero requiere ENTER
if (stock[j].vendido == 'S' || stock[j].vendido == 's')
{
printf("\n\tVenta al contado (S/N): ");
do
{
stock[j].cont = getche(); // Puede ser reemplazada con getchar() pero requiere ENTER
if (stock[j].cont == 'S' || stock[j].cont == 's')
{
printf("\n\tValor: ");
/* Utilizacion de una variable auxiliar *
* para permitir el ingreso de una variable *
* de tipo "float" en un vector de estructuras */
scanf("%f", &f);
/* Almacenar en struct autos => union fina valor => float contado el valor almacenado en la variable float f */
stock[j].valor.contado = f;
}
if (stock[j].cont == 'N' || stock[j].cont == 'n')
{
printf("\n\tNumero de cuotas: ");
scanf("%d", &stock[j].valor.pagos.cant);
printf("\tValor de la cuota: ");
scanf("%f", &f); // Se sobreescribe el valor de la variable float f
/* Almacenar en struct autos => union fina valor => struct cuotas pagos => float val el valor almacenado en la variable float f */
stock[j].valor.pagos.val = f;
}
} /* Mientras que cont sea uno de los caracartere S, s, N, n el programa seguira */
while(!(stock[j].cont != 'S' || stock[j].cont != 's' || stock[j].cont != 'N' || stock[j].cont != 'n')); // Cambiada la logica de !(tipo != caracter || tipo != caracter) a (tipo != caracter && tipo != caracter) para que funcione
//while(stock[j].cont != 'S' && stock[j].cont != 's' && stock[j].cont != 'N' && stock[j].cont != 'n');
}
/* En caso de no haberse producido la venta *
* Se inicializan las variables a cero */
if (stock[j].vendido == 'N' || stock[j].vendido == 'n')
{
stock[j].valor.pagos.cant = 0;
stock[j].valor.pagos.val = 0;
}
} /* Mientras que vendido sea uno de los caracartere S, s, N, n el programa seguira */
while(!(stock[j].vendido != 'S' || stock[j].vendido != 's' || stock[j].vendido != 'N' || stock[j].vendido != 'n')); // Cambiada la logica de !(tipo != caracter || tipo != caracter) a (tipo != caracter && tipo != caracter) para que funcione
//while(stock[j].vendido != 'S' && stock[j].vendido != 's' && stock[j].vendido != 'N' && stock[j].vendido != 'n');
printf("\n\tDesea ingresar otro vehiculo (S/N): ");
i = getche(); // Puede ser reemplazada con getchar() pero requiere ENTER
j++; // Contador
}
/* Se comprueba que no se exceda el largo maximo del vector *
* en el caso de que se quieran agregar mas dato que los permitidos */
while((i == 'S' || i == 's') && j < MAX);
/* Se retorna el ultimo valor de la posicion maxima de los valores ingresados */
return (j);
}
/* Funcion que permite la visualizacion de los datos */
void listado(struct autos stock[], int i)
{
/* Declaracion de las variables a utilizar en la funcion */
int j, k;
/* Lazo para poder realizar la visualizacion de los datos *
* dentro del rango ingresado */
for (j = 0; j < i; j++)
{
clrscr(); // No existe en GCC/MinGW, reemplazar por system("cls") de stdlib.h
//system("cls");
/* Mostrar marca, modelo y tipo */
printf("\n\n\tMarca: %s", stock[j].marca);
printf("\tModelo: %d", stock[j].modelo);
printf("\tTipo: %c\n", stock[j].tipo);
/* Listado selectivo segun el tipo */
if (stock[j].tipo == 'C' || stock[j].tipo == 'c')
{
/* Mostrar numero de cilidros, cilindrada, velocidad maxima, cantidad de marchas para tipo Coupe */
printf("\n\tNumero de cilindros: %d", stock[j].caract.dat.nro_cil);
printf("\n\tCilindrada: %d", stock[j].caract.dat.cilind);
printf("\n\tVelocidad máxima : %d",stock[j].caract.dat.veloc_max);
printf("\n\tCantidad de marchas : %d",stock[j].caract.dat.marchas);
}
if(stock[j].tipo=='S'||stock[j].tipo=='s')
{
/* Mostrar cantidad de puertas, color, familiar para tipo Sedan */
printf("\n\tCantidad de puertas : %d",stock[j].caract.dat1.puertas);
printf("\n\tColor : %s",stock[j].caract.dat1.color);
printf("\n\tFamiliar : %c",stock[j].caract.dat1.familiar);
}
/* Mostrar vendido */
printf("\n\n\tVendido : %c",stock[j].vendido);
/* Listado selectivo de los datos de venta */
if (stock[j].vendido == 'S' || stock[j].vendido == 's')
{
if (stock[j].cont == 'S' || stock[j].cont == 's')
{
printf("\n\tValor : %.2f", stock[j].valor.contado); // Mostrar valor de contado
}
if (stock[j].cont == 'N' || stock[j].cont == 'n')
{
printf("\n\tNumero de cuotas : %d", stock[j].valor.pagos.cant); // Mostrar numero de cuotas
printf("\tValor de la cuota : %.2f", stock[j].valor.pagos.val); // Mostrar valor de cada cuota
}
}
printf("\n\n\t\tDesea listar otro vehículo (S/N) ");
k = getche(); // Puede ser reemplazada con getchar() pero requiere ENTER
/* Seleccion que permite seguir visualizando o no *
* los datos del vector segun la eleccion del operador */
if (k == 'N' || k == 'n')
{
return;
}
}
}
Union 07
Makefile
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra -pedantic
PROG = main
OBJ = main.o
$(PROG): $(OBJ)
$(CC) $(OBJ) -o $(PROG)
$(OBJ): main.c
$(CC) $(CFLAGS) -c main.c
.PHONY: clean
clean:
del $(OBJ) $(PROG).exe
Código:
// gcc -std=c11 -Wall -Wextra -pedantic main.c -o main
///////////// Es Union-06 sin comentarios ///////////////////
#include <stdio.h>
#include <conio.h>
#define MAX 100
struct coupe
{
char nro_cil;
int cilind, veloc_max;
char marchas;
};
struct sedan
{
char puertas, color[10], familiar;
};
struct cuotas
{
int cant;
float val;
};
union clase
{
struct coupe dat;
struct sedan dat1;
};
union fina
{
float contado;
struct cuotas pagos;
};
struct autos
{
char marca[10];
int modelo;
char tipo;
union clase caract;
char vendido, cont;
union fina valor;
};
int ingreso(struct autos stock[], int);
void listado(struct autos stock[], int);
int main(void)
{
struct autos stock[MAX];
int i, j = 0;
do
{
clrscr();
printf("\n\t\t\t\tMenu principal");
printf("\n\t1 - Ingreso de datos");
printf("\n\t2 - Listado de datos");
printf("\n\t3 - Salir");
printf("\n\nIngrese una opción ( 1 - 3 ) ");
scanf("%d", &i);
switch(i)
{
case 1:
j = ingreso(stock, j);
break;
case 2:
listado(stock, j);
}
}
while (i != 3);
return 0;
}
int ingreso(struct autos stock[], int j)
{
int i;
float f;
if (j == MAX)
return(j);
do
{
clrscr();
printf("\n\t\t\tINGRESO DE DATOS");
printf("\n\n\tMarca : ");
fflush(stdin);
gets(stock[j].marca);
printf("\tModelo : ");
scanf("%d", &stock[j].modelo);
fflush(stdin);
printf("\tTipo (C-S) : ");
do
{
stock[j].tipo = getche();
if (stock[j].tipo == 'C' || stock[j].tipo == 'c')
{
printf("\n\tNumero de cilindros : ");
scanf("%d", &i);
stock[j].caract.dat.nro_cil = i;
printf("\tCilindrada : ");
scanf("%d", &stock[j].caract.dat.cilind);
printf("\tVelocidad máxima : ");
scanf("%d", &stock[j].caract.dat.veloc_max);
printf("\tCantidad de marchas : ");
scanf("%d", &i);
stock[j].caract.dat.marchas = i;
}
if (stock[j].tipo == 'S' || stock[j].tipo == 's')
{
printf("\n\tCantidad de puertas : ");
scanf("%d", &i);
stock[j].caract.dat1.puertas = i;
fflush(stdin);
printf("\tColor : ");
gets(stock[j].caract.dat1.color);
printf("\tFamiliar (S/N) : ");
stock[j].caract.dat1.familiar = getche();
printf("\n");
}
}
while (!(stock[j].tipo != 'C' || stock[j].tipo != 'c' || stock[j].tipo != 'S' || stock[j].tipo != 's'));
printf("\tVendido (S/N) : ");
do
{
stock[j].vendido = getche();
if (stock[j].vendido == 'S' || stock[j].vendido == 's')
{
printf("\n\tVenta al contado (S/N) : ");
do
{
stock[j].cont = getche();
if (stock[j].cont == 'S' || stock[j].cont == 's')
{
printf("\n\tValor : ");
scanf("%f", &f);
stock[j].valor.contado = f;
}
if (stock[j].cont == 'N' || stock[j].cont == 'n')
{
printf("\n\tNumero de cuotas : ");
scanf("%d", &stock[j].valor.pagos.cant);
printf("\tValor de la couta : ");
scanf("%f", &f);
stock[j].valor.pagos.val = f;
}
}
while (!(stock[j].cont != 'S' || stock[j].cont != 's' || stock[j].cont != 'N' || stock[j].cont != 'n'));
}
if (stock[j].vendido == 'N' || stock[j].vendido == 'n')
{
stock[j].valor.pagos.cant = 0;
stock[j].valor.pagos.val = 0;
}
}
while (!(stock[j].vendido! = 'S' || stock[j].vendido != 's' || stock[j].vendido != 'N' || stock[j].vendido != 'n'));
printf("\n\t\tDesea ingresar otro vehículo (S/N) ");
i = getche();
j++;
}
while ((i == 'S' || i == 's') && j < MAX);
return(j);
}
void listado(struct autos stock[], int i)
{
int j, k;
for (j = 0; j < i; j++)
{
clrscr();
printf("\n\n\tMarca : %s", stock[j].marca);
printf("\tModelo : %d", stock[j].modelo);
printf("\tTipo : %c\n", stock[j].tipo);
if (stock[j].tipo == 'C' || stock[j].tipo == 'c')
{
printf("\n\tNumero de cilindros : %d", stock[j].caract.dat.nro_cil);
printf("\n\tCilindrada : %d", stock[j].caract.dat.cilind);
printf("\n\tVelocidad máxima : %d", stock[j].caract.dat.veloc_max);
printf("\n\tCantidad de marchas : %d", stock[j].caract.dat.marchas);
}
if (stock[j].tipo == 'S' || stock[j].tipo == 's')
{
printf("\n\tCantidad de puertas : %d", stock[j].caract.dat1.puertas);
printf("\n\tColor : %s", stock[j].caract.dat1.color);
printf("\n\tFamiliar : %c", stock[j].caract.dat1.familiar);
}
printf("\n\n\tVendido : %c", stock[j].vendido);
if (stock[j].vendido == 'S' || stock[j].vendido == 's')
{
if (stock[j].cont == 'S' || stock[j].cont == 's')
printf("\n\tValor : %.2f", stock[j].valor.contado);
if (stock[j].cont == 'N' || stock[j].cont == 'n')
{
printf("\n\tNumero de cuotas : %d", stock[j].valor.pagos.cant);
printf("\tValor de la cuota : %.2f", stock[j].valor.pagos.val);
}
}
printf("\n\n\t\tDesea listar otro vehículo (S/N) ");
k = getche();
if (k == 'N' || k == 'n')
return;
}
}
Union 08
Makefile
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra -pedantic
PROG = main
OBJ = main.o
$(PROG): $(OBJ)
$(CC) $(OBJ) -o $(PROG)
$(OBJ): main.c
$(CC) $(CFLAGS) -c main.c
.PHONY: clean
clean:
del $(OBJ) $(PROG).exe
Código:
// gcc -std=c11 -Wall -Wextra -pedantic main.c -o main
#include <stdio.h> // gets() eliminado en C11, reemplazo fgets()
#include <conio.h> // clrscr() no existe en GCC/MinGW reemplazo con system("cls") de stdlib.h
/* Reemplazo de clrscr() */
#include <stdlib.h> // system("cls");
/* Declaracion de constante global */
#define MAX 3
/* Declaracion de estructuras */
struct coupe
{
char nro_cil;
int cilind, veloc_max;
char marchas;
};
struct sedan
{
char puertas, color[10], familiar;
};
struct cuotas
{
int cant;
float val;
};
/* Declaracion de union de estructuras */
union clase
{
struct coupe dat;
struct sedan dat1;
};
/* Declaracion union que contiene tipo primitivo y estructura */
union fina
{
float contado;
struct cuotas pagos;
};
/* Declaracion de estructura que contiene miembros de tipo union */
struct autos
{
char marca[10];
int modelo;
char tipo;
union clase caract;
char vendido, cont;
union fina valor;
};
/* Prototipos de funciones */
int ingreso(struct autos stock[], int);
void listado(struct autos stock[], int);
int main(void)
{
/* Declaracion de vector de tipo struct autos */
struct autos stock[MAX];
/* Declaracion de variables */
int i,j=0;
do
{
clrscr(); // Comentar y reemplazar con la siguiente linea
//system("cls"); // Desomentar y comentar la linea anterior
/* Menu principal */
printf("\n\t\t\t\tMenu principal");
printf("\n\t1 - Ingreso de datos");
printf("\n\t2 - Listado de datos");
printf("\n\t3 - Salir");
printf("\n\nIngrese una opcion ( 1 - 4 ): ");
/* Leer el valor intriducido */
scanf("%d", &i);
/* Caso 1: llamar a la funcion ingreso con los argumentos vector de estructura stock y la variable entera j y almacenar lo que devuelve en j
* Caso 2: llamar a la funcion listado con los argumentos vector de estructura stock y la variable entera j.
*/
switch(i)
{
case 1:
j = ingreso(stock, j);
break;
case 2:
listado(stock, j);
}
}
while (i != 3); // Mientras la variable sea distinta de 3.
return 0;
}
/* Funcion para permitir el ingreso de los datos */
int ingreso(struct autos stock[], int j)
{
/* Declaracion de las variables a utilizar para *
* realizar el ingreso de los valores de tipo *
* "char" con formato numerico y para poder *
* ingresar los valores de tipo "float" *
*/
int i;
/* Verifica que no se exceda el maximo del vector */
if (j == MAX)
return (j);
/* Comienzo del ingreso de los datos */
do
{
clrscr(); // Comentar y reemplazar con la siguiente linea
//system("cls"); // Desomentar y comentar la linea anterior
printf("\n\t\t\tINGRESO DE DATOS");
printf("\n\n\tMarca : ");
fflush(stdin);// Produce comportamiento indefinido, puede ser remplazaodo por las 2 siguientes lineas
//int basura;
//while ((basura = getchar()) != '\n' && basura != EOF);
gets(stock[j].marca); // Eliminado en C11 reemplazar con fgets
//fgets(stock[j].marca, sizeof(stock[j].marca), stdin);
printf("\tModelo : ");
scanf("%d", &stock[j].modelo);
printf("\tTipo (C-S): ");
/* Ingreso de datos selectivo segun el tipo elegido */
do
{
stock[j].tipo = getche(); // Puede ser reemplazada con getchar() pero requiere ENTER
if (stock[j].tipo == 'C' || stock[j].tipo == 'c')
{
printf("\tNumero de cilindros : ");
/* Utilizacion de una variable auxiliar para *
* ingresar un valor con formato numerico en *
* una variable de tipo "char" *
*/
scanf("%d", &i);
/* Almacenar en struct autos => union clase caract => struct coupe dat => char nro_cil el valor almacenado en la variable entera i */
stock[j].caract.dat.nro_cil = i;
printf("\tCilindrada : ");
scanf("%d", &stock[j].caract.dat.cilind);
printf("\tVelocidad maxima : ");
scanf("%d", &stock[j].caract.dat.veloc_max);
printf("\tCantidad de marchas : ");
scanf("%d", &i); // Se sobreescribe el valor de la variable entera i
/* Almacenar en struct autos => union clase caract => struct coupe dat => char marchas el valor almacenado en la variable entera i */
stock[j].caract.dat.marchas = i;
}
if (stock[j].tipo == 'S' || stock[j].tipo == 's')
{
printf("\tCantidad de puertas : ");
scanf("%d", &i); // Se sobreescribe el valor de la variable entera i
/* Almacenar en struct autos => union clase caract => struct sedan dat1 => char puertas el valor almacenado en la variable entera i */
stock[j].caract.dat1.puertas=i;
fflush(stdin); // Produce comportamiento indefinido, puede ser remplazaodo por la siguiente linea
//while ((basura = getchar()) != '\n' && basura != EOF);
printf("\tColor : ");
gets(stock[j].caract.dat1.color); // Eliminado en C11, reemplazar con fgets(), comentar esta linea y descomentar la siguiente
//fgets(stock[j].caract.dat1.color, sizeof(stock[j].caract.dat1.color), stdin);
printf("\tFamiliar (S/N) : ");
stock[j].caract.dat1.familiar = getche(); // Puede ser reemplazada con getchar() pero requiere ENTER
}
}
while (stock[j].tipo == 'C' || stock[j].tipo == 'c' || stock[j].tipo == 'S' || stock[j].tipo == 's');
printf("\tVendido (S/N) : ");
/* Ingreso selectivo de los datos de venta */
do
{
stock[j].vendido = getche(); // Puede ser reemplazada con getchar() pero requiere ENTER
if (stock[j].vendido == 'S' || stock[j].vendido == 's')
{
printf("\tVenta al contado (S/N) : ");
do
{
stock[j].cont = getche(); // Puede ser reemplazada con getchar() pero requiere ENTER
if (stock[j].cont == 'S' || stock[j].cont == 's')
{
printf("\tValor : ");
scanf("%f", &stock[j].valor.contado);
}
if (stock[j].cont == 'N' || stock[j].cont == 'n')
{
printf("\tNumero de cuotas : ");
scanf("%d", &stock[j].valor.pagos.cant);
printf("\tValor de la couta : ");
scanf("%f", &stock[j].valor.pagos.val);
}
}
while (stock[j].cont == 'S' || stock[j].cont == 's' || stock[j].cont == 'N' || stock[j].cont == 'n');
//while (stock[j].cont != 'S' && stock[j].cont != 's' && stock[j].cont != 'N' && stock[j].cont != 'n');
}
if (stock[j].vendido == 'N' || stock[j].vendido == 'n')
{
stock[j].valor.pagos.cant = 0;
stock[j].valor.pagos.val = 0;
}
}
while (stock[j].vendido == 'S' || stock[j].vendido == 's' || stock[j].vendido == 'N' || stock[j].vendido == 'n');
//while (stock[j].vendido != 'S' && stock[j].vendido != 's' && stock[j].vendido != 'N' && stock[j].vendido != 'n');
printf("\n\t\tDesea ingresar otro vehiculo (S/N): ");
i = getche(); // Puede ser reemplazada con getchar() pero requiere ENTER
j++;
}
while (i == 'N' || i == 'n' || j >= MAX); // Deberia ser, como en el codigo anterior:
//while ((i == 'S' || i == 's') && j >= MAX);
/* Se retorna el ultimo valor de la posicion maxima de los valores ingresados */
return (j);
}
/* Funcion que permite la visualizacion de los datos */
void listado(struct autos stock[], int j)
{
/* Declaracion de variable a utilizar en la funcion */
int i;
/* Lazo para poder realizar la visualizacion de los datos *
* dentro del rango ingresado *
*/
for (i = 0; i < j; i++)
{
/* Mostrar marca, modelo y tipo */
printf("\n\n\tMarca : %s", stock[i].marca);
printf("\tModelo : %d", stock[i].modelo);
printf("\tTipo : %c", stock[i].tipo);
/* Listado selectivo segun el tipo */
if (stock[i].tipo == 'C' || stock[i].tipo == 'c')
{
/* Mostrar numero de cilidros, cilindrada, velocidad maxima, cantidad de marchas para tipo Coupe */
printf("\n\tNumero de cilindros : %d", stock[i].caract.dat.nro_cil);
printf("\tCilindrada : %d", stock[i].caract.dat.cilind);
printf("\n\tVelocidad maxima : %d", stock[i].caract.dat.veloc_max);
printf("\tCantidad de marchas : %d", stock[i].caract.dat.marchas);
}
if (stock[i].tipo == 'S' || stock[i].tipo == 's')
{
/* Mostrar cantidad de puertas, color, familiar para tipo Sedan */
printf("\tCantidad de puertas : %d", stock[i].caract.dat1.puertas);
printf("\tColor : %s", stock[i].caract.dat1.color);
printf("\tFamiliar (S/N) : %c", stock[i].caract.dat1.familiar);
}
/* Mostrar vendido */
printf("\n\tVendido : %c", stock[i].vendido);
/* Listado selectivo de los datos de venta */
if (stock[i].vendido == 'S' || stock[i].vendido == 's')
{
if (stock[i].cont == 'S' || stock[i].cont == 's')
printf("\tValor : %f", stock[i].valor.contado); // Mostrar valor de contado
if (stock[i].cont == 'N' || stock[i].cont == 'n')
{
printf("\tNumero de cuotas : %d", stock[i].valor.pagos.cant); // Mostrar numero de cuotas
printf("\tValor de la couta : %f", stock[i].valor.pagos.val); // Mostrar valor de cada cuota
}
}
printf("\n\t\tDesea listar otro vehiculo (S/N): ");
i = getche(); // Puede ser reemplazada con getchar() pero requiere ENTER
/* Seleccion que permite seguir visualizando o no *
* los datos del vector segun la eleccion del operador *
*/
if (i == 'N' || i == 'n')
return;
}
}