resueltos - listas enlazadas en c++ codigo fuente
Errores al compilar el ejemplo del libro ANSI C, capítulo Listas enlazadas (6)
Esta línea es incorrecta:
tele_typ *first; /* create a pointer to a structure */
Olvidó la palabra clave struct
.
Además, main
debería declararse como devolver un int
y finalizar con un return
.
Estoy sacando algunos ejemplos de un libro C anterior [A First Book of ANSI C] y estoy obteniendo un error al intentar compilar este código de ejemplo:
#include <stdio.h>
struct tele_typ {
char name[30];
char phone_no[15];
struct tele_typ *nextaddr;
};
main() {
struct tele_typ t1 = {"Acme, Sam", "(201) 555-6678"};
struct tele_typ t2 = {"Dolan, Edith", "(213) 682-3104"};
struct tele_typ t3 = {"Lanfrank, John", "(415) 718-4581"};
tele_typ *first; /* create a pointer to a structure */
first = &t1; /* store t1''s address in first */
t1.nextaddr = &t2; /* store t2''s address in t1.nextaddr */
t2.nextaddr = &t3; /* store t3''s address in t2.nextaddr */
t3.nextaddr = NULL; /* store the NULL address in t3.nextaddr */
printf("/n%s %s %s",first->name,t1.nextaddr->name,t2.nextaddr->name);
}
..y la salida de gcc newstruct.c -o newstruct
:
newstruct.c: In function ''main'':
newstruct.c:13:3: error: unknown type name ''tele_typ''
newstruct.c:15:9: warning: assignment from incompatible pointer type [enabled by default]
newstruct.c:20:28: error: request for member ''name'' in something not a structure or union
Es el capítulo 10.4 en las listas enlazadas. Hay un error en el libro? o ha cambiado algo en la gcc version 4.6.2 20120120 (prerelease)
estándar / gcc version 4.6.2 20120120 (prerelease)
? ¡Gracias!
No pude reproducir la primera advertencia; ¿Estás seguro de que el código que has pegado aquí es el código que te da la advertencia?
El unknown type name ''tele_typ''
error unknown type name ''tele_typ''
es fácil de arreglar: has declarado un tipo struct tele_typ
, pero no tienes la struct
al frente de la línea:
tele_typ *first; /* create a pointer to a structure */
Si cambias esto a:
struct tele_typ *first; /* create a pointer to a structure */
Se compilará sin error. (Y también sin advertencias en mi gcc-4.5.real (Ubuntu / Linaro 4.5.2-8ubuntu4) 4.5.2.)
Si desea compilar el cuerpo de la función exactamente como está, entonces también debería agregar:
typedef struct tele_typ tele_typ;
inmediatamente después de la definición struct tele_typ
:
struct tele_typ {
char name[30];
char phone_no[15];
struct tele_typ *nextaddr;
};
typedef struct tele_typ tele_typ;
Pero estoy un poco preocupado por un libro en C que no le da a la función main()
un tipo de devolución o parámetros escritos. int main(int argc, char* argv[])
o int main(int argc, char** argv)
es habitual, y cualquier libro que se desvíe de estas dos opciones me parece un poco extraño. El lenguaje de programación C es un buen libro; es difícil mejorarlo por su claridad y corrección. Considera cambiar al original.
Te estás perdiendo la ''estructura'' al comienzo de la 4ª línea de función principal. Debe leer
struct tele_typ *first;
Eso habría funcionado bien en C ++, ya que la palabra clave ''struct'' es opcional, pero en C es obligatorio.
Usar typedef definitivamente es el camino a seguir.
Solo una objeción: los subrayados dobles iniciales están reservados; NO deben ser utilizados por programadores de aplicaciones porque podrían causar problemas de espacio de nombres.
El libro de Kernahan & Ritche "The C Programming Language" es el mejor libro sin ninguno. Sin embargo, es un duro trabajo para el principiante. ¡El libro que la persona que publicó la pregunta obviamente está equivocado!
Debe cambiar la declaración de la estructura del puntero para algo como esto:
struct tele_typ *first; /* create a pointer to a structure */
Porque, como aún no ha definido la estructura tele_type
como un tipo directo, todavía tiene que señalarlo usando struct tele_typ
.
Si por el otro lado hubiera hecho algo como esto:
typedef struct TELE_TYP {
char name[30];
char phone_no[15];
struct TELE_TYP *nextaddr;
}tele_typ;
Habría podido llamar al tipo previamente definido y hubiera estado bien si hubiera escrito:
tele_typ *first;
Para resumir, el libro está equivocado: P
Su código tiene los siguientes errores, algunos de ellos menores.
main()
debe serint main(void)
. El formulariomain()
es una definición antigua; está obsoleto a partir del estándar ANSI C de 1989, y no cumple con los requisitos del estándar ISO C de 1999, que eliminó la regla "implicit imp". Al usar(void)
lugar de()
hace explícito quemain
no tiene parámetros; el formulario()
sigue siendo válido, pero ha quedado obsoleto desde 1989. Muchos compiladores de C aceptarán características antiguas como esta por razones de compatibilidad con versiones anteriores, pero al menos advertirán sobre ellas en el modo correspondiente. Debería descubrir cómo habilitar tales advertencias para su compilador.tele_typ *first;
necesita serstruct tele_typ *first;
. Este es el problema principal. (Agregar untypedef
es otra forma de evitar esto, pero es absolutamente innecesario. El código ya se refiere al tipo comostruct tele_typ
; solo tiene que hacerlo de manera consistente). Tenga en cuenta que en C ++ puede referirse al tipo ya sea comostruct tele_typ
o simplemente comotele_typ
- por supuesto, C ++ es un idioma diferente con diferentes reglas.Debería tener un
/n
al final de la cadena que imprime; no lo necesitas al principio.printf("%s %s %s/n",first->name,t1.nextaddr->name,t2.nextaddr->name);
Deberías tener una
return 0;
antes del cierre}
en su funciónmain
. A partir del estándar ANSI C de 1989 (o el estándar ISO C equivalente de 1990), caerse al final de la líneamain
sin devolver un valor devuelve un resultado indefinido al entorno de llamada. A partir de la norma de 1999, caerse al final de la líneamain
return 0;
implícitamentereturn 0;
, pero no hay daño en ser explícito al respecto.
Con las advertencias habilitadas, algunos compiladores pueden quejarse de la falta de inicializadores en las declaraciones de t1
, t2
y t3
, ya que no proporcionó valores para el miembro nextaddr
. Esto está bien, ya que (a) mientras tenga un inicializador, los miembros no especificados se inicializan a cero (en el caso de un puntero, a un puntero nulo), y (b) explícitamente asigna valores a estos miembros más adelante. .
Veo que estás usando gcc. Para obtener un buen conjunto de advertencias, puede usar esto:
gcc -ansi -pedantic -Wall -Wextra
Cambia el -ansi
a -std=c99
o -std=c1x
si deseas probar contra una versión más nueva del estándar C. Tenga en cuenta que usar -ansi
o una de las opciones -std=...
puede desactivar algunas extensiones no estándar. A veces necesitas escribir un código no portátil; en ese caso, puede soltar esa opción, y probablemente también el -pedantic
. Pero este programa no usa extensiones, y no necesita hacerlo.