Estructuras anónimas

Antes dijimos, al hablar sobre la sintaxis de las declaraciones de estructuras, que debe aparecer o bien el identificador de estructura, o bien declararse algún objeto de ese tipo en la declaración. Bien, eso no es del todo cierto. Hay situaciones donde se pueden omitir ambos identificadores.

Una estructura anónima es la que carece de identificador de tipo de estructura y de declaración de objetos del tipo de estructura.

Por ejemplo, veamos esta declaración:

struct stAnonima {
  struct {
    int x;
    int y;
  };
  int z;
};

Para acceder a los campos x o y se usa la misma forma que para el campo z:

   stAnonima Anonima;
 
   Anonima.x = 0;
   Anonima.y = 0;
   Anonima.z = 0;

Pero, ¿cual es la utilidad de esto?

Pues, la verdad, no mucha, al menos cuando se usa con estructuras. En el capítulo dedicado a las uniones veremos que sí puede resultar muy útil.

El método usado para declarar la estructura dentro de la estructura es la forma anónima, como verás no tiene identificador de tipo de estructura ni de campo. El único lugar donde es legal el uso de estructuras anónimas es en el interior de estructuras y uniones.

Operador sizeof con estructuras

Podemos usar el operador sizeof para calcular el espacio de memoria necesario para almacenar una estructura.

Sería lógico suponer que sumando el tamaño de cada elemento de una estructura, se podría calcular el tamaño de la estructura completa, pero no siempre es así. Por ejemplo:

#include <iostream>
using namespace std;
 
struct A {
   int x;
   char a;
   int y;
   char b;
};

struct B {
   int x;
   int y;
   char a;
   char b;
};

int main()
{
   cout << "Tamaño de int: " 
        << sizeof(int) << endl;
   cout << "Tamaño de char: " 
        << sizeof(char) << endl;
   cout << "Tamaño de estructura A: " 
        << sizeof(A) << endl;
   cout << "Tamaño de estructura B: " 
        << sizeof(B) << endl;

   return 0;
}

El resultado, usando Dev-C++, es el siguiente:

Tamaño de int: 4
Tamaño de char: 1
Tamaño de estructura A: 16
Tamaño de estructura B: 12

Si hacemos las cuentas, en ambos casos el tamaño de la estructura debería ser el mismo, es decir, 4+4+1+1=10 bytes. Sin embargo en el caso de la estructura A el tamaño es 16 y en el de la estructura B es 12, ¿por qué?

La explicación es algo denominado alineación de bytes (byte-aling). Para mejorar el rendimiento del procesador no se accede a todas las posiciones de memoria. En el caso de microprocesadores de 32 bits (4 bytes), es mejor si sólo se accede a posiciones de memoria múltiplos de cuatro, de modo que el compilador intenta alinear los objetos con esas posiciones.

En el caso de objetos int es fácil, ya que ocupan cuatro bytes, pero con los objetos char no, ya que sólo ocupan uno.

Cuando se accede a datos de menos de cuatro bytes la alineación no es tan importante. El rendimiento se ve afectado sobre todo cuando hay que leer datos de cuatro bytes que no estén alineados.

En el caso de la estructura A hemos intercalado campos int con char, de modo que el campo int y, se alinea a la siguiente posición múltiplo de cuatro, dejando tres posiciones libres después del campo a. Lo mismo pasa con el campo b.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
x a vacío y b vacío

En el caso de la estructura B hemos agrupado los campos de tipo char al final de la estructura, de modo que se aprovecha mejor el espacio, y sólo se desperdician los dos bytes sobrantes después de b.

0 1 2 3 4 5 6 7 8 9 10 11
x y a b vacío

Campos de bits

Existe otro tipo de estructuras que consiste en empaquetar cada uno de los campos en el interior de valores enteros, usando bloques o subconjuntos de bits para cada campo.

Por ejemplo, un objeto char contiene ocho bits, de modo que dentro de ella podremos almacenar ocho campos de un bit, o cuatro de dos bits, o dos de tres y uno de dos, etc. En un objeto int de 16 bits podremos almacenar 16 campos de un bit, etc.

Para definir campos de bits debemos usar siempre valores de enteros sin signo, ya que el signo se almacena en un bit del entero, el de mayor peso, y puede falsear los datos almacenados en la estructura.

La sintaxis es:

struct [<nombre de la estructura>] {
   unsigned <tipo_entero> <identificador>:<núm_de_bits>;
   .
} [<lista_objetos>];

Existen algunas limitaciones, por ejemplo, un campo de bits no puede crearse a orcajadas entre dos objetos distintos, todos sus bits tienen que estar en el mismo valor entero.

Veamos algunos ejemplos:

struct mapaBits {
   unsigned char bit0:1;
   unsigned char bit1:1;
   unsigned char bit2:1;
   unsigned char bit3:1;
   unsigned char bit4:1;
   unsigned char bit5:1;
   unsigned char bit6:1;
   unsigned char bit7:1;
   };
 
struct mapaBits2 {
   unsigned short int campo1:3;
   unsigned short int campo2:4;
   unsigned short int campo3:2;
   unsigned short int campo4:1;
   unsigned short int campo5:6;
};
 
struct mapaBits3 {
   unsigned char campo1:5;
   unsigned char campo2:5;
};

En el primer caso se divide un valor char sin signo en ocho campos de un bit cada uno:

7 6 5 4 3 2 1 0
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0

En el segundo caso dividimos un valor entero sin signo de dieciséis bits en cinco campos de distintas longitudes:

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
campo5 c4 campo3 campo2 campo1

Los valores del campo5 estarán limitados entre 0 y 63, que son los números que se pueden codificar con seis bits. Del mismo modo, el campo4 sólo puede valer 0 ó 1, etc.

unsigned char unsigned char
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
      campo2       campo1

En este ejemplo vemos que como no es posible empaquetar el campo2 dentro del mismo char que el campo1, de modo que se añade un segundo valor char, y se dejan sin usar todos los bits sobrantes.

También es posible combinar campos de bits con campos normales, por ejemplo:

struct mapaBits2 {
   int numero;
   unsigned short int campo1:3;
   unsigned short int campo2:4;
   unsigned short int campo3:2;
   unsigned short int campo4:1;
   unsigned short int campo5:6;
   float n;
};

Los campos de bits se tratan, por norma general, igual que cualquier otro de los campos de una estructura. Se les puede asignar valores (dentro del rango que admitan por su tamaño), pueden usarse expresiones, imprimirse, etc.

#include <iostream>
#include <cstdlib>
using namespace std;
 
struct mapaBits2 {
   unsigned short int campo1:3;
   unsigned short int campo2:4;
   unsigned short int campo3:2;
   unsigned short int campo4:1;
   unsigned short int campo5:6;
};

int main()
{
   mapaBits2 x;
   
   x.campo2 = 12;
   x.campo4 = 1;
   cout << x.campo2 << endl;
   cout << x.campo4 << endl;
   
   return 0;
}

Lo que no es posible es leer valores de un campo de bits mediante cin. Para poder leer valores desde el teclado se debe usar una variable entera auxiliar, y posteriormente asignarla al campo de bits.

No es frecuente usar estas estructuras en programas, salvo cuando se relacionan con ciertos dispositivos físicos. Por ejemplo, para configurar un puerto serie en MS-DOS se usa una estructura empaquetada en un unsigned char, que indica el número de bits de datos, de bits de parada, la paridad, etc, es decir, todos los parámetros del puerto. En general, para programas que no requieran estas estructuras, es mejor usar estructuras normales, ya que son mucho más rápidas.

