Professional Documents
Culture Documents
Manual para
Usuario de
Turbo C++
2.3 CONSTANTES
2.4 DECLARACIONES
2.5 OPERADORES ARITMETICOS
2.6 OPERADORES LOGICOS Y DE RELACION
2.7 TIPOS DE CONVERSION
2.8 OPERADORES DE INCREMENTO Y DECREMENTO
2.10 OPERADORES Y EXPRESIONES DE ASIGNAMIENTO
2.11 EXPRESIONES CONDICIONALES
2.12 PRECEDENCIA Y ORDEN DE EVALUACION
4.1 BASICS
4.2 FUNCIONES QUE DEVUELVEN VALORES NO ENTEROS.
4.3 MAS SOBRE ARGUMENTOS DE FUNCIONES
4.4 VARIABLES EXTERNAS
4.5 ALCANCE DE LAS REGLAS
4.6 VARIABLES ESTATICAS
4.7 VARIABLES REGISTRO
4.8 ESTRUCTURA DE BLOQUE
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
4.9 INICIALIZACION
4.10 RECURSION
4.11 EL PROCESADOR C
6.1 BASICOS
6.2 ESTRUCTURAS Y FUNCIONES
6.3 ARREGLOS DE ESTRUCTURAS
6.4 PUNTEROS PARA ESTRUCTURAS
6.5 ESTRUCTURA REFERENCIAL POR SI MISMA
6.6 TABLA Lookup
6.7 CAMPOS
6.8 UNIONS
6.9 Typedef
CAPITULO 1 INTRODUCCION
main ()
{
printf (" hola , Freddy\n ");
}
main ()
{
printf ("hola, ");
printf ("Freddy");
printf ("\n");
}
main ()
{
int lower,upper,step;
float fahr,celsius;
lower = 0;
upper = 300;
step = 20;
fahr = lower;
while ( fahr <= upper ) {
celsius = (5.0 / 9.0)*(fahr - 32.0);
printf ("%4.0f %6.1f\n",fahr,celsius);
fahr = fahr + step ;
}
}
lower = 0;
upper = 300;
step = 20;
fahr = lower;
La razón para usar 5.0 / 9.0 en lugar de la simple forma 5/9 es que
en C como en muchos otros lenguajes, la división de enteros es truncada.
Un punto decimal en una constante indica que esta es de punto flotante,
así es como 5.0 / 9.0 es 0,555.... que es lo que se desea. También
escribimos 32.0 en vez de 32, aunque sin embargo fahr es una variable
float, 32 seria automáticamente convertido a float antes de la
sustracción.
Veamos ahora el asignamiento
fahr = lower;
y la pregunta
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
printf("%4.0f %6.1f\n"fahr,celsius);
main()
{
int fahr;
for (fahr = 0; fahr <= 300; fahr = fahr + 20)
printf ("%4d %6.1f\n",fahr,(5.0 / 9.0)*(fahr - 32));
}
main()
{
int fahr;
c = getchar();
putchar(c);
COPIANDO ARCHIVOS
{
int c;
c = getchar ();
while (c != EOF ) {
putchar (c);
c = getchar ();
}
}
#define EOF -1
o
#define EOF 0
c = getchar()
c = getchar() != EOF
es equivalente a
c = (getchar() != EOF)
CONTANDO CARACTERES
La instrucción
++nc;
CONTANDO LINEAS
CONTANDO PALABRAS
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
#define YES 1
#define NO 0
nl = nw = nc = 0;
if ( expresión )
declaracion-1
else
declaracion-2
1.6 ARREGLOS
main ()
{
int c,i,nwhite,nother;
int ndigit[10];
nwhite = nother = 0;
for (i = 0;i < 10;++i)
ndigit[i] = 0;
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
++ndigit[c-'0'];
else if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
else
++nother;
printf ("dígitos = ");
for ( i = 0; i < 10; ++i)
printf ("%d ",ndigit[i]);
printf ("\n espacios en blanco = %d,otros = %d\n",
nwhite,nother);
}
c - '0'
Esto trabaja solo si '0', '1', etc. son positivos en orden creciente
si hay solo dígitos entre '0' y '9'. Afortunadamente esto es verdadero
para todos los conjuntos de caracteres convencionales.
Por definición, la aritmética envuelve a char's e int's
convirtiendo todo en int antes de proceder, Así las variables char y
constantes son escencialmente idénticas a int's en el contexto
aritmético. Esto es bastante natural y conveniente; por ejemplo c -
'0' es un entero con valor entre cero y nueve correspondiendo a los
caracteres '0' y '9' almacenado en c, es así una subindicacion valida
para el arreglo ndigit.
La decisión referente a si un carácter es un dígito, un espacio en
blanco, o algo mas es hecho por la secuencia
El modelo
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
if (condición)
instrucción
else if ( condición)
instrucción
else
instrucción
else if (condición)
instrucción
1.7 FUNCIONES
main ()
{
int i;
for (i = 0; i < 10; ++i)
printf ("%d %d %d\n",i,power(2,i),power(-3,i));
}
power (x,n)
int x, n;
{
int i,p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * x;
return (p);
}
int x, n;
int x,n;
{
int p;
max = 0;
while ((len = getline(line, MAXLINE)) >0)
if (len > max) {
max = len ;
copy (line,save);
}
if (max > 0) /* hubo una línea */
printf ("%s",save);
}
char s ;
int lim;
"hello\n"
pueden tener acceso directo a ellas. Lo mismo ocurre con las variables
en otras funciones; por ejemplo, la variable i en getline no esta
relacionada con la i en copy. Cada una de las variables locales va
dentro de una rutina solo cuando la función en existencia es llamada y
desaparecera cuando la función es dejada de lado. Es por esta razón
que tales variables son usualmente conocidas como variables automaticas,
siguiendo la terminologia de otros lenguajes usaremos el termino
automatico de aquí en adelante para referirnos a estas variables locales
dinamicas.(En el cap.4 discutiremos las clases de almacenaje estatico,
en las cuales las variables locales retienen sus valores entre la
invocacion de funciones)
Porque las variables automaticas van y vienen con la invocacion de
una función, ellas no retienen sus valores desde una llamada a la
próxima, y deben estar explicitamente sobre cada entrada de un set. Si
ellas no están en un set, contendran basura.
Como una alternativa para variables automaticas, es posible definir
variables, que son externas para todas las funciones, esto es, variables
globales que pueden ser accesadas por el nombre de alguna función.(Este
mecanismo es semejante al Fortran common o al pl/1 external) Porque
las variables externas son globalmente accesibles, pueden ser usadas en
vez de listas de argumentos para comunicar datos entre funciones.
Además porque las variables permanecen en existencia permanentemente,
mas bien que apareciendo y desapareciendo mientras que las funciones son
llamadas y dejadas de lado, ellas retienen sus valores aun después que
el set de funciones es ejecutado.
Una variable externa es definida fuera de una función. Las
variables deben ser declaradas también en cada función que se desee
accesar; esto puede ser hecho por una declaración explicita extern o
implicita en el contexto. Para hacer mas concreta la discusion, nos
permitiremos reescribir el programa de las líneas mas largas con line,
save y max como variables externas. Esto requiere cambiar los
llamados, declaraciones, y cuerpos de las tres funciones.
int len;
extern int max;
extern char save[];
max = 0;
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
int c,i;
extern char line ;
line [i] = c;
if ( c == '\n') {
line [i] = c;
++i;
}
int i;
extern char line[], save[];
i = 0;
while ((save[i] = line[i]) != '\0')
++i;
}
agregado de extern.
En ciertas circunstancias, la declaración extern puede ser omitida:
si la definición externa de una variable ocurre en el archivo fuente
antes de usarla en una función particular, entonces no hay necesidad de
una declaración extern en la función. Las declaraciones extern en
main, getline y copy son así redundantes. En efecto, en la practica
comn es ubicar definiciones de todas las variables externas al comienzo
del archivo fuente, y entonces omitir todas las declaraciones extern.
Ud. debería notar que hemos usado cuidadosamente las palabras
declaración y definición cuando nos referimos a variables externas en
esta seccion. Definición se refiere al lugar donde la variable es
actualmente creada o asignada a un almacen, declaración se refiere al
lugar donde la naturaleza de la variable es declarada pero no
almacenada.
De esta forma, hay una tendencia para hacer todo con miras a una
variable extern porque esto parece simplificar las comunicaciones ( las
listas de argumentos son cortas y las variables están siempre ahi cuando
Ud. las requiera. Pero las variables externas están siempre ahi aun
cuando Ud. no las requiera).
short int x;
long int y;
unsigned int z;
---------------------------------------------------------------
DEC PDP-11 HONEYWELL 6000 IBM 370 INTERDATA 8/32
ASCII ASCII EBCDIC ASCII
2.3 CONSTANTES
int y float son constantes que ya han sido dispuestas, excepto para
notar que la usual
123.456e-7
o
0.12E3
seconds = 60 * 60 * hours;
o
"" /* un string nulo */
Las comillas no son parte del string, pero solo sirven para delimitarlo.
Las mismas secuencias de escape utilizadas por caracteres constantes
son aplicables en strings; \" representa el carácter de doble comilla.
Técnicamente un string es un arreglo cuyos elementos son caracteres
simples. El compilador automáticamente ubica el carácter nulo \0 al
final de cada string, así los programas pueden encontrar
convenientemente el final. Esta representaci¢n significa que no hay un
limite real para cuan largo puede ser un string, pero hay programas para
buscar y determinar completamente su largo.
La siguiente funci¢n strlen(s) devuelve el largo del string de
caracteres s excluyendo el ultimo \0.
{
int i;
i=0;
while(s[i] != '\0')
++i;
return(i);
}
2.4 DECLARACIONES
int lower;
int upper;
int step;
char c;
char line[1000];
x%y
Así a+(b+c) puede ser evaluado como (a+b)+c. Esto raramente hace
alguna diferencia, pero si un orden particular es requerido deben
explicitarse las variables temporales que deban ser usadas.
== !=
(c =getchar()) != '\n'
if (!inword)
en vez de
if (inword == 0)
int i,n;
n = 0;
for (i=0; s[i] >= '0' && s[i] <= '9'; ++i)
n = 10 * n + s[i] - '0';
return(n);
}
s[i] - '0'
char c;
c = getchar();
if (c == EOF)
...
int i;
char c;
i = c;
c = i;
x=i
i=x
(tipo_de_nombre) expresi¢n
sqrt((double)n)
if (c == '\n')
++nl;
x = n++;
pone en x un 5, pero
x = ++n;
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
if (c == '\n')
nl++;
if (s[i] != c) {
s[j] = s[i];
j++;
}
if (c == '\n') {
s[i)]= c;
++i;
}
if (c == '\n')
s [i++] = c;
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
int i, j;
i = j = 0;
c = n & 0177;
x = x | MASK
x & ~077
i=i+2
i += 2
e1 op= e2
es equivalente a
e1 = (e1) op (e2)
x *= y + 1
es actualmente
x = x * (y + 1)
x=x*y+1
for (b = 0; n != 0 ; n >>= 1)
if ( n & 01)
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
b++;
return(b);
}
yyva(yypv(p3+p4) + yypv(p1+p2)) += 2
Las instrucciones
if (a > b)
z = a;
else
z = b;
e1 ? e2 : e3
z = (a > b) ? a : b ; /* z = max(a,b) */
(n > 0) ? f : n
operador asociatividad
Â
() [] -> . izqu. a der.
! ++ -- -(tipo) * & sizeof der. a izqu.
* / % izqu. a der.
+ - izqu. a der.
<< >> izqu. a der.
< <= > >= izqu. a der.
== != izqu. a der.
& izqu. a der.
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
^ izqu. a der.
| izqu. a der.
&& izqu. a der.
|| izqu. a der.
?: der. a izqu.
= += -= etc. der. a izqu.
, (cap.3) izqu. a der.
Á
x = f() + g();
++n;
printf("%d %d \n", n, power(2,n));
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
a [i] = i++;
/*Rolando = Corima*/
3.1 INSTRUCCIONES Y BLOCKS
Una expresión tal como x=0, i++ o printf("...") llega a ser una
instrucción cuando es seguida por un punto y coma, como en :
x = 0;
i++;
printf("...");
3.2 IF - ELSE
if (expresión)
instruccion-1
else
instruccion-2
if (expresión)
en lugar de
if (expresión != 0)
if (n > 0)
if (a > b)
z = a;
else
z = b;
if (n > 0) {
if (a > b)
z = a;
}
else
z = b;
La ambiguedad es especialmente perniciosa en situaciones como :
if (n > 0)
for (i = 0; i < n;i++)
if (s[i] > 0) {
printf (...);
return(i);
}
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
else
printf("error-n es cero\n");
if (a > b)
z = a;
else
z = b;
3.3 ELSE - IF
La construcción :
if (expresión)
instrucción
else if (expresión)
instrucción
else if (expresión)
instrucción
else
instrucción
else
instrucción
puede ser omitido, o puede ser usada para chequear un error o hallar una
condición "imposible".
Para ilustrar una decisión triple, hay una función de busqueda
binaria que decide si un particular valor de x se encuentra en el
arreglo v, ordenado. Los elementos de v pueden estar en orden
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
3.4 SWITCH
case '6' :
case '7' :
case '8' :
case '9' :
ndigit[c - '0']++;
break;
case ' ' :
case '\n' :
case ' \' :
nwhite ++;
break;
default :
nother++;
break;
}
printf ("dígitos = ");
for (i = 0; i < 10; i++)
printf ("%d",ndigit[i]);
printf ("\n espacios en blanco= %d, otros =
%d\n",nwhite,nother);
}
while (expresión)
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
instrucción
La instrucción for
for (exp1;exp2;exp3)
instrucción
es equivalente a
exp1;
while (exp2) {
instrucción
exp3;
}
for ( ;; ) {
...
}
do
instrucción(es)
while (expresión);
3.7 BREAK
break;
line[n+1] = '\0';
printf("%s\n",line)
}
}
3.8 CONTINUE
for (...)
for (...) {
...
if( desastre)
goto error;
}
...
error :
borrar - mensaje
goto found;
/* no lo encuentra */
...
found:
/* encuentra uno en la posición i,j */
...
found = 0;
for (i = 0; i < N && !found; i++)
for (j = 0; j < M && !found; j++)
found = v[i][j] < 0;
if (found)
/* el elemento estuvo en i-1, j-1 */
...
else
/* no encontrado */
...
4.1 BASICS
producira la salida
char line[MAXLINE];
while (getline(line, MAXLINE) > 0)
if (index(line,"the") >= 0)
printf("%s",line);
}
dummy()
la que no hace nada.(una función que no hace nada es til a veces como
un lugar de espera durante el desarrollo del programa.) El nombre de
la función puede ser precedido también por un type si la función
devuelve alguna otra cosa en vez de un valor entero; este es el tipico
de la próxima seccion.
Un programa es justamente un conjunto de funciones definidas
individualmente. La comunicación entre las funciones es (en este
caso) por argumentos y valores devueltos por las funciones; también
puede ser via variables externas. Las funciones pueden ocurrir en
algn orden en el archivo fuente.
sign = 1;
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
sum = 0;
while (getline(line, MAXLINE) > 0)
printf (" t%.2f n",sum += atof(line));
La declaración
double sum,atof();
dice que sum es una variable double, y que atof es una función que
devuelve un valor double. Como una nemotecnica, sugerimos que sum y
atof(...) son ambos valores de punto flotante de doble precisión.
A menos que atof este explicitamente declarado en ambos lugares, C
asume que devuelve un entero, y entregara respuestas sin sentido. Si
atof mismo y la llamada para el, en main, son tipeados incompatiblemente
en el mismo archivo de origen, será detectado por el compilador. Pero
si (como es mas probable) atof fue compilado separadamente, la
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
double atof();
return(atof(s));
return("expresión")
(1 - 2) * (4 + 5) =
es entrada como
12-45+*=
int type;
char s MAXOP ;
double op2, atof(), pop(), push();
case NUMBER :
push(atof(s));
break;
case '+' :
push(pop() + pop());
break;
case '*' :
push(pop() * pop());
break;
case '-' :
op2 = pop();
push(pop() - op2);
break;
case '/' :
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("división por cero n");
break;
case '=' :
printf(" t%f n",push(pop()));
break;
case 'c' :
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
clear();
break;
case TOOBIG :
printf("%.02s...es demasiado largo
n",s);
break;
default :
printf("comando desconocido %c n",type);
break;
if (sp > 0)
return (val --sp );
else
printf("error : stack vacío n");
clear();
return(0);
sp = 0;
int sp = 0;
double val MAXVAL ;
double push(f) ...
double pop() ...
clear() ...
entonces las variables val y sp pueden ser usadas en push, pop y clear
simplemente nombrandolas; las declaraciones no son necesitadas mas alla.
Si una variable externa es referida antes, esta es definida, o si
es definida en un archivo fuente diferente desde uno donde est siendo
usado, entonces es obligatoria una declaración extern.
Es importante distinguir entre la declaración de una variable
externa y su definición. Una declaración anuncia las propiedades de
una variable (su tipo, largo, etc.); una definici¢n tambi‚n provoca el
almacenaje para ser asignada. Si las líneas
int sp;
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
declaran para el resto del archivo fuente que sp es un int y que val es
un arreglo double (cuyo largo es determinado en otra parte), pero ellas
no crean las variables o les asignan almecenaje.
Allí debe estar solo una definición de una variable externa entre
todos los archivos que completan el programa fuente; otros archivos
pueden contener declaraciones extern para declararlo. (Allí también
puede estar una declaración extern en el archivo conteniendo una
definición.) Alguna inicializacion de una variable externa va solo con
la definición. Los largos de los arreglos deben ser especificados con
la definición, pero son opcionales con una declaración extern.
Aunque no es probable una organizacion para este programa, val y sp
pudieron ser definidas e inicializadas en un archivo, y las funciones
push, pop y clear definidas en otro. Entonces estas definiciones y
declaraciones deberian ser necesarias para enlazarlas juntas :
en archivo1 :
en archivo2 :
int i, c;
Hemos usado un arreglo para los devueltos, mejor que un simple carácter,
ya que la generalidad puede entrar manualmente, mas tarde.
getch() ...
ungetch(c) ...
register int x;
register char c;
y as¡ la parte int puede ser omitida. register puede ser aplicado s¢lo
a variables automticas y a los parmetros formales de una funci¢n. En
este £ltimo caso la declaraci¢n tiene el efecto
f(c,n)
register int c,n;
register int i;
...
if(n > 0)
int i; /* declara un nuevo i */
for (i = 0; i < n; i++)
...
int x;
f()
double x;
...
int z;
f(z)
double z;
...
4.9 INICIALIZACION
int x = 1;
char squote = ' '';
long day = 60 * 24; /* minutos en el d¡a */
binary(x,v,n)
int low = 0;
int high = n-1;
int mid;
...
en lugar de
binary(x,v,n)
int x, v ,n;
low = 0;
high = n-1;
...
nwhite = nother = 0;
for(i = 0; i < 10; i++)
ndigit i = 0;
...
int nwhite = 0;
int nother = 0;
int ndigit 10 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;
int c, i;
...
4.10 RECURSION
char s 10 ;
int i;
if(n < 0)
putchar('-');
n = -n;
i = 0;
do
s i++ = n % 10 + '0'; /* encuentra pr¢ximo
carácter */
while((n /= 10) > 0); /* descartarlo */
while(--i >= 0)
putchar(s i );
int i;
if(n < 0)
putchar('-');
n = -n;
if((i = n/10) != 0)
printd(i);
putchar(n % 10 + '0');
4.11 EL PROCESADOR C
INCLUSION DE ARCHIVOS
include "nombre-archivo"
SUSTITUCION MACRO
define YES 1
define then
define begin
define end ;
y entonces escribir
if (i > 0) then
begin
a = 1;
b=2
end
ahora la línea
x = max(p + q, r + s);
px = &x;
y = *px;
px = &x;
y = *px;
y = x;
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
int +px;
dice que en una expresión atof(), y *dp tienen valores del tipo double.
Ud. debería también notar la implicacion en la declaración, que un
puntero esta restringido a un punto de un genero particular de objeto.
Los punteros pueden ocurrir en expresiones. Por ejemplo, si px
apunta al entero x, entonces *px puede ocurrir en algn contexto donde x
podria ocurrir.
y = *px + 1
y = *px + 1
los operadores unarios * y & ligan mas apretadamente que los operadores
aritmeticos, así estas expresiones toman todo lo que apunte px, suma 1,
y lo asigna a y. Volveremos dentro de poco para ver que significado
podria tener :
y = *(px + 1)
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
*px = 0
pone un cero en x, y
*px += 1
py = px
swap(a, b);
swap(x, y) /*WRONG*/
int x, y;
int temp;
temp = x;
x = y;
y = temp;
swap(&a, &b);
int temp;
temp = *px;
*px = *py;
*py = temp;
int c, sign;
Por todo getint, *pn es usado como una variable intPb ordinaria. Hemos
también usado getch y ungetch (descrito en el cap.4) así el carácter
extra que debe ser leído puede ser devuelto a la entrada.
int a 10
int *pa
entonces el asignamiento
pa = &a 0
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
x = *pa
copiara el contenido de a 0 en x.
si pa apunta a un elemento particular de un arreglo a, entones por
definición pa+1 apunta al próximo elemento, y en general pa-i apunta i
elementos antes de pa, y pa+i apunta i elementos después. Así, si pa
apunta a a 0 ,
*(pa+1)
pa = &a 0
pa = a
int n;
char s ;
char *s;
f(&a 2 )
f(a+2)
f(arr)
int arr ;
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
...
f(arr)
int *arr;
...
p<q
p+n
Este hecho puede ser usado paara escribir otra versi¢n de strlen:
char *p = s;
while(*p)
p++;
el arreglo de caracter.
Los arreglos de caracter en curso no necesitan ser argumentos de
funci¢n. Si message es declarado como
char *message
entonces la instrucci¢n
s=t
strcpy(s, t) /* copia t a s */
char s , t ;
int i;
i = 0;
while ((s i = t i ) != ' 0)
i++;
Porque los argumentos son pasados por valor, strcpy puede usar s y t en
la forma que guste. Aqu¡ los punteros son convenientemente
inicializados, que son puestos en marcha a lo largo de los arreglos un
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
while(*s++ = *t++)
;
int i;
i = 0;
while (s i == t i )
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
strcmp(s, t)
char *s, *t;
*++p
*--p
primero decrementa p.
strcpy(p,s);
retun(p);
char *p;
int i, leap;
*/
int year, yearday, *pmonth, *pday; /* desde dia del
a|o */
int i, leap;
day_tab i j
mejor que
day_tab i, j
f(day_tab)
int day_tab 2 13 ;
...
int day_tab 13 ;
int (*day_tab) 13 ;
ya que los punteros son variables, Ud. pudo esperar que fuera usado
para arreglos de punteros. Verdaderamente, este es el caso.
Ilustraremos escribiendo un programa que sortear un set de l¡neas de
texto en orden alfab‚tico; una versi¢n de UNIX el utilitario sort.
Esto est donde el erreglo de punteros enteros. Si las l¡neas a
ser sorteadas son almacenadas completamente en un gran arreglo de
caracteres (mantenido por alloc, quizs), entonces cada l¡nea puede ser
accesada por un puntero para su primer caracter. Los mismos punteros
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
define NULL 0
define LINES 100 /* mximo de l¡eas a ser
sorteadas */
else
printf("entrada demaciada grande para sortear
n");
nlines = 0;
while ((len = getline(line, MAXLEN)) > 0)
if(nlines >= maxlines)
return(-1);
else if ((p = alloc(len)) == NULL)
return(-1);
else
line len-1 = ' 0'; /* zap newlines */
strcpy(p, line);
lineptr nlines++ = p;
return(nlines);
int i;
for (i = 0; i < nlines; i++)
printf("%s n", lineptr i );
int gap, i, j;
char *temp;
int a 10 10 ;
int *b 10 ;
es dado, la l¡nea es
hola, mundo
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
int i;
for (i = 1; i < argc; i++)
printf("%s %c", argv i , (i < argc - 1) ?
' ': ' n');
sta versi¢n muestra que el formato de argumento de printf puede ser una
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
int argc;
char *argv ;
find -x -n the
con la entrada
if (argc != 1)
printf ("uso: encuentra -x -n modelo
n");
else
while (getline(line, MAXLINE) > 0)
lineno++;
if ((index(line, *argv) >= 0) !=
except)
if (number)
printf ("%1d: ", lineno);
printf ("%s", line);
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
argv es decrementado antes de cada argumento opcional, y argc. Si no hay errores, el final
del loop argc ser¡a 1 y
*argv apuntar¡a al modelo. Notar que *++argvpb es un puntero para un
argumento string; (*++argv) 0 es su primer caracter. Los par‚ntesis
son necesarios, porque sin ellos la expresi¢n ser¡a *++(argv 0 ), que es
completamente diferente ( y equivocada). Una forma alternativa vlida
ppdr¡a ser **++argv.
int gap, i, j;
int(*comp)()
dice que comp es un puntero para una funci¢n que devuelve un entero.
El primer conjunto de par‚ntesis son necesarios; sin ellos
int *comp()
(*comp)(v j , v j+gap )
v1 = atof(s1);
v2 = atof(s2);
if (v1 < v2)
return(-1);
else if (v1 > v2)
return(1);
else
return(0);
char *temp;
temp = *px;
*px = *py;
*py = temp;
Hay una variedad de otras opciones que pueden ser sumadas al programa de
sorteo.
_
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
CAPITULO 6 ESTRUCTURAS
6.1 BASICOS
struct date {
int day;
int month;
int year;
int yearday;
int mon_name[4];
};
seguida por una lista de variables, justo como para algun tipo basico.
Esto es,
struct { ... } x, y, z;
es sintacticamente analogo a
int x, y, z;
struct date d;
define una variable d que es una estructura del tipo date. Una
estructura externa o estatica puede estar inicializada por la siguiente
definicion con una lista de inicializadores para componentes:
structura-nombre . miembro
d.mon_name[0] = lower(d.mon_name[0]);
struct person {
char name[NAMESIZE];
char address[ADRSIZE];
long zipcode;
long ss_number;
double salary;
struct date birthdate;
struct date hiredate;
};
entonces
emp.birthdate.month
hiredate.yearday = day_of_year(&hiredate);
day = pd->day;
leap = pd->year % 4 == 0 && pd->year % 100 != 0
!! pd->year % 400 == 0;
for (i = 1; i < pd->month; i++)
day += day_tab leap i ;
return(day)
La declaracion
pd->year
p->miembro-de-estructura
(*pd).year
p->q->memb
emp.birthdate.month
son
(p->q)->memb
(emp.birthdate).month
pd->month = i;
struct
int x;
int *y;
*p;
entonces
++p->x
Pero el mismo hecho que los arreglos son paralelos indican que una
organizacion diferente es posible. Cada keyword es realmente un par:
char *keyword;
int keycount;
y hay un arreglo de pares. La declaracion de estructura
struct key
char *keyword;
int keycount;
keytab NKEYS ;
struct key
char *keyword;
int keycount;
;
struct key
char *keyword;
int keycount;
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
keytab =
"break", 0,
"case", 0,
"char", 0,
"continue", 0,
"default", 0,
/* ... */
"unsigned", 0,
"while", 0,
;
"break", 0 ,
"case", 0 ,
define MAXWORD 20
int n, t;
char word MAXWORD ;
low = 0;
high = n-1
while (low <= high)
mid = (low+high) / 2;
if((cond = strcmp(word;tab mid .keyword)) <0 )
high = mid-1;
return(-1);
sizeof(objeto)
admite una cantidad entera para el tamano del objeto especificado. (La
magnitud esta dada en unidades sin especificar los llamados "bytes", que
son de la misma magnitud como un char). El objeto puede ser una
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
int c, t;
break;
p->keycount++;
for (p = keytab; p < keytab + NKEYS; p++)
if (p->keycount > 0)
printf("%4d %s n", p->keycount,
p->keyword);
int cond;
struct key *low = &tab 0 ;
struct key *high = &tab n-1 ;
struct key *mid;
return(NULL);
mid = (low+high) / 2
struct key *
binary(word, tab, n)
busqueda lineal para cada palabra como ellas arrivan, para ver si `stas
han sido vistas; el programa tomar^a siempre. (M#s precisamente, su
esperado funcionamiento se desarrollar~a cuadricalmente con el n^mero de
palabras en la entrada.) ]C}mo podr~amos organizar el dato para copiar
eficientemente con una lista de palabras arbitrarias?.
Una soluci}n es la de guardar el conjunto de palabras v~stas hasta
ahora sorteadas en toda momento, para localizar cada palabra hasta su
propia posici}n en el orden como arriban. Esto no podr~a ser hacho
para trasladar palabras en un arreglo lineal, sin embargo usar~amos un
dato de estructura llamado un #rbol binario.
El #rbol contiene un "nodo" por palabra ; cada nodo contiene
El nodo no puede tener m#s que dos hijos; `ste podr~a tener s}lo un 0 o
un 1.
Los nodos son mantenidos as~ que cualquier nodo el sub#rbol
izquierdo contiene s}lo palabras que son menores que la palabra en el
nodo, y el sub#rbol derecho contiene s}lo las palabras m#s grandes.
Para descubrir si una nueva palabra ya esta en el #rbol, en un comienzo
en el origen y comparar la nueva palabra con la palabra almacenada en el
nodo. S~ ellos concuerdan, la pregunta es respondida afirmativamente.
Si la nueva palabra es menor que la palabra del #rbol, la busqueda hasta
el hijo izquierdo; de otro modo el hijo derecho es investigado. Si no
hay hijo en la direcci}n requerida, la nueva palabra no est# en el
#rbol, y en efecto el propio place gor it to be is missing child.
Este busca procesos que estan inherentemente recursivos, ya que la
busqueda desde alg^n nodo usa una busqueda de sus hijos. Por
consiguiente, rutinas recursivas para inserci}n e impresi}n ser#n m#s
natural.
Partiendo hacia la descripci}n de un nodo, este es claramente una
estructura con 4 componentes.
define MAXWORD 20
main() /* cuenta frecuencia de la palabra */
root = NULL;
while ((t = getword(word, MAXWORD)) != EOF)
if (t == LETTER)
root = tree(root, word);
treeprint(root);
if (p != NULL)
treeprint(p->left);
printf("%4d %s n", p->count, p->word);
treeprint(p->right);
char *p;
entonces
(struct tnode *) p
char *alloc();
define YES 1
inword = YES;
int hashval;
if(strcmp(s, np->name) == 0)
return(np); /* lo encontr} */
return(NULL); /* no encontrado */
return(NULL);
hashval = hash(np->name);
np->next = hashtab hashval ;
hahstab hashval = np;
else /* ya aqu~ */
free(np->def); /* definici}n previa libre */
if ((np->def = strsave(def)) == NULL)
return(NULL);
return(np);
6.7 CAMPOS
define KEYWORD 01
define EXTERNAL 02
define STATIC 04
(Los n^meros deben ser de dos sifras). Entonces accesando los bits
llega a ser un asunto de "bit-fiddling" con el cambio, encubrimiento, y
completando operadores que descubrimos en el cap.2.
Ciertos modismos aparecen frecuentemente :
vuelve a apagarlo, y
struct
unsigned is_keyword : 1;
unsigned is_extern : 1;
unsigned is_static : 1;
flags;
Esto define una variable llamada flags que contiene un #rbol de campo
1-bit. El n^mero que sigue a los dos puntos representa el campo con
anchura en bits. Los campos son declarados unsigned para enfatizar que
ellos realmente son cantidades no se|aladas.
Individualmente los campos son refernciados como flags.is_word,
flags.is_extern, etc, justo como otros mienbros de la estructura. Los
campos se portan como peque|os, enteros no se|alados, y pueden
participar en expresiones aritm`eticas como otros enteros. As~ los
ejemplos previos pueden ser escritos m#s naturalmente como
flags.is_extern = flags.is_static = 1;
flags.is_extern = flags.is_static = 0;
para cerrarlos; y
para consultarlos.
Un campo no puede cruzar sobre un int l~mite; si la anchura
causar~a esto para sucedr, el campo es alineado al pr}ximo int l~mite.
Los campos no necesitan ser nombrados; los campos no nombrados son
usados para rellenar. El ancho especial 0 puede ser usado para forzar
alineamiento al pr}ximo int l~mite.
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
6.8 UNIONES
Una union es una variable que puede ocupar (en diferentes momentos)
objetos de diferentes tipos y tama¤os, con el compilador preserva la
pista del tama|o y alineamientos requeridos. Las unions proporcionan
una manera de manipular diferentes clases de datos en una simple area de
almacen, sin encajar en alguna m#queina dependiente una informaci}n en
el programa.
Como un ejemplo, ora vez desde un compilador tablas de s~mbolos,
supone que constantes pueden ser int's, float's o punteros de
caracteres. El valor de una constante en particular debe ser
almacenada en una variable del mismo tipo, sin embargo esto es m#s
conveniente para manejar una tabla si el valor ocupa la misma cantidad
de almacenaje y es almacenado en el mismo lugar sin tomar en
consideraci}n de este tipo. Este es el prop}sito de una union - para
proveer una simple variable que puede letimamnete ocupar alguna vez
varios tipos. Como con los campos, la sint#xis est# basada en
estructuras.
union u_tag
int ival;
float Fval;
char *pval;
uval;
union-nombre.miembro
union-puntero->miembro
if (utype == INT)
printf ("%d\n", uval.ival);
else if (utype == FLOAT)
printf ("%f n", uval.fval);
else if (utype == STRING)
printf ("%s n", uval.pval);
else
printf ("mal tipo %d en utype n ", utype);
struct
char *name;
int flags;
int utype;
union
int ival;
float fval;
char *pval;
uval;
symtab NSYM ;
symtab i .uval.ival
*symtab i .uval.pval
6.9 Typedef
Similarmente, la declaracion
TREEPTR talloc()
char *alloc();
return((TREEPTR) alloc(sizeof(TREENODE)));
crea el tipo PFI, puntero "para la funcion que devuelve enteros", que
puede ser usado en contexto como
#include <stdio.h>
prog <infile
causa que prog lea infile em lugar del terminal. Los switching de la
entrada estan hechos de tal manera que el prog mismo es olvidado por el
cambio; en particular, el string "<infile" no esta incluido en el
argumento de la linea de comando en argv. La entrada de switching es
tambien invisible si la entrada viene desde otro programa via una
llamada de mecanismo; la linea de comando
otherprog | prog
prog >outfile
CURSO DE TURBO C++ L.I. LEONARDO GASTELUM ROMERO
prog | anotherprog
#include <stdio.h>
int i;
float x;
char name [50];
scanf("%d %f %s", &i, &x, name);
25 54.32E-1 Thompson
int i;
float x;
char name [50];
scanf ("%2d %f %*d %2s", &i, &x, name);
con la entrada
#include <stdio.h>
scanf("%d", n);
en vez de
scanf("%d", &n);
c = getc (fp)
putc (c,fp)
segundo argumento.
Con estos preparativos, ahora estamos en posicion para escribir el
programa cat para concatenar archivos. El diseno basico es uno que ha
sido encontrado conveniente para muchos programas; si hay argumentos de
linea de comando, ellos son procesados en orden. Si no hay
argumentos, la entrada standard es procesada. De esta forma el
programa puede ser usado en una sola posicion o como parte de un gran
proceso.
#include <stdio.h>
}
else {
filecopy(fp);
fclose(fp);
}
}
#include <stdio.h>
#include <stdio.h>
register int c;
register char *cs;
cs = s;
while (--n > 0 && (c = getc(iop)) != EOF)
if ((*cs++ = '\n')
break;
*cs = '\0';
return((c == EOF && cs == s) ? NULL : s);
}
while (c = *s++)
putc(c, iop)
}
UNGETC
ungetc(c, fp)
SISTEMA DE LLAMADA
system("date");
causa que el programa date sea corrido; este imprime la fecha y hora del
dia.
calloc(n, sizeof(objeto))
devuelve un puntero para bastante espacio para pbn objetos del largo
especificado, o NULL si el requerimiento no puede ser satisfecho. El
almacenaje esta inicializado en cero.
El puntero tiene el alineamiento propio para el objeto en cuestion,
pero esto seria lanzado en el tipo apropiado, como en
char *calloc();
int *ip;