¡Te damos la bienvenida a Scribd!
Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Documentos de Pasatiempos y Manualidades
Documentos de Crecimiento personal
Lenguaje C PDF
\n"}; Cuando una cadena de caracteres como ésta aparece en un progra sella cs a través de un apuntador a caracteres; printf recibe un apuntay del arreglo de caracteres Esto es, se tiene acceso a una cadena constante po apuntador a su primer elemento. [Las cadenas constantes no necesitan ser argumentos de funciones, Si pmessage se declara cono char “pmessage; ‘entonees la proposicién message = "ya or el tempo”; ‘signa a pmessage un apuntador al arreglo de caracteres. Esta no es la copia de luna cadena; s6lo concierse a apuntadores. El lenguaje C no proporciona ningin operador para procesar como unidad una cadena de caracteres Existe una importante diferencia entre estas definiciones: cchar amessage[ ] = "ya es el tiempo"; / arreglo «/ char spmessage = "ya os el tiempo"; /* apuntador +/ Amessage es un arreglo, suficientemente grande como para contener Ia secuencia feewrctiesy AAO a 2a Se pueden mouificarearactresindividua. '6 dno del aregl, peo amessage sempre se refer ala isn localad de ‘cenamiento. Por oto lado, pmessage es un apuntador, inicializado para ‘Dania a una eadena constante el apuntador puede modifcase posterionmente due apunte a alin otro lado, pero el resultado es indefinido si trata de mo- ificar et Poecsage: [—}—e[ ahora ov elena ] anessage: [ahora es 0IG APUNTADORES ¥ ARREGLOS ann APUNTADORES A CARACTERES Y FUNCIONES 117 lustraremos més aspects de los apuntadores los ateglos, estudiando jae ciclo. El efecto rederque lon caracteresss.co siones de dos utiles funciones adaptadas de funcién es strepy(e), que copia la cadena t a simplemente 8, pero esto copia el apun:ador, no los caracteres. Para cearacteres Se requiere de un ciclo. Primero esti la version con un arreglo. versién de eubindicas +/ “Samo restimen final, observe que una comparacién contra \O' es redundante, ‘que la pregunta es simplemente si la expresién es cero. Asi, la funcién po- ia escribirse correctamente como J+ stropy: copia t hacia old ainipyfchar va, abi + stropy: copia t hacia s; versién 3 con apuntadoros */ void strepy(char +5, char “t) { = while (*s+ + = t+ +) , la conveniencia de esta Puesto que se encontrar (0 puede parecer misterioso a primers iderable, y debe dominarse el en programas de C. feca esténdar () strepy, devuelve la cadena objetivo vin, ue examinaremos es stromp(s,{), que compara las cadenas regresa un valor negativo, cero 0 positivo sis es Iexicogratfi- igual a, o mayor que t. El valor se obtiene al restar los carac- teres de la primera posicion en que s y t no coinciden, (+ stromp: regresa 0 a1 s>t +/ int tromp(char +, char +!) Puesto que los argumentos se pasan por valor, stropy puede toss y t en la forma que le parezca mejor. Aqui hay apuntadores com mente iniiaizados, que se desplazan a lo largo del areglo un carécter a la \O' con que termina t se ha copiado a s. En la préctica, strepy no se escribiria como se mostré anteriormente. Los fan return sli] — ' J+ stropy: copia t hacia s; void strcpy(char +s, char { sién 2 con apuntadores +/ a versién con apuntadores de stremp: while (est = st4 +) I= 0) } Esto traslada el incremento de s y de t hada dentro de la parte de prucba d clo. Bl valor de *t-+ + es el cardcter al que apunta t ante118 APUNTADORES Y ARREGLOS Puesto que ++ y — son operadores prefijos o post ', Se presentan ot combinaciones de +, ++ y ——, aunque con menos frec cia. Por ejemplo, — disminuye p antes de traer el cardcter al que apunta. En efecto, la pareja de J+ meta val en la pila +/ J» saca el tope de ia pila y lo pone en val «/ son expresiones idiomiticas esténdar para meter y sacar algo de una pi Ia seccién 4.3, El header contiene declaraviones para las funciones que se en esta seccién, ademas de una variedad de otras funciones para mi de cadenas en Ia biblioteca estandar, Ejercicio 5-3. Escriba una versién con apuntadores de la funcién streat que ‘muestra en el capitulo 2: streat(s,) copia la cadena t al final de s. C rend(s,t, que regresa 1 si la cadena t se pr inal de la cadena, y cero si no « asi. © Ejercicio 5-5. Escriba versiones de las funciones de biblioteca stmomp, que operan con hasta los n primeros caracteres de sus argument ) copia hasta n caracteres de t hacia 8, Ei jones mas completas. © 56, Reescriba los pro} . empleando apuntador lo 3 se presento una funcin de ordenamiento Shell que podia’ lo de enteros, yen lo 4 se mejor6 con un quicksort 10 funcionard, excepto que akora se debe tratar con Iineas de tudes, y que, a diferencia de los enteros, no se pueden ibiar en una simple operacién. Se necesita una representacién de Aqui es donde entran los arreglos de apantadores. Si las lineas que se ¥ ordenar se almacenan juntas en un gran arreglo de earacteres, entonces s@ tener acceso a cada linea por medio de un apuntador a su primer cardcter- sBOCION 58 AKKEGLOS DE APUNTADORES; APUNTADORES A APUNTADORES 119 lado, los apuntadores se pueden almacenar en un arreglo, Dos lineas se pueden asando sus apuntadores a stremp. Cuando dos lineas desordenadas rcambian los apuntadores en el arreglo de apun- EE jina el doble problema de un manejo complicado de almacenamiento y roduciria al mover ne tFes pasos: proceso de ordenzmiento lee todas las lineas de entrada ‘ordénalas Jimprimelas en ordea apuntadores hi irada, puesto que esa informacién se req i. Debido a que la funcidn de entrada s6l cas, puede regresar alguna cuenta de ne que imprimir las lineas en el orden en que apare- arreglo de apuntadores. #include include ‘#define MAXLINES 5000 J+ max # de lineas por ordenar */ char ‘lineptr[MAXLINES]; _/* apuntadores a neas de texto */ ft ceadlines(char «linepte| old writelines(cha: “linept Void qeort(char “lineptl |, int let, int right); ‘+ ordona lineae de entrada +/ main) (120 APUNTADORES ¥ ARREGLOS worn ARREGLOS DE APUNTADORES; APUNTADORES A APUNTADORES 121 secc1ON 56 int lines; J+ mimero de ineas de entrada leidas «/ que indica que lineptr es un atteglo de MAXLINES elementos, cada uno de los ss un apuntador a char. Esto es, lineptr[i] es un api cs el cardcter al que apunta, el primer cardcter de readlinex(tinoptr, MAXLINES)) > = 0) { -D; wnitelines(lizeptr, tam 0; ombre de como un apuntador en la misma forma que en nuestros ejemplos anteriores (rrtelines puede escribirse en su lugar como or: entrada demasiado grande para ordenara\n") 1 waltelines: ei void wrtelinoe(c i while (alines— > 0) ‘deline MAXLEN 1000 + méx longitud de cua printl(%s\n", sineptr+ +); int geiline(char +, ini}; } Inicialmente *lineptr apunta a la primera linea; cada incremento lo avanza al si- (+ readlines: lee lineas de entrada +/ {int readlines(char slinepts{ |, int mazlines) ( ‘int Ion, lines; ‘char *p, line[MAXLEN]; jones deben modificarse, y la operacién de comparacién debe hacerse ‘a stromp. El algoritmo permanece igual, lo que nos da cierta confianza de que ain trabajard. len—l] = \0'; /+ elimina earécter nueva linea +/ strepy(, lin + no hace nada si el arreglo contiene */ ‘menos de doe elementos =/ ft + sight)/2); sswap(y, left, as) cgeor(y, left, last); gone, last +1, right) for () = 0; < mlines; i+ rinti("%e\n", linep ' La funcién getline se traté en la seccién 1.9, EI principal nuevo elemento es la declaracién para lineptr: cchar slineptr[MAXLINES] ina de i Poco sig + swap: inlercambia vii] y vil +/ void swap(char +], {122 APUNTADORES ¥ ARREGLOS carrtut spCcION 527 AARREGLOS MULTIDIMENSIONALES 123 leap = your¥s4 == 0 Gite yoas%6100 != 0 year%6400 = = 0; for (1 = 1;4 < month; 14 +) day += daytab[leap]til; return day; ano +/ 5 y dia a partir de dia Puesto que cual void month daylint year, int yearday, int *pmonth, int «pday cardcter, temp lemento individual de v (alias lineptr) es un apuntador debe serlo, de medo que uno pueda copiarse al otro, Ejercicio §-7. Reescriba readlines para almacenar lineas en un arreglo pr cionado por main, en lugar de llamar a alloc para obtener espacio de almac leap = yoar%d == 0 &6 year%100 != 0 ! year%400 = = 0; miento. {Cudnto més rapido es el programa? 0 ee a for (1 = 1; yoarday > yearday —= dayta spmonth = 3 spday = yearday; 5.7 Arreglos multidimensionale: EI lenguaje C proporciona arreglos muitidimensionales rectangulares, cen la préctica se usan menos que los arreglos de apuntadores. En esta s ‘mostraremos algunas de sus propiedades. Considérese el problema de la conversion de fechas, de dia del mes a dia ao y viceversa. Por ejemplo, el 1 de mazo es el 60° dia de un ano que no bisiesto, y el 61° dia de uno que silo es. Definamos dos funciones para hacer month_day, para que conversion: day_of_year convierte mes y dia en el dia del ano, convierte el dia del afio en mes y dia, Puesto que esta valores, 1os argumentos de mes y dia deben ser apuntadores: month day(1988, 60, &m, &d) hhace m igual a 2 yd igual a 2 ‘Ambas funciones dias de cada mes ( por mes difiere para ¥ Bo bsiestos, es mas facil separarlos en renglones de un arreglo ional quessiga la pista de lo q durante los célculos. El arreglo y las funciones que real son como se muestra a continuacién: static char daytab(2] (13] = { (0, 31, 28, 31, 30, 31, 20, 31, 31. 30, 31, 30, (0, 31, 29, 31, 30, 31, 30, 31, 31. 30, 31, 20, 31}, daytab es el primerarreglo de caracteres de dos dimensiones con el que hemos tratado. En C, un arrezlo de dos dimensiones es en realidad un arreglo unidimen- sional, cada uno de cuyos elementos es un arreglo, Por ello, los subindices se es- ciben como daytab| ‘+ [ronglén} {columaa] +/ cn lugar de ‘+ day-ol_year: obtiene dia del ato a partir de mes y atlo «/ int day-ot_year(int year, int month, iat day) 4 pasa a una funci el numero de columnas declaracién de pa- inti, leap; imiimero de renglo-APUNTADORES VS. ARREGLOS MULTIDIMENSIONALES 125 124 APUNTADORES ¥ ARREGLOS caprTuto seCCION 58 hi totum (n <1 {n> 12)? namo(0] ; name[n]; , La declaracién de name, que es un ar rma que [a de lneptr en el ejemplo del de cadenas de caracteres; cada una Los caractetes dk nes es itrelevante, puesto que lo que se pasaes, como antes, un apuntador @ arreglo de renglones, donde cada rengln es un arreglo de 13 ints. Es este particular, es un apuntador a objetos que son arreglos de 13 ints. Entonces, el arreplo daytab se pasara a la funcién f, a declaracién de f seria Sint daytab ‘También podria ser © podria ser | niimero corr que indica que el pardmetro es un apuntador a un arreglo de 13 enteros. Los rémesis son necesarios, puesto que los corchetes [tienen mas alta preced 5.9 Apuntadores vs. arreglos multidimensionales 1s nuevos usuarios de C algunas veces se confunden con la le dos dimersiones y uno de apuntadores, como name en el ejemplo rncia entre int +daylab (13) es un arreglo de 13 apuntadores a entero. De modo mas general, dimensién (subindice) de un arreglo queda abierta; todas las ot En la seccién 5.12 se discute mas acerca de declaraciones complicadas, i "4 entonces tanto afi ] son referencias sintdcticamente legitimas a co int, Per snte un arreglo de dos dimensiones: se le han asignado 200 localidades de tamafio de un int, y se emplea el célculo convencional de subindices rectangulares 20% renglén-+columna para encontrar elemento alrengl6n,columna]. Para b, sin embargo, la definicién s6lo asigna 10 apuntado- res y no los icializacién debe realizarse en forma expli stéticamente con cédigo. Suponiendo que cada elemento de b ap arreglo de veinte elemestos, entonces existiran 200 ints reservados, mas diez cel- das para los apuntadores. La ventaja importante del arreglo de apuntadores es pueden ser de longitudes diferentes. Esto es, m0 ¢s rcicio 5-8. No © Solucione ese defect fe deteccién de errores en day-of_year ni en mont o izacién de arreglos de apuntadores rese el problema de escribir una funcién month_name(n), que lor a una cadena de caracteres que contengan el nombre del n: ‘a es una aplicacién ideal para un arreglo static interno, mont contiene un arreglo reservado de cadenas de caracteres, y regresa un apunt a la cadena apropiada cuando se llama, Este seccién muestra como se inici ese arreglo de nombres, La fo a ningun. (05, el uso mas fre- s de anuntadores es para almacenar cadenas de cari como en la funcién month_name. Compare la declaracion J+ month name: regresa el nombre dei n-ésimo met +! ‘char *month name(int 2)126 APUNTADORES Y ARREGLOS con la de un arreglo bidimensional: b’, cchar aname| ] [15] = { "Mes ilegal", "Ene", “Feb”, “Mar” } 8 0 8 0 Ejercicio 5-9. Reescriba las rutinas day_ol_year y month_day empleando aj tadores en lugar de indices. 5.10 Argumentos en Ia linea de érdenes Dentro de un medio ambiente que maneje C hay una forma de pasar mentos en la linea de ordenes o de parimetros a un programa cuando empi ejecucion. Cuando se llama a main se le invaca con dos argumentos. El pri (llamado por conveneién arge, por argument count) sel niumero de argumei en la linea de ordenes con los que se invocé el programa; el segundo (argv, por gument vector) es un apuntador a un arreglo de cadenas de caracteres que et ne los argumentos, uno por cadena. Se acostumbra utilizar niveles mult \dores para manipular esas cadenas de caracteres. sjemplo mas set rograma echo, que desplicga sus argu inea de Ordenes en una linea, separsdos por blancos. Esto es, la of ‘echo hola, mundo imprime hola, mundo Por convencidn, argv(0] es el nombre con ef que se invocd el programa, que argc es por lo menos 1. Si argc es 1, entonce no hay argumentos en la después del nombre del programa. En el ejemplo anterior, arge es 3, y a1 “hola” y “mando”, respectivamente. El prit ‘gumento optativo es argv} y el altimo es argv[arge—1]; ademas, el quiere que argvlarge] sea un apuntador nulo. argy: -Lechon ] seC10N 5.10 ARGUMENTOS EN LA LINEA DE COMANDOS 127 La primera version de echo trata a argv como un arreglo de apuntadores a ca #include 1+ eco de los argumentos de la linea de érdenes; 1a. versién +/ ‘main(int argc, char ¢argv! J) ( } Como argv es un apunador a un arreglo de apuntadores, se pueden manipular ‘al apuntador en lugar ce indexar al arreglo. Esta siguiente variacién se basa en IF argv, que ¢s un apuntador a un apuntador a char, en tanto se dis fe los argumentos de la linea de érdenes; 2a. versién +) age, cher "ar uesto que argy es un apuntadar al inicio del arreglo de cadenas de argumentos, incrementarlo en 1 (+ +argu) lo hace apuntar hacia argv(1] en lugar de apuntar 4 argv(0]. Cada incremento sucesivo lo mueve al siguiente argumento; entonces “argv es el apuntador aese argumento. Al mismo tiempo, arge disminuye; cuan- 4o lesa a cero, no quedan argumentos por imprimir. En forma alternativa, podemos escribir la proposicién printf como print{(arge > 1)? "Ya": "9%", ++ + arev); Eso demuestra que el argumento de formato del printf también puede ser una presion Como un segundo ejemplo, hagamos algunas me; 28"4.1 que encuentra un patron. Si se recuerda, potundo del progra Farts la guia del BY €l patron que se debe encontrar se especifique por el primer areumento en la Mea de drdenes. yrograma de la sec nde busqueda en128 APUNTADORES ¥ ARREGLOS carn #include include ‘#define MAXLINE 1000 {int gotlino(char line, int max); J+ find: smprime lineas que coinciden con el patrén del Jer. argumento main(int argc, char *arav{ }) c cchar line[MARLINE]; int found = 0; i (arge I= 2) printi("Uso: find patrén\n"); alse while (getline(line, MAXLINE) > 0) Mf (steteline, aray{l] != NULL) { printf("%s", line); found+ +; return found } La funcién strstr(s,t) de la biblioteca esténda: regresa un apuntador a la pri cocurrencia de la cadena t dentro de la cadena s, 0 NULL si no exis sda linea impresa con su nimero de linea ‘Una convencién comiin para programas en C en sistemas UNIX es que un (*nimero") para solicitar la numeracién de lineas, entonces la orden find —x -n patrén cada linea que no coincida con el patrén, precedida por su numero’ Los argumentos para opciones deben ser permitidos en cualquier orden resto del programa debe ser independiente de! nimero de argumentos que ran presentes. Ademés, es conveniente para los usuarios que los argument las opciones puedan combinarse, como en find ~ax patron Aqui esta el programa: sgcc108 5.10 ARGUMENTOS EN LA LINEA DE COMANDOS 129 #include include ‘#doline MAXLINE 1000 (char ‘line, int max); Js find: imprime lineas que coinciden con el patrén del Ler. argumento +/ ‘main(int arge, char argv! J) 4 char line[MAXLINE); Jong lineno = 0; int ©, except = 0, number = 0, found = 0; while (—arge > 0 &é (++ +argv)[0] = = 9 while (¢ = ++ +aravi0)) umber = 1; break; defeat printi(“ind: opcién ilegal %c\n", ¢); arge = 0; found = ~2; Dreak; ‘while (gelline(line, MAXLINE) > 0) { linexo+ +; if ((tratx(line, vargv) |= NULL) != oxcopt) { f (oumber) return found; ) 1a S965 di ¥y argy se incrementa antes de cada argumento opcional. inal del ci 10 hay errores, argc dice cudntos argumentos permanecen,130 APUNTADORES ¥ ARREGLOS caPrTULo sin procesar y argy apunta al primero de éstos. Asi, arge debe ser Ly +argy det + +argv)[O} cs su primer cara En efecto, esto es lo que empleamos en el ciclo mAs interno, donde la tarea proceder a lo largo de una cadena especifice de argumentos. En el ciclo mas expresion *+ +argv{0] incrementa el apuntador argvi0] Es raro que se empleen expresiones con apuntadores més complicadas que tas; en tal caso, seré més intutivo separarlas en dos 0 tres pasos. Ejercicio 5-10. Escriba el programa expr, que evalia una expresién polaca im st a de ordenes, donde cada operador w operando es un argumento p separado. Por ejemplo, opr 234 + se evahia como 2 x G+4). 0 rcicio 5-11. Modifique el programa entab y detab (escritos como ejercicios de puntos de tabulacién como argu: los tabuladores habituales si no hay argumentos. © Ejercicio $-12, Extienda entab y detab de modo que acepten la abreviatura ‘entab-m + que indica puntos d in cada m columnas, i en la columna m. leccione el comportamiento por omisién més conveniente (para el usuario). Ejercicio 5-13. Escriba el programa tail, qu¢ imprime las ultimas n lineas entrada. Por omisién, 1s 10, digamos, pero puede madificarse con un argu {0 optativo, de modo que tal-n imprime las tiltimas 1 lineas. El programa debe comportarse en forma raci sin importar cuan poco razonable sea la entrada o el valor de n. Escriba el pr ma de manera que haga el mejor uso de la memoria disponible; las almacenarse como en el programa de ordenamiento de la seccién 5.6, no arreglo de dos dimensiones de tamaiio fijo. 5.11 Apuntadores a funciones En C, una funcién por si sola no es una variable, pero es posible definit tadores a funciones, que pueden asignarse, ser solocados en arreglos, pasados SECCION 5.11 modo que sise da el argum: APUNTADORES A FUNCIONES 131 snéricamente en lugar de lexicograti La comparacién lexicogrifica de do ‘es; también requeriremos de una ruti as y regrese la jones se declaran antes 1e los objetosesten en orden. las operaciones de comparaci ineas es realizada por stremp, como an- jumemp que compare el valor numérico .cidn que hace stremp. Bstas fun- de los errores en los argu: jos elementos principales. clude ‘#deline MAXLINES 5000 cchar +lineptr/MAXLINES); int readlines(char “linept void wrtelines(char slineptr| void qsort(void slineptr| J Js max # de liness 2 ordenar +/ 1+ apuntadores a lineas de texto */ int (comp) (void +, Int numemp(char *, char *); /» ordena linear de entrada +/ main(int argc, char ‘argv{ 1) { 1+ mximero de lineas de entrada leidas +/ J+ 1.81 08 ordenamionto numérico +/ int alines; int numeric = 0; (arge > 1 & stremplargy(l], "-n") = = 0) MAXLINES)) >= 0) { el (numeric ? numemp : stromp));132 APUNTADORES ¥ ARREGLOS ‘carro rada demasiado grande para ser ordenada\n"); En la llamada a qsort, stromp y numemp son direcciones de funciones. Ci se sabe que son funciones, el operador & no es necesario, en la misma forma tno es necesario antes del nombre de un arreglo. Hemos escrito qsort de modo que pueda procesar cualquier tipo de dato, slo cadenas de caracteres. Como se indice por la funcién prototipo, qsort es un arreglo de apuntadores, dos enteros y una funcién con dos argumentos de ti apuntador. Para los argumentos apuntadores se emplea el tipo de apuntador rico void +. Cualquier apuntador puede ser forzado a ser void * y resresa de nuevo sin pérdida de informacion, de modo que podemos llamar a qsort fe zando los argumentos a voids. Fl elaborado cast del argumento de la Fanci fuerza los argumentos de la funcion de comparacion. Esto generalmente tendra efecto sobre la representacion real, pero asegura al compilador que t if (left >= right) /+no hace nada si el arreglo contiene */ Las declaraciones deben estudiarse con cuidado, Eleuarto pardimetro de qsort int (comp) (void +, void +) Que indica que comp es un apuntador a una funcién qu; void * y regresa un El uso de comp SeCCION 5.1 APUNTADORES A FUNCIONES 133 te con la declaracion: comp es un apuntador a una funcién, *comp es is son necesarios para que los componentes sean correctamente asociados; sin ellos, int scomp(void +, void +) f+ INCORRECTO «/ indica que comp es una funcién que regresa un apuntador a int, lo cual es muy diferente. ‘Ya hemos mostrade stremp, que c ‘que compara dos cadenas numericamente, valor que include (> numemp: compara sl y 62 numéricamente */ int umemp(char *s1, char +52) { La funcién swap, que intercambia dos apuntadores, es idéntica a la que pre- Sentamos anteriormente en este capitulo, excepto en que las declaraciones se han cambiado a void +. ‘oid swap(void 4 Sint 5, int) } Puede agregarse una variedad dé lgunas se convierten en ejercicios opciones al programa de ordenamien- teresantes. Ejercicio 5-14. Modificue el programa de ordenamiento de modo que maneje na bandera x, que iadica ordenar en orden inverso (descendente). Asegurese que —x, trabaja con =n. 3134 APUNTADORES ¥ ARREGLOS carrrul las letras maysculas y miniis las durante el ordenamiento; Ejercicio 5-15. Agregue la opcién ~f para ign Jas, de modo que no se haga distincién ent ejemplo, al comparar, ay A son iguales. © jercicio 5-16. Agregue la opcién ~d (“orden de directorio”), que compara s was, nuimeros y blancos. Aseguirese de que trabaja en conjuncién conf. 0 jercicio 5-17. Agregue capacidad de manejo de campos, para que el order (0 se haga sobre campos de las lineas, caca campo ordenado de acuerdo con 10 independiente de opciones. (EI indice de este libro fue ordenado, las entradas y —n para los mimeres de pagina.) O 5.12 Declaraciones complicadas Al lenguaje C se le reprucba algunas veces por la sit icularmente las que involucran apuntadores a ful de haver que coincidan las declaraciones con » pero puede ser confusa para los dificiles, del sno pueden leerse de izquierda a derecha, y debido al exceso de uso de sis. La diferencia entre ‘+ f funcién que regresa un apuntador a int «/ int (ep ilustra el problema: « es un operador prefijoy tiene menor precedencia que ( ‘modo que los paréntesis son necesarios para obligar a una asociacién apropi ‘Aunque en la préctica es extrafio que aparezcan declaraciones verdad ¢ sadas, es importante saber como entenderlas y, si es nevesario, . Una buena forma de sintetizar decaraciones es en pequefios pasos , que se discute en la seccién 6.7. Como una alten presentaremos un par de programas que cenvierten de C valido a una dé cin verbal y viceversa, La descripcién verbal se lee de izquierda a derecha. La primera, del, es la més compleja. Cenvierte una declaracién de C en descripcién hecha con palabras, como en egos ejemplos: ‘(+ pf: apuntador a una funcién que regresa un int «/ chen sarge apuntador 4 unapuntador # char fuacién que regress apurtador a void srcciON 3.12 DECLARACIONES COMPLICADAS 135 comp: apuniador a una funcién que regresa void har (x 010. x: funcién cue regresa un apuniador a un arzeglol | de ‘apuntadores auna funciéa que regresa char char (+(x) x: arreglo[ de apuntadores a wna funcion que regresa ‘up apuntador a un arregio[8] de char del esti basada en la gramatica que especi en forma precisa en el apéndice A, seccién 8.5; ésta es una forma simplificada: considere este declarador: dt \ ] et | det-ir | detdir act ca un declarador, at puede emplearse para reconocer declaraciones, Por ejemplo, define136 APUNTADORES ¥ ARREGLOS ca El coraz6n del programa del es un par de funciones, del y dirdcl, que bben una declaracién de acuerdo con esta gramética. Debido a que la grami llaman recursivamente una a sel programa se conoce eonocen piezas de una ictico por descenso rei J+ del: reconoce una declaracién void del{veid) int ns; for (ns = 0; gettoken( ) /* euenia +6 */ dirdel( while (as strcaifout, “apuntador a); } J+ dirdel: reconoce un declarador directo */ ‘void dirdel(void) { int type; iM (lokentype == "(){ —fs (ech) +f while ((ype=gettoken( )) == PARENS | type = = BRACKETS) ‘modo que las declaraciones invalidas tambi dejan come ejetccios, ‘cupera mucho ante los lo confunden, Esas secC10N 5.12 DECLARACIONES COMPLICADAS 137 ‘Aqui estén las variables globales y la rutina principal: waclude #include #include ‘#deline MAXTOKEN 100 ‘enum { NAME, PARENS, BRACKETS }; {nt gettoken(void) int tokentypo; char token|MAXTOKEN]; cchar name[MAXTOKEN]; cchar datatype[MAXTOKEN]; nombre del identiicador + tipe de dato = char, int, while ((c = geteh()) == He == 40DECLARACIONES COMPLICADAS 139 138 APUNTADORES v ARREGLOS caprruto gf seccion $12 zotum tokentype = PARENS; } else { ungeteh(c); return tokentype = ‘( } else (6 == ‘19 for (p++ = ci (p++ = geteh( )) “p= "0; ‘P+ + = c;lsalnum(e = getch( ));) jo 5-20. Extiende del para que maneje declaraciones con tipos de argu- de funciones, ealificadores como const, etcétera, C se discutieron en el capitulo 4. en la direccién inversa, especialmente si no nos preocu Por la generacién de paréntesis redundantes. El programa undel convierte Aescripcién verbal como "x es una funcién que regresa un apuntador a un de apuntadores a funciones que regresan char”, que se expresaré como {La sintaxis abreviada de la entrada nos permite reutilizar ala funcién gettoken. Funcién undel también emplea las mismas variables externas que dol. /* undel: convierle una descripcién vetbal a declaracién «/ main( ) { int type; char temp(MAXTOKEN}; =n) ype = = BRACKETS)carituLoé: Estructuras Una estructura es una coleccién de una 0 mas variables, de tipos posiblemente diferentes, agrupadas bajo un solo nombre para manejo convenient fructuras se conocen como “records” en algunos otros lenguajes, p Pascal.) Las estructuras ayudan a organizar datos complicados, en particular dentro de programas grandes, debido a que permiten que a un grupo de relacionadas se les trate como una unidad en lugar de como entidades separadas. ‘Unejemplo tradicional de estructura es el registro de una némina: un emplea- do estd descrito por un conjunto de atributos, como nombre, domicilio, numero del seguro social, salario, etc. Algunos de estos atributos pueden, a su vez, ser estructuras: un nombre tiene varios componentes, como los tiene un domicilio y aiin un salario. Otro ejemplo, mas tipico para C, procede de las graticas: un pun- to es un par de coo-denadas, un rectangulo es un par de puntos, y otros casos semejantes. EI principal cambio realizado por el estiindar ANSI es la definicién de la asig- nacign de estructuras —las estructuras se pueden copiar y asignar, pasar a funcio- nes y ser regresadas por funciones. Esto ha sido manejado por muchos compiladores durante varios afios, pero las propiedades estin ahora definidas en forma precisa. Las estructuras y lot arreglas automaticos ahora también se pueden inicializar. 6.1 Conceptos basicos sobre estructuras Definamos alguras estructuras propias para graficacién. El objeto basico es ‘un punto, del cual supondremos que tiene una coordenada x y una coordenada 3 ambas enteras,