Otro motivo que puede decidirnos por estas estructuras es el ahorro de espacio, ya sea en disco o en memoria. Si conocemos los límites de los campos que queremos almacenar, y podemos empaquetarlos en estructuras de mapas de bits podemos ahorrar mucho espacio.

Palabras reservadas usadas en este capítulo

struct.

Problemas

  1. Escribir un programa que almacene en un array los nombres y números de teléfono de 10 personas. El programa debe leer los datos introducidos por el usuario y guardarlos en memoria (en el array). Después debe ser capaz de buscar el nombre correspondiente a un número de teléfono y el teléfono correspondiente a una persona. Ambas opciones deben se accesibles a través de un menú, así como la opción de salir del programa. El menú debe tener esta forma, más o menos:

    a) Buscar por nombre
    b) Buscar por número de teléfono
    c) Salir

    Pulsa una opción:

    Nota: No olvides que para comparar cadenas se debe usar una función, no el operador ==.

  2. Para almacenar fechas podemos crear una estructura con tres campos: ano, mes y dia. Los días pueden tomar valores entre 1 y 31, los meses entre 1 y 12 y los años, dependiendo de la aplicación, pueden requerir distintos rangos de valores. Para este ejemplo consideraremos suficientes 128 años, entre 1960 y 2087. En ese caso el año se obtiene sumando 1960 al valor de ano. El año 2003 se almacena como 43.
    Usando estructuras, y ajustando los tipos de los campos, necesitamos un char para dia, un char para mes y otro para ano.
    Diseñar una estructura análoga, llamada fecha, pero usando campos de bits. Usar sólo un entero corto sin signo (unsigned short), es decir, un entero de 16 bits. Los nombres de los campos serán: dia, mes y anno.
  3. Basándose en la estructura de bits del ejercicio anterior, escribir una función para mostrar fechas: void Mostrar(fecha);. El formato debe ser: "dd de mmmmmm de aaaa", donde dd es el día, mmmmmm el mes con letras, y aaaa el año. Usar un array para almacenar los nombres de los meses.
  4. Basándose en la estructura de bits del ejercicio anterior, escribir una función bool ValidarFecha(fecha);, que verifique si la fecha entregada como parámetro es válida. El mes tiene que estar en el rango de 1 a 12, dependiendo del mes y del año, el día debe estar entre 1 y 28, 29, 30 ó 31. El año siempre será válido, ya que debe estar en el rango de 0 a 127.
    Para validar los días usaremos un array int DiasMes[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};. Para el caso de que el mes sea febrero, crearemos otra función para calcular si un año es o no bisiesto: bool Bisiesto(int); Los años bisiestos son los divisibles entre 4, al menos en el rango de 1960 a 2087 se cumple.

    Nota: los años bisiestos son cada cuatro años, pero no cada 100, aunque sí cada 400. Por ejemplo, el año 2000, es múltiplo de 4, por lo tanto debería haber sido bisiesto, pero también es múltiplo de 100, por lo tanto no debería serlo; aunque, como también es múltiplo de 400, finalmente lo fue.

  5. Seguimos con el tema de las fechas. Ahora escribir dos funciones más. La primera debe responder a este prototipo: int CompararFechas(fecha, fecha);. Debe comparar las dos fechas suministradas y devolver 1 si la primera es mayor, -1 si la segunda es mayor y 0 si son iguales.
    La otra función responderá a este prototipo: int Diferencia(fecha, fecha);, y debe devolver la diferencia en días entre las dos fechas suministradas.

Comentarios de los usuarios (35)

b0ch0n
2010-09-28 00:39:50

Nota del administrador: Hemos eliminado el código ya que las soluciones a los problemas no se han incluido de forma intencionada. La idea es que cada uno haga sus propios problemas a su modo.

b0ch0n
2010-10-02 03:34:54

Éste es uno de los temas que más me costó entender y aquí dejo mi aporte.

Nota del administrador: Hemos eliminado el código ya que las soluciones a los problemas no se han incluido de forma intencionada. La idea es que cada uno haga sus propios problemas a su modo.

>Ariel
2010-12-13 19:47:05

Muy buen aporte Bochoon pero igualmente el enunciado del problema hay que tratarlo con campos de bits... Gracias por aportar!!

Ariel
2010-12-13 22:08:34

//El programa debe leer los datos introducidos por el usuario y guardarlos en memoria (en el array).

//Después debe ser capaz de buscar el nombre correspondiente a un número de teléfono y el teléfono

//correspondiente a una persona. Ambas opciones deben ser accesibles a través de un menú,

//así como la opción de salir del programa

//<Ariel> ;)

#include <iostream>

#include <string>

using namespace std;

struct personas {

char nombre[15];

int tel;

} registro[10];

int main ()

{

int i;

char buscaNombre[15];

int buscaTel;

int opcion;

char rta[2];

for ( i=0; i<3; i++)

{

cout << \"Ingrese el nombre de la persona \" << i+1 << \" : \";

cin >> registro [i].nombre;

cout << \"Ingrese el numero telefonico de \" << registro [i].nombre << \" : \";

cin >> registro [i].tel;

cout << endl << endl ;

}

cout << endl;

cout << endl << endl << endl;

do

{

cout << \"*****************************************************\" << endl;

cout << \" MENU PRINCIPAL \" << endl;

cout << \"*****************************************************\" << endl << endl << endl;

cout << \"Marque la opcion que desea realizar\" << endl << endl;

cout << \"1- Buscar por: Un numero telefonico\" << endl;

cout << \"2- Buscar por: El nombre de una persona\" << endl;

cout << \"3- Salir\" << endl << endl << endl << endl << endl << endl << endl;

cout << \"Opcion : \";

cin >>opcion;

cout << endl << endl;

if (opcion == 1)

{

cout << \"Telefono: \";

cin >> buscaTel;

cout << endl << endl;

cout << \"*****************************************************\" << endl;

cout << \" RESULTADOS \" << endl;

cout << \"*****************************************************\" << endl << endl << endl << endl << endl;

for (i=0; i<9 ; i++)

{

if (registro [i].tel == buscaTel)

cout << buscaTel << \": \"<< registro [i].nombre << endl << endl << endl << endl << endl << endl;

}

}

if (opcion == 2)

{

cout << \"Nombre: \";

cin >> buscaNombre;

cout << endl << endl;

cout << \"*****************************************************\" << endl;

cout << \" RESULTADOS \" << endl;

cout << \"*****************************************************\" << endl << endl << endl << endl << endl;

for (i=0; i<9 ; i++)

{

if (strcmp(registro [i].nombre,buscaNombre)==0) //Compara las dos cadenas, si la cad1 es mayor que cad2 el resultado será mayor de 0, si cad1 es menor que cad2, el resultado será menor de 0, si son iguales, el resultado será 0. La comparación se realiza carácter a carácter. Mientras los caracteres comparados sean iguales, se continúa con el siguiente carácter. Cuando se encuentran caracteres distintos, aquél que tenga un código ASCII menor pertenecerá a la cadena menor. Por supuesto, si las cadenas son iguales hasta que una de ellas se acaba, la más corta es la menor.

cout << buscaNombre << \": \"<< registro [i].tel << endl << endl << endl << endl << endl << endl;

}

}

if (opcion == 3)

return 0;

cout <<endl << endl << endl << \"Desea realizar otra busqueda? \";

cin >> rta;

}

while ( rta [0] == \'s\' || rta [0] == \'S\' );

cout << endl << endl;

return 0;

}

Jorge
2011-01-18 18:27:48

//*

//*

//* EJERCICIO 2,3,4,5

//* problema de las fechas

//*

//*

#include <iostream>

using namespace std;

struct bmpFecha {

//*Mapa de bits que representa las fechas

//* dia = 2e5 = 32

//* mes = 2e4 = 16

//* año = 2e7 = 128

unsigned short int dia:5;

unsigned short int mes:4;

unsigned short int anno:7;

} fecha[2];

char meses[12][11] = {"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" };

int diaMes[12] = {31,28,31,30,31,30,31,31,30,31,30,31};

bool bisiesto (bmpFecha f);

bool validar (bmpFecha f);

void mostrar(bmpFecha f);

int numDias(bmpFecha f);

int mayor (bmpFecha f1, bmpFecha f2);

int comparar (bmpFecha f1, bmpFecha f2);

int main(){

//*

//* Programa principal, usa bucle for para la introducion de las fechas

//* Muestra las fechas introducidas y calcula el numero de dias de diferencia

//* entre ellas

//*

int i;

int aux;

for (i=0; i <2; i++){

cout << "Introduzca el dia " << endl;

cin >> aux;

fecha[i].dia = aux;

cout << "Introduzca el mes " << endl;

cin >> aux;

fecha[i].mes = aux;

cout << "Introduzca el anno" << endl;

cin >> aux;

fecha[i].anno = aux - 1960;

if (validar(fecha[i])) cout << "Fecha correcta" << endl;

else {

cout << "Fecha incorrecta" << endl;

i--;

}

}

mostrar(fecha[0]);

mostrar(fecha[1]);

cout << "El numero de dias de diferencia es " << comparar(fecha[0],fecha[1]) << endl;

cin.get();

cin.get();

return 0;

}

int comparar(bmpFecha f1, bmpFecha f2){

//*

//*Compara dos fechas

//*IN: fecha1, fecha2

//*OUT: entero, como diferenca en dias entre fechas

//*

switch (mayor(f1,f2)){

case 1:{

return numDias(f1) - numDias(f2);

break;

}

case -1: {

return numDias(f2) - numDias(f1);

cout << numDias(f2);

cin.get();

break;

}

case 0: {

return 0;

break;

}

}

}

int mayor(bmpFecha f1, bmpFecha f2){

//*

//*Determina si una fecha es mayor que otra

//*IN: fecha1, fecha2

//*OUT: 1 si fecha 1 > fecha2, -1 si fecha2 > fecha1, 0 si son iguales

//*

int diasF1;

int diasF2;

diasF1 = numDias(f1);

diasF2 = numDias(f2);

if (diasF1 != diasF2) {

if (diasF1 > diasF2) return 1;

else return -1;

}

else return 0;

}

int numDias(bmpFecha f) {

//*

//* Calcula en numero de dias desde el 1/1/1960 hasta la fecha introducida

//*IN: fecha

//OUT: entero, numero de dias.

int sumaDias;

int i;

sumaDias = 0;

for (i=0; i<f.anno; i++) {

if (bisiesto(f)) sumaDias += 366;

else sumaDias += 365;

}

for (i=0; i<f.mes -1; i++) {

sumaDias += diaMes[i];

}

sumaDias += f.dia;

if ((bisiesto(f)) && f.mes > 2) sumaDias ++;

return sumaDias;

}

void mostrar(bmpFecha f){

//*

//* Muesta la fecha

//* IN: fecha

//* OUT: Vacio

//*

cout << "El dia seleccionado es " << f.dia << "\\" << meses[f.mes-1] << "\\" << f.anno + 1960 << endl;

}

bool validar (bmpFecha f){

//*

//* Comprueba que la fecha el dia no sea mayor que el dia maximo del mes

//* Tiene en cuenta los años bisiestos

//* IN: fecha

//* OUT: boolean, true si es fecha correcta, false si no

if (f.dia > diaMes[f.mes-1]) {

if ((f.mes == 2) && (f.dia == 29) && bisiesto(f)) return true;

else return false;

}

else return true;

}

bool bisiesto (bmpFecha f) {

//*

//* Calcula que el año sea bisiesto o no

//* IN = fecha

//* OUT = boolean, true si es bisiesto, false sino

if (((f.anno + 1960) % 4 == 0) && ((f.anno + 1960) % 100 != 0)) {

return true;

}

else {

if ((f.anno + 1960) % 400 ==0) {

return true;

}

else return false;

}

}

Javier Rollon
2011-03-12 15:16:58

Hola. Buenísimo el curso. Muchísimas gracias!

En la parte de estructuras de bits en el ejercicio de comprobar la fecha tengo un problema. Los meses pueden ser del 1 al 12 y lo definimos con 4 bits ya que con ya incluye hasta el numero 16. El problema es que si a la hora de introducir a partir del 17 este se transformará en 0 y el 18 en 1 y volverá de nuevo a renombrarse.. por lo que a la hora de acceder a los datos no habrá manera de saber qué número metimos realmente.

Claro que podría hacer un if aux > 12 pero quiero comprobar la fecha una vez introducidos todos los datos.

Como lo hago sin tener varias variables auxiliares? para comprobar la fecha correcta?

Steven
2011-03-12 17:51:24

Hola Javier,

Efectivamente, podemos asignar un número cuya representación binaria requiera más bits de los que podemos albergar en tal campo de bits.

La solución es la que indicas: usa una variable auxiliar. Además, si piensas obtener esta información a partir de 'cin >>', entonces no te queda más remedio, porque no puedes pasar un campo de bits a 'cin >>' directamente. Tendrás que hacer esto:

fecha f1;

int aux;
cin >> aux;

// Procesar 'aux' => validar 'aux'
...
f1.dia = aux;

Aquí estamos verificando la información introducida por el usuario. Es posible que tengamos que volver a pedir datos al usuario.

Pero luego comprobaremos la fecha correcta según la información guardada. Esto se hace independientemente de la comprobación de los valores introducidos por el usuario.

Espero haber aclarado la duda.

Steven

Carlos
2011-07-02 13:59:18

Buenas!!! Tengo una duda con el enunciado del ejercicio 2. Cuando dice:

"Usando estructuras, y ajustando los tipos de los campos, necesitamos un char para dia, un char para mes y otro para ano.

Diseñar una estructura análoga, llamada fecha, pero usando campos de bits. "

Realmente tengo que usar 2 structuras?? Una con los campos de bits y otra en formato char?? es que iba a hacerlo solo con la de bits, pero releyendo el enunciado esto me ha perdido un poco. Si hago 2, ¿con cuál se trabajaría? Gracias

Steven R. Davidson
2011-07-02 15:47:41

Hola Carlos,

Para el 2º ejercicio, debes diseñar una estructura con campos de bits.

Hasta luego,

Steven

fco_gar_alb
2011-11-24 20:06:05

Hay va eso; para los que se duermen en los laureles...

// Problema 11.5 
// Seguimos con el tema de las fechas. 
// Ahora escribir dos funciones más: 
// La primera debe responder a este prototipo: int CompararFechas(fecha, fecha);
// Debe comparar las dos fechas suministradas 
// y devolver 1 si la primera es mayor,
// -1 si la segunda es mayor 
// y 0 si son iguales.
// La otra función responderá a este prototipo: int Diferencia(fecha, fecha);
// y debe devolver la diferencia en días entre las dos fechas suministradas.

#include <iostream>
#include <stdlib.h>

using namespace std;

char * mesLetra[] = { "Enero", "Febrero", "Marzo", "Abril", "Mayo",
    "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre",
    "Diciembre"}; 

int diasMes[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

struct stFecha{
    unsigned short int dia: 5; // Campo dia 5 bits; 32 valores
    unsigned short int mes: 4; // Campo mes 4 bits; 16 valores
    unsigned short int ano: 7; // Campo ano 7 bits; 128 valores  

    stFecha(){ almacenaFecha(1, 1, 1960); }
    stFecha(short d, short m, short a)
    { 
        if( !almacenaFecha(d, m, a) ) 
            almacenaFecha(1, 1, 1960);
    }
        
    bool almacenaFecha(short d, short m, short a)
    {   
        bool almacenar = false; 
         
        if( validarFecha(&d, &m, &a) )
        { 
            dia = d;
            mes = m;
            ano = a - 1960;
            
            almacenar = true;
        }
        
        return almacenar;
    } 
        
    void mostrarFecha()
    {
        cout.fill('0');
        cout.width(2);
        cout << dia << "-";
        cout.width(2);
        cout << mes << "-" << ano + 1960 << endl;
        cout.fill(' ');
    }  
        
    bool bisiesto()
    {
        bisiesto( ano );
    } 
    
    bool validarFecha();
    int compararFechas( stFecha fecha2 );      
    int diferencia( stFecha fecha2 );
    
    private :
    bool bisiesto( int anno )
    {
        bool anoBisiesto = false;
     
        if( !((anno+1960)%4) && ( (anno+1960)%100 || !((anno+1960)%400) ) ) 
            anoBisiesto = true;
     
        return anoBisiesto;
    } 
    
    bool validarFecha( short *d, short *m, short *a);
};
    

int main()
{         
        
   stFecha fechaPrueba1(1,1,2000); // Creamos una fecha 
   fechaPrueba1.mostrarFecha(); // La mostramos
   cout << "Resultado de la validacion: " 
        << fechaPrueba1.validarFecha() << endl; // comprobamos si es valida
   
   stFecha fechaPrueba2(1,1,2002); // Creamos otra fecha
   fechaPrueba2.mostrarFecha(); // La mostramos 
   cout << "Resultado de la validacion: " 
        << fechaPrueba2.validarFecha() << endl; // y comprobamos si es valida
   
   // Comparamos las fechas
   cout << "Resultado de la comparacion: " 
        << fechaPrueba1.compararFechas(fechaPrueba2) << endl;

   // Vemos la diferencia en dias entre las fechas anteriores        
   cout << "Resultado de la diferencia: " 
        << fechaPrueba1.diferencia(fechaPrueba2) << endl;

   system("pause");
   return 0;
}

bool stFecha::validarFecha()
{
    bool fechaValida = false;
        
    if( mes >= 1 && mes <= 12 && ano <= 127 )
    {
        if( mes == 2 && bisiesto() )
        {
            if( dia >= 1 && dia <= 29 ) 
                fechaValida = true;
        }
        else
        {
            if( dia >= 1 && dia <= diasMes[mes-1] )
                fechaValida = true;
        }
    }
    
    return fechaValida;
}

int stFecha::compararFechas( stFecha fecha2 )
{
    int fechaPeso1, fechaPeso2, difPeso, resComp;
    
    // Convertimos las fechas en numeros con peso significativo
    fechaPeso1 = ano * 10000 + mes * 100 + dia;
    fechaPeso2 = fecha2.ano * 10000 + fecha2.mes * 100 + fecha2.dia;
    
    // Las restamos y comparamos la diferencia
    if( (difPeso = fechaPeso1 - fechaPeso2) > 0 )
        // La primera es mayor; 1
        resComp = 1;
    else
        if(difPeso < 0)
            // La segunda es mayor; -1
            resComp = -1;
        else
            // Son iguales; 0
            resComp = 0;

    return resComp;            
}       
       
int stFecha::diferencia( stFecha fecha2 )
{
    // Con vuestro permiso voy a usar punteros a las estructuras;
    // para referenciar correctamente a la menor y mayor fecha
    // y no crear mas estructuras en memoria
    stFecha *refFechMen, *refFechMay;
    int i, antBis;
    float acumDias;

    if( compararFechas( fecha2 ) > 0 )
    {   // Si compararFechas es cierto (mayor que cero); es decir 1
        // La primera fecha es mayor
        refFechMen = &fecha2;
        refFechMay = this;
    }
    else
    {   // Si compararFechas es falso (menor o igual que cero); 
        // es decir 0 o -1
        // La segunda fecha es mayor o ambas son iguales.
        refFechMen = this;
        refFechMay = &fecha2;
    }
    
    // Calculo de los dias contenidos en años completos
    // Consideremos el año de la fecha menor como completo
    //---------------------------------------------------------------------
    // Buscamos el anterior bisiesto al año del fecha menor
    for( antBis = refFechMen->ano - 1; !bisiesto(antBis); antBis-- );
    // Calculamos la fracción de día erronea que llevamos a partir del año 
    // bisiesto: 0, 0.25, 0.50 o 0.75
    acumDias = ((refFechMen->ano - antBis) * 0.25) - 0.25;
    // Acumulamos los años con su fraccion de dias erroneos
    acumDias += (refFechMay->ano - refFechMen->ano) * 365.25;

    // Acumulamos dias desde principio de año hasta la fecha mayor
    //---------------------------------------------------------------------    
    for( i = 1; i < refFechMay->mes; i++ )
        acumDias += diasMes[i-1];
    
    ( bisiesto(refFechMay->ano) && refFechMay->mes > 2 )? 
        acumDias += refFechMay->dia  : acumDias += refFechMay->dia - 1;
    
    // Desacumulamos los dias desde principio de año hasta la fecha menor; 
    // para quitar la diferencia de dias que hemos sumado de más
    // al considerar el primer año completo
    //---------------------------------------------------------------------    
    for( i = 1; i < refFechMen->mes; i++ )
        acumDias -= diasMes[i-1];
        
    ( bisiesto(refFechMen->ano) && refFechMen->mes > 2 )?   
        acumDias -= refFechMen->dia : acumDias -= refFechMen->dia - 1;
    
    // Finalmente retornamos acumulados despreciando la parte decimal
    //---------------------------------------------------------------------        
    return (int) acumDias; 
}        

bool stFecha::validarFecha( short *d, short *m, short *a)
{
    bool fechaValida = false;
            
    if( *m >= 1 && *m <= 12 
        && *a >= 1960 && *a <= 2087 )
    {
        if( *m == 2 && bisiesto((int) *a ))
        {
            if( *d >= 1 && *d <= 29 ) 
                fechaValida = true;
        }
        else
        {
            if( *d >= 1 && *d <= diasMes[*m-1] )
                fechaValida = true;
        }
    }
    
    return fechaValida;
}   

Pedro
2011-12-21 23:06:56

Hola, tengo una duda, intentaba hacer un:

cin << entrada[x].dia

siendo entrada[x].dia un campo de bits, y me da error al compilar, pero si uso una variable intermediaria para el proceso, lo puedo compilar y funciona.

¿Por que no puedo hacer directamente el cin << entrada[x].dia, pese a encontrar la manera de hacerlo, me gustaria comprender el motivo por el que no me ha dejado?

Gracias de antemano

(Perdon por el comentario duplicado en otro capitulo)

Salvador Pozo
2011-12-22 12:00:57

Hola, Pedro:

El problema está en un concepto que aún no hemos visto. Se trata de la sobrecarga de operadores.

Concretamente se trata del operador <<. Por defecto este operador está definido (sobrecargado) para todos los tipos fundamentales, pero no para los agregados, ni, lamentablemente, para los campos de bits.

Pedro
2011-12-26 21:01:31

Hola estoy teniendo problemas con este codigo:

El problema es que, cuando ingreso el primer nombre, se me pierde el primer caracter, estoy conciente que es por la sentencia f[i]=getchar();. Pero en este momento no se me ocurre como controlar el ingreso del nombre por teclado. También algunas veces cuando esto ingresando los datos de nombre y número de telefono, el programa se salta. Es decir es como si no entrara al while para el ingreso del nombre. Agradezco su colaboración. Saludos y gracias por el curso

#include <cstdlib>

#include <iostream>

#include <stdio.h>

#include <ctype.h>

#include <cstring>

struct Directorio{

char nombre[45];

long int numero;

} lista[10];

using namespace std;

void BuscarNumero();

void BuscarNombre();

int i;

int main(int argc, char *argv[])

{

int p;

char c,f[45];

for(int k=0;k<10;k++){

i=0;

cout<<"Ingrese el nombre de la persona "<<k<<endl;

f[i]=getchar();

while((f[i]=getchar())!='\n'){

tolower(f[i]);

i++;

}

f[i]=0;

strcpy(lista[k].nombre,f);

cout<<"Ingrese el # Telefonico de la persona "<<k<<endl;

cin>>lista[k].numero;

}

cout<<"Oprima el # de la operacion que desea realizar"<<endl;

cout<<"1. Buscar por Nombre."<<endl;

cout<<"2. Buscar por # de Telefono."<<endl;

cout<<"3. Salir"<<endl;

cin>>p;

i=0;

switch(p){

case 1: BuscarNumero(); break;

case 2: BuscarNombre(); break;

default: break;

}

system("PAUSE");

return EXIT_SUCCESS;

}

void BuscarNumero()

{

char c,d[45];

cout<<"Ingrese el nombre de la persona."<<endl;

getchar();

while(((c=getchar()))!='\n'){

d[i]=tolower(c);

i++;

}

d[i]=0;

int m=0;

for(int j=0;j<10;j++){

if(!strcmp(lista[j].nombre,d)){

cout<<"# Telefonico"<<endl;

cout<<lista[j].numero<<endl;

break;

}

else

m++;

}

if(m==10)

cout<<"El nombre no esta registrado"<<endl;

}

void BuscarNombre(){

long int k;

cout<<"Ingrese el # telefonico"<<endl;

cin>>k;

int m=0;

for(int j=0;j<10;j++){

if(lista[j].numero==k){

cout<<"El Nombre de la Persona es "<<endl;

cout<<lista[j].nombre<<endl;

break;

}

else

m++;

}

if(m==10)

cout<<"El # no esta registrado"<<endl;

}

Anubiz
2013-02-24 02:52:45

#include <iostream.h>

#include <conio2.h>

#include <ctype.h>

struct usuarios

{

char nombre[15];

char numero[15];

}per[10];

int d=0;

char E[]={"Error"};

using namespace std;

int comparar(char k[15]);

int comparar2(char k[15]);

char buscar[15];

int main()

{

cout<<"\n\t\t\tIngresa los datos de usuarios: "<<endl;

char opcion;

for (int a=0;a<15;a++)

{

cout<<" Usuario "<<a+1<<":"<<endl;

cout<<" Nombre: ";

cin>>per[a].nombre;

cout<<" Numero: ";

cin>>per[a].numero;

cout<<"\n Desea ingresar otro contacto? s/n :: ";

cin>>opcion;

if (opcion=='s')

{

cout<<"\n";

continue;

}

else

{

clrscr();

cout<<"\n\t\tLos datos fueron almacenados exitosamente.\n";

break;

}

if (a==14)

{

clrscr();

cout<<" Ha llegado al limite de usuarios.\n\n";

}

}

opcion='a';

opciones:

if (opcion!='a' && opcion!='b' && opcion!='c' && opcion!='s')

{

cout<<"\n\n El valor ingresado no esta dentro de los parametros correctos."<<endl;

}

opcion=0;

if (d==15)

{

cout<<"\n Ha ocurrido un error durante el proceso. ";

}d=0;

cout<<"\n a) Buscar por nombre."<<endl;

cout<<" b) Buscar por numero de telefono."<<endl;

cout<<" c) Salir."<<endl;

cout<<"\n Ingrese la opcion que desea ejecutar: "<<endl;

cout<<" ";

cin>>opcion;

switch(opcion)

{

case 'a':

cout<<"\n Ingresa un nombre: ";

cout<<" ";

cin>>buscar;

if (comparar(buscar)!=15){

cout<<" El usuario con ese nombre posee el numero: "<<per[comparar(buscar)].numero;

cout<<"\n\n Desea intentarlo nuevamente? s/n :: ";

cin>>opcion;

if (opcion=='s')

{

clrscr();

goto opciones;

}else{return 0;}

}

else

{

d=15;

goto opciones;

}

break;

case 'b':

cout<<"\n Ingresa un numero: ";

cout<<" ";

cin>>buscar;

if (comparar2(buscar)!=15){

cout<<" El numero ingresado le pertecene al usuario: "<<per[comparar2(buscar)].nombre;

cout<<"\n\n Desea intentarlo nuevamente? s/n :: ";

cin>>opcion;

if (opcion=='s')

{

clrscr();

goto opciones;

}else{return 0;}}

else

{

d=15;

goto opciones;

}

break;

case 'c':

return 0;

break;

default:

clrscr();

goto opciones;

break;

}

}

int comparar(char k[15])

{

int c,a=0;

for (int b=0;b<10;b++)

{

if (k[a]==per[b].nombre[a] && k[a]!=0)

{

c=b;

}

a++;

}

return c;

}

int comparar2(char k[15])

{

int c,a=0;

for (int b=0;b<10;b++)

{

if (k[a]==per[b].numero[a] && k[a]!='\0')

{

c=b;

}

a++;

}

return c;

}

efreue
2013-10-03 05:48:16

A continuación dejo resuelto el primer problema:

#include <cstdlib>

#include <iostream>

/*

Problema:

1.Escribir un programa que almacene en un array los nombres y números de teléfono de 10 personas.

El programa debe leer los datos introducidos por el usuario y guardarlos en memoria (en el array).

Después debe ser capaz de buscar el nombre correspondiente a un número de teléfono

y el teléfono correspondiente a una persona.

Ambas opciones deben se accesibles a través de un menú, así como la opción de salir del programa.

El menú debe tener esta forma, más o menos:

a) Buscar por nombre

b) Buscar por número de teléfono

c) Salir

*/

using namespace std;

//creo la estructura persona

struct Persona

{

//declaro variables

string nombre, telefono;

//declaro metodos

string leerNombre() {return nombre;} //devuelve el nombre

void guardarNombre(string nom) {nombre = nom;} //asigna un valor al nombre

string leerTelefono() {return telefono;} //devuelve el telefono

void guardarTelefono(string tel) {telefono = tel;} //asigna un valor al telefono

//declaro constructor: con el objetivo de

Persona(){nombre = "Constructor"; telefono = "111";}

} UnaPersona[10]; //UnaPersona represeta la variable donde se almacenaran las personas

int main()

{

//declarar variables

string n = "";

int op,i = 0, cont = 0;

bool encontro = 0;

//retornados por el constructor

UnaPersona[i].leerNombre();

UnaPersona[i].leerTelefono();

//solicitar al usuario que inserte nombres y telefonos

cout << "Insertar hasta 10 personas. (Para finalizar debera escribir la palabra salir)" << endl;

while (n != "salir")

{

if (i >= 9)

break;

cout << "Ingresar un nombre " << endl;

cin >> n;

if (n != "salir")

{

i++;

UnaPersona[i].guardarNombre(n);

cout << "Ingresar un telefono " << endl;

cin >> n;

UnaPersona[i].guardarTelefono(n);

}

cout << i;

}

//muestro la cantidad de personas insertadas

cont = i;

cout << "********************" << endl;

cout << " MENU " << endl;

cout << "********************" << endl;

cout << "1. Buscar por nombre" << endl;

cout << "2. Buscar por telefono" << endl;

cout << "3. salir" << endl;

cout << "Ingrese el numero de una de las opciones: ";

cin >> op; //el usuario ingresa la opcion

switch (op)

{

case 1:

cout << "Se procedera la persona por nombre " << endl;

cout << "Ingresar el nombre" << endl;

cin >> n;

for(i=0;i<=cont;i++)

{

if(UnaPersona[i].leerNombre() == n)

{

cout << "El telefono de la persona llamada " << UnaPersona[i].leerNombre() << " es " << UnaPersona[i].leerTelefono() << endl;

encontro = 1;

break;

}

}

if (encontro == 0)

cout << "No se ha encontrado la persona" << endl;

break;

case 2:

cout << "Se procedera la persona por telefono " << endl;

cout << "Ingresar el telefono" << endl;

cin >> n;

for(i=0;i<=cont;i++)

{

if(UnaPersona[i].leerTelefono() == n)

{

cout << "El nombre de la persona con telefono " << UnaPersona[i].leerTelefono() << " es " << UnaPersona[i].leerNombre() << endl;

encontro = 1;

break;

}

}

if (encontro == 0)

cout << "No se ha encontrado la persona" << endl;

break;

default:

break;

}

system("PAUSE");

return EXIT_SUCCESS;

}

Diego
2015-01-02 16:39:22

Hola, entendí la asignación de bits, y realmente parece útil al momento de ahorrar espacio cuando se usan variables pequeñas, sobretodo unsigned short int. Pero no encuentro la utilidad de los char quer tienen mas de 4 bits.Entiendo que el valor de un valor int esta delimitado por potencias de 2, Pero que sucede en el caso de char, un char de solo un bit para que podria servir, si alguien me puede explicar gracias.

Steven R. Davidson
2015-01-03 01:38:31

Hola Diego,

Creo que has confundido "bits" con "bytes" en algunas partes de tu comentario. El tipo de dato 'char' siempre ocupa 1 byte (8 bits). Los otros tipos pueden variar de una plataforma a otra - y de un compilador a otro - pero las relaciones de tamaños, no; esto es,

char  <=  short int  <=  int  <=  long int

Así que 'short int' puede ocupar 1 byte o más, pero no más de lo que ocupe 'int'.

Sospecho que querías preguntar por una estructura con campos de bits formados por 4 'char' comparada con una con campos formados por 1 'int' - si 'int' ocupe 4 bytes; por ejemplo,

struct stBitsChar
{
  unsigned char a: 2;  // 1º byte
  unsigned char b: 6;
  unsigned char c: 7;  // 2º byte
  unsigned char d: 8;  // 3º byte
  unsigned char e: 1;  // 4º byte
  unsigned char f: 5;
  unsigned char g: 2;
};

struct stBitsInt
{
  unsigned int a: 2;  // 1er int
  unsigned int b: 6;
  unsigned int c: 7;
  unsigned int d: 8;
  unsigned int e: 1;
  unsigned int f: 5;
  unsigned int g: 2;
};

La diferencia es el agrupamiento y las restricciones de tales grupos: cuatro octetos comparados con una sola secuencia contigua de 32. Con 4 grupos, accedes al grupo directa y explícitamente, pero no puedes rebasar la limitación del tamaño de cada campo. Con un bloque de 32 bits, tienes la facilidad de manipular cada secuencia en su totalidad (de 32 bits).

En el ejemplo anterior, 'stBitsChar' ocupa 4 bytes, pero existe un bit sin usar en el 2º byte, mientras que en 'stBitsInt' el bit sin usar es el primero o el último, según el compilador que uses.

En general, se usan las estructuras de campos de bits para tratar funcionamientos de muy bajo nivel, como por ejemplo los banderines y otras variables de estado del procesador u otro componente físico como la tarjeta gráfica. Si no necesitamos tal comunicación, entonces usaríamos tales estructuras para organizar los datos bajo un mismo concepto, que suele ser más legible que usar operaciones a nivel de bits para manipular supgrupos de bits. Por ejemplo, no necesitamos usar OR o AND para manipular 6 bits guardados en el medio de un entero de 8 bits:

0 11010 0

Tendríamos que usar OR para asignar esta secuencia de bits en esta posición. Si usáremos una estructura, sería más fácil; esto es,

struct bits
{
  unsigned char a: 1;
  unsigned char b: 6;
  unsigned char c: 1;
};
...
bits dato;

dato.b = 0x1A;  // 11010

Espero que todo esto aclare la duda.

Steven

wilber
2015-03-20 05:26:47

Ejercicio 1

#include <iostream>
#include <cstring>
using namespace std;

struct registro { 
   char Nombre[10];
   int Telefono;
} Par[10];
struct almacen {
	char GuardaNombre[10];
	char respuesta[4];
	int opcion;
	int GuardaTelefono;
} Par2;
 
int main()
{
   for(int z=0; z<10; z++) { 
   cout << "Ingrese el nombre: ";
   cin >> Par[z].Nombre;
   cout << "Ingrese el numero telefonico: ";
   cin >> Par[z].Telefono; 
   cout << "===========================================" << endl;
   }
   system("CLS");
  do {
   cout << "====================Menu===================" << endl;
   cout << "1)Buscar por nombre" << endl;
   cout << "2)Buscar por numero telefonico" << endl;
   cout << "3)Salir" << endl;
   cout << endl;
   cout << endl;
   cout << endl;
   cout << endl;
   cout << "Elija la opcion: ";
   cin >> Par2.opcion; 
   if(Par2.opcion == 1) {
   	cout << "Nombre: ";
    cin >> Par2.GuardaNombre;
    system("CLS");
   	for(int z=0; z<10; z++) {
   	   if(strcmp(Par2.GuardaNombre, Par[z].Nombre) == 0) cout << "=====Resultado=====" << endl << "Nombre: " << Par[z].Nombre << "  " << "Telefono: " << Par[z].Telefono << endl;
       }
   }
   if(Par2.opcion == 2) {
   	cout << "Telefono: ";
   	cin >> Par2.GuardaTelefono;
   	system("CLS");
   	for(int z=0; z<10; z++) {
   		if(Par2.GuardaTelefono == Par[z].Telefono) cout << "=====Resultado=====" << endl << "Telefono: " << Par2.GuardaTelefono << "  " << "Nombre: " << Par[z].Nombre << endl;
	   }   
   }
   if(Par2.opcion == 3) {
   	exit(0);
   }
   cout << "Desea continuar?: ";
   cin >> Par2.respuesta;
   system("CLS");
  } while(Par2.respuesta[0] == 's' || Par2.respuesta[0] == 'S');
  cout << endl;
  return 0;
}
wilber
2015-03-21 22:33:48

steven una pregunta

a que se refiere cuando dice esto "Los valores del campo5 estarán limitados entre 0 y 63" ?

Steven R. Davidson
2015-03-21 22:40:35

Hola Wilber,

Es el intervalo válido de enteros que se puede representar con 6 bits. El cálculo es 2^6 = 64 diferentes valores, y por tanto el intervalo es entre 0 y 63. Si intentas asignar un valor fuera de ese intervalo, sólo se guardarán los últimos 6 bits, porque 'campo5' sólo puede guardar 6 bits.

Espero que esto te oriente.

Steven

wilber
2015-03-22 01:46:35

Gracias steven ahora si la capte.

wilber
2015-03-24 01:30:32

Steven una ultima pregunta, en el problema 2 tengo que haces un campo de bits con variables char?, yo se que aca vienes a aprender y no pedir codigo pero te pido que me des un ejemplo sencillo para entyender porque los demas problemas dependen del problema 2 y no podre hacer los demas. te lo pido por favor.

Steven R. Davidson
2015-03-24 01:53:03

Hola Wilber,

El enunciado pide usar 'unsigned int', no 'char'. De hecho, dice: "Usar sólo un entero corto sin signo (unsigned short), es decir, un entero de 16 bits. Los nombres de los campos serán: dia, mes y anno".

Por cierto, por favor envía los ejercicios al correo-e: ejercicioscpp@conclase.net en lugar de presentarlos públicamente.

Espero que esto te ayude.

Steven

wilber
2015-03-24 02:09:28

we pero me has dicho todo lo que dice el problema 2, o solo es hacer el campo de bits y nada mas?. Si se me olvido lo del correo, el proximo lo mando.

Steven R. Davidson
2015-03-24 02:14:03

Hola Wilber,

Correcto. El ejercicio #2 sólo pide definir la estructura, 'fecha'; nada más. Obviamente, necesitarás diseñar la estructura correctamente, porque la necesitarás para los demás ejercicios de este capítulo.

Steven

wilber
2015-03-24 02:29:24

Gracias steven

Wilber
2015-06-19 01:54:25

Hola steven

Envie el problema al correo que me diste hace 1 mes pero no me responden.

Jesus Leyva
2015-07-07 22:59:57

Hola, tengo una pregunta, espero alguien me ayude... en windows y en una distro de GNU/Linux tengo mi sistema de 64bits he hecho este pequeño codigo :

#include <stdio.h>

typedef struct{
	char *type;
	char a;
	char *id;
        char b;
} A;

int main()
{
 printf("\nTAMAÑO DE UN INT %d", sizeof(int));/*4*/
 printf("\nTAMAÑO DE UN PUNTERO %d", sizeof(int *));/*4 en windows y 8 en GNU/Linux*/
 printf("\nTAMAÑO DE UN CHAR %d", sizeof(char));
 printf("\nTAMAÑO DE UNA ESTRUCTURA A %d", sizeof(A));/*16 en windows y 24 en linux*/
	return 0;
}

bien ahora si en las estructuras no existiera punteros, entonces tomaria el recorrido en multiplos de 4, pero en la existencia de un solo puntero en la estructura lo hace en multiplos de 8, esto pasa en GNU/Linux, en windows siempre toma multiplos de 4... y algo raro me pasa en windows... supuestamente un long ocupa 8 bytes, pero solo me muestra 4 bytes, lo mismo para el double...??? a que se debe estos resultados... Ojo mis dos sistemas son x64, el programa lo ejecuto en una misma computadora. Espero se me aclare esta duda... a y si no fuera mucha molestia se me explicase como podria crear una estructura algo compleja, que contenga punteros a char, pero estas que sean redimensionables con memoria dinamica, y en la funcion main crear un puntero a la clase, dicho de la misma manera, asignando memoria dinamica(malloc, realloc) GRACIAS DE ANTEMANO.!!!

Jesus Leyva
2015-07-08 01:32:55

Hola otra vez... dejo un pequeño codigo, por lo que veo el orden o desplazamientos que se hace en una estructura depende del tipo que contenga mas bytes, el tipo de mayor bytes, sera el que se tome como multiplo... ahora, bien con el codigo trato de entender como se ordenan los bytes de una estructura que contengan uno o mas punteros, me ayudarian a entender el porque cuando no son punteros va en orden, de un char salta una posicion, de un int 4... pero de un puntero... no se cuanto salta, al parecer no se puede saber... pero quisiera que alguien me fundamente ese punto de vista que tengo... y corregirme si es necesario. Gracias

#include <stdio.h>
#include <stdlib.h>
typedef struct{
	
	char a;
	char b;
	char *id;
	char *type;
	char e;
	char *otro;
	int c;
	char d;
	
} A;
int main()
{	size_t mem = sizeof(char)*4 + sizeof(char)*30 + sizeof(int)*1;
	A *a = (A*) (char*) malloc(mem);
	a->id = (char*) malloc (sizeof(char)*10);
	a->otro = (char*) malloc (sizeof(char)*10);
	a->type = (char*) malloc (sizeof(char)*10);
	
	printf("\nDIRECCION DE UNA ESTRUCTURA a\t %X", a);
	printf("\nTAMAÑO DE UNA ESTRUCTURA a\t %d", sizeof(*a));
	printf("\nDIRECCION DEL ELEMENTO a\t %X", &(a->a));/*x*/
	printf("\nDIRECCION DEL ELEMENTO b\t %X", &(a->b));/*x*/
	printf("\nDIRECCION DEL ELEMENTO id\t %X", a->id);/*x*/
	printf("\nDIRECCION DEL ELEMENTO type\t %X", a->type);/*x*/
	printf("\nDIRECCION DEL ELEMENTO e\t %X", &(a->e));/*x*/
	printf("\nDIRECCION DEL ELEMENTO otro\t %X", a->otro);/*x*/
	printf("\nDIRECCION DEL ELEMENTO c\t %X", &(a->c));/*x*/
	printf("\nDIRECCION DEL ELEMENTO d\t %X", &(a->d));/*x*/
	return 0;
}
Leonardo
2015-07-30 06:08:09

Hola, quisiera preguntar algo, hice el codigo completo tal cual al pie de la letra hasta el punto 5 y funciona pero se me ocurrio crear una nueva funcion para ingresar la fecha:

void IngresarFecha(fecha date)
{
    unsigned short int Aux;
    cout<<"por favor ingrese una fecha: "<<endl;//la primer fecha
    cout<<"año: ";cin>>Aux;Aux-=1960; date.anno=Aux;
    cout<<"Mes: ";cin>>Aux;date.mes=Aux;
    cout<<"Dia: " ; cin>>Aux;date.dia=Aux;
}

y no funcionó, entonces despues aplicando punteros (a punta de pruebas porque los punteros no los entiendo muy bien) la modifiqué y funcionó:

void IngresarFecha(fecha* date)
{
    unsigned short int Aux;
    cout<<"por favor ingrese una fecha: "<<endl;//la primer fecha
    cout<<"año: ";cin>>Aux;Aux-=1960; date->anno=Aux;
    cout<<"Mes: ";cin>>Aux;date->mes=Aux;
    cout<<"Dia: " ; cin>>Aux;date->dia=Aux;
}

la pregunta es porque no funcionó al primer intento si se supone que en:

struct fecha {
   unsigned short int dia:5;
   unsigned short int mes:4;
   unsigned short int anno:7;
}date1,date2;

date1 y date2 son variable globales y no se necesitan punteros. En que estoy mal.

Por favor una respuesta, gracias.

GINN
2016-11-01 00:48:54

Excelente trabajo lo que hacen en esta página. Estoy en esta página leyendo y practicando fuertemente, pero con las funciones printf y scanf, ya que nuestro profesor nos tiene esta limitante con respecto a estas dos funciones, mi pregunta es ¿por que ustedes recomienda el uso de cout y cin en vez del printf y scanf?

Con respecto a este contenido "Estructuras" quería mencionar que he estado practicando pero me he encontrado con un problema, en la parte de la asignacion de valores a las variables de la estructura. Es con los campos de bit a utilizar, al momento de guardar valores con el scanf no me lo permite sino que me lanza un error "[Error] attempt to take address of bit-field structure member 'fecha::dia'", es por ende que me siento trancado en esta parte. si me pudieran ayudar y ademas responderme la primera pregunta tambien, se los agradeceria. De antemano muchísimas gracias. Les dejo el código para que lo observen:

#include <stdio.h>

#define x 3

using namespace std;

struct fecha{

unsigned short int dia: 5;

int mes;

int anio;

};

struct fecha nac[x];

main(){

for(int i=0; i<x; i++){

printf("Ingrese dia de nacimiento: ");

fflush(stdin);

scanf("%d", &nac.dia); // Aqui es donde me mustra el error.

printf("Ingrese mes de nacimiento: ");

fflush(stdin);

scanf("%i", &nac[i].mes);

printf("Ingrese el ano de nacimiento: ");

fflush(stdin);

scanf("%d", &nac[i].anio);

}

return 0;

}

Steven R. Davidson
2016-11-22 17:36:27

Hola Ginn,

Se pueden usar las funciones (de ANSI C), 'printf()' y 'scanf()', más bien para una programación de bajo nivel (más cercana a la máquina), mientras que 'cout' y 'cin' (ANSI C++) ofrecen una programación de alto nivel. Por ejemplo, usando C,

char c;
int i;
float f;

scanf( "%c %d %f", &c, &i, &f );

printf( "El entero es: %d, el carácter es: '%c', y el número real es: %f\n", i, c, f );

En C++, escribiríamos,

char c;
int i;
float f;

cin >> c >> i >> f;

cout << "El entero es: " << i << ", el carácter es: '" << c << "', y el número real es: " << f << endl;

Hay otras diferencias notables, como por ejemplo, la nomenclatura de 'printf()' y 'scanf()' no es muy natural ni fluida, porque hace uso de una nomenclatura (en forma de cadena de caracteres), que hace referencia a los valores pasados por parámetro. Esto implica que no hay una tipificación fuerte por cada valor pasado por parámetro, por lo que puede ser de cualquier tipo de dato. La tipificación se realiza internamente homologando los especificadores con los parámetros de cada función. Esto crea una situación peligrosa por falta de tipificación. Usando 'cin' y 'cout', el compilador puede asegurar la tipificación para elegir el comportamiento específico para el valor (operando) basado en su tipo de dato.

La inclusión del fichero de cabecera, <iostream>, supone un aumento en el tamaño del ejecutable, mientras que la de <cstdio> es insignificante.

En cuanto al error que estás teniendo en tu código fuente, el problema se basa en que no puedes conseguir una dirección de memoria para un campo de bits. Recuerda que una dirección de memoria sirve para ubicar bytes, pero no bits. La solución es crear una variable auxiliar que sirva de intermediaria para luego asignar el valor guardado en el campo de bits. Por ejemplo,

unsigned short int dia;

scanf( "%hu", &dia );

nac[i].dia = dia;

Espero que esto te ayude.

Steven

Alex
2017-02-21 17:01:52

Tengo un error en la ejecución del código. Al hacer la búsqueda ya sea por nombre o por teléfono, si busco el último elemento de la estructura, número 3 en mi caso para hacerlo más rápido lo he limitado a 3 posiciones, me sale mal. Si busco el primero o el segundo no hay ningún problema y la ejecución es correcta.

El código que he utilizado es el siguiente:

#include <iostream>

#include <stdio.h>

#include <string.h>

using namespace std;

struct persona{

char Nombreyap[10];

char Numerotel[9];

} Plantilla[2];

void busportel (char Numtlf[9]);

void buspornom (char Nompers[10]);

char Numtlf[9]; char Nompers[10]; int i=0;

int main(){

int copcion;

//METEMOS LOS DATOS:

for(i=0;i<3;i++){

cout<<"Introduce los nombres y telefonos de 3 personas"<<endl;

cout<<"Nombre"<<i+1<<": "<<endl;

cin>>Plantilla[i].Nombreyap;

cout<<"Telefono"<<i+1<<": "<<endl;

cin>>Plantilla[i].Numerotel;

}

for(i=0;i<3;i++){

cout<<"Nombre"<<": "<<Plantilla[i].Nombreyap<<endl;

cout<<"Telefono"<<": "<<Plantilla[i].Numerotel<<endl;

}

//MENÚ PRINCIPAL

cout << "*****************************************************" << endl;

cout << " MENU PRINCIPAL " << endl;

cout << "*****************************************************" << endl << endl << endl;

cout << "Marque la opcion que desea realizar" << endl << endl;

cout << "1- Buscar por: Un numero telefonico" << endl;

cout << "2- Buscar por: El nombre de una persona" << endl;

cout << "3- Salir" << endl << endl << endl << endl << endl << endl << endl;

cin>>copcion;

while(1){

if (copcion==1){

cout<<"Introduzca el numero de tlf: "<<endl;

cin>>Numtlf;

busportel(Numtlf);

}

if (copcion==2){

cout<<"Introduzca el nombre de la persona: "<<endl;

cin>>Nompers;

buspornom(Nompers);

}

if (copcion==3){

cout<<"Saliendo del programa..."<<endl;

return 0;

}

if (copcion!=1&&copcion!=2&&copcion!=3){

cout<<"Introduce un numero del 1 al 3 por favor."<<endl;

}

}

return 0;

}

void busportel(char Numtlf[9]){

int aux=0;

bool vale=false;

for(i=0;i<3;i++){

if(strcmp(Numtlf,Plantilla[i].Numerotel)==0){

aux=i;

cout<<Plantilla[aux].Nombreyap<<endl;

cout<<Plantilla[aux].Numerotel<<endl;

vale=true;

}}

if(!vale){cout<<"Introduce un numero válido"<<endl;}

}

void buspornom(char Nompers[10]){

int aux=0; bool vale=false;

for(i=0;i<3;i++){

if(strcmp(Nompers,Plantilla[i].Nombreyap)==0){

aux=i;

cout<<Plantilla[aux].Nombreyap<<endl;

cout<<Plantilla[aux].Numerotel<<endl;

vale=true;

}

}

if(!vale){cout<<"Introduce un nombre valido"<<endl;}

}

ivan jesus
2018-06-19 17:00:50

hola, he leido su curso varias veces lo tengo en mi computadora, tengo 3 preguntas relacionadas para un lenguaje de programacion interpretado que estoy programando, y necesito un ayuda con esto que quiero intentar.

1) estaba biendo el tema de los campos de bits y se me ocurrio intentar utilizar esto o un array tipo unsigned char para controlar la representacion de los tipos de numeros ya sea int, float, double, en binario etc, mi objetivo con eso es simular un tipo generico al pasar el array como parametro de una funcion, o crearlo con memoria dinamica de este modo podria ofrecer en mi lenguaje el tipo struct y queria saber si esto es posible o hay alguna forma de hacerlo.

2) mi otra duda es si puedo controlar directamente el stack y los datos que se pasan, para ver si se puede pasar un array como parametro pero que cada elemento del array sean los parametros de la funcion.

3) mi otra duda esta relacionada con las clases, he creado una clase que actua como un tipo de dato generico

pero en el lenguaje se que voy a necesitar la direccion de memoria de la variable que estoy usando en la clase y no la direccion de memoria de la clase, estoy usando polimorfismo.

seria muy bueno sus ayudas pues no tengo a nadie a quien preguntar que sepa, cualquier ayuda la agradesco y su curso es genial de aqui aprendi todo lo que se de c++

ivan jesus
2018-06-19 22:25:47

hola de nuevo solo quiero decir que mi pregunta de los campos de bits no la contesten ya me di cuenta que si se puede despues de experimentar un rato, pero me surjio otra duda despues del experimento y es que en mi cumpu el bit menos significativo es el primero que de la estructura, mi pregunta es, al cambiar de procesador la forma en que se introducen los datos cambiara por la forma en que algunos procesadores guardan la informacion big-endian y little-endian por ejemplo si yo cambiara a otra computadora diferente que guardara la informacion por ejemplo como little-endian la forma de introducir los datos en la estructura cambiaria? haciendo que bit menos significativo sea el del final de la estructura?

ha, y otra pregunta con respecto a lo de controlar directamente el stack, se puede hacer sin usar el lenguaje ensamblador solo con c/c++?

gracias por cualquier ayuda que me puedan ofrecer :)