Nomenclatura de Lenguaje C++
Nomenclatura de Lenguaje C++
Nomenclatura de Lenguaje C++
Alerta
\b
Espacio atrs
\f
Salto de pgina
\n
Salto de lnea
\r
Retorno de carro
\t
Tabulacin horizonta
\v
Tabulacin vertical
\\
Barra invertida
\'
Comilla simple
\"
Comillas dobles
\OOO
Visualiza un carcter
\xHHH
Visualiza un carcter
Captulo 2.
Tipos bsicos y variables
Los tipos de datos bsicos definidos por C son caracteres, nmeros enteros y nmeros en
coma flotante. Los caracteres son representados por char, los enteros por short, int, long y
los nmeros en coma flotante por float y double. Los tipos bsicos disponibles y su
tamao son:
Char
Short
Int
Unsigned
Long
Float
Double
La palabra unsigned en realidad es un modificador aplicable a tipos enteros, aunque si no
se especifica un tipo se supone int. Un modificador es una palabra clave de C que indica
que una variable, o funcin, no se comporta de la forma normal. Hay tambin un
modificador signed, pero como los tipos son por defecto con signo, casi no se utiliza.
Las variables son definidas utilizando un identificador de tipo seguido del nombre de la
variable. Veamos el siguiente programa:
#include <stdio.h>
main()
{
float cels, farh;
farh = 35.0;
cels = 5.0 * ( farh - 32.0 ) / 9.0;
printf("-> %f F son %f C\n", farh, cels );
}
En el programa anterior se definen dos variables float, se asigna un valor a la primera y se
calcula la segunda mediante una expresin aritmtica. Las asignaciones en C tambin
son una expresin, por lo que se pueden utilizar como parte de otra expresin, pero segn
que prcticas de este tipo no son muy recomendables ya que reducen la legibilidad del
programa. En la instruccin printf, el smbolo %f indica que se imprime un nmero en
coma flotante.
Hay un tipo muy importante que se representa por void que puede significar dos cosas
distintas, segn su utilizacin. Puede significar nada, o sea que si una funcin devuelve
un valor de tipo void no devuelve ningn resultado, o puede significar cualquier cosa,
como puede ser un puntero a void es un puntero genrico a cualquier tipo de dato. Ms
adelante veremos su utilizacin.
Captulo 3.
Funciones
Un programa C est formado por un conjunto de funciones que al menos contiene la
funcin main. Una funcin se declara con el nombre de la funcin precedido del tipo de
valor que retorna y una lista de argumentos encerrados entre parntesis. El cuerpo de la
funcin est formado por un conjunto de declaraciones y de sentencias comprendidas
entre llaves. Veamos un ejemplo de utilizacin de funciones:
#include <stdio.h>
#define VALOR 5
Los distintos operadores permiten formar expresiones tanto aritmticas como lgicas. Los
operadores aritmticos y lgicos son:
+, ++, -*, /, %
>>, <<
&
|
^
~
!
==, !=
&&, ||
<, <=
>, >=
En estos operadores deben tenerse en cuenta la precedencia de operadores y las reglas
de asociatividad, que son las normales en la mayora de lenguajes. Se debe consultar el
manual de referencia para obtener una explicacin detallada. Adems hay toda una serie
de operadores aritmticos con asignacin, como pueden ser += y ^=.
En la evaluacin de expresiones lgicas, los compiladores normalmente
utilizan tcnicas de evaluacin rpida. Para decidir si una expresin lgica es cierta o
falsa muchas veces no es necesario evaluarla completamente. Por ejemplo una expresin
formada <exp1> || <exp2>, el compilador evala primero <exp1> y si es cierta, no evala
<exp2>. Por ello se deben evitar construcciones en las que se modifiquen valores de
datos en la propia expresin, pues su comportamiento puede depender de la
implementacin del compilador o de la optimizacin utilizada en una compilacin o en
otra. Estos son errores que se pueden cometer fcilmente en C ya que una asignacin es
tambin una expresin.
Debemos evitar: if (( x++ > 3 ) || ( x < y ))
y escribir en su lugar: x++; if (( x > 3 ) || ( x < y ))
Hay un tipo especial de expresin en C que se denomina expresin condicional y est
representada por los operadores ? : . Su utilizacin es como sigue: <e> ? <x> : <y>. Se
evala si e entonces x; si no, y.
int mayor ( int a, int b ) {
return ( a > b ) ? TRUE : FALSE;
}
waste_time () {
float a, b = 0.0;
( b > 0.0 ) ? sin(M_PI / 8) : cos(M_PI / 4);
}
Captulo 5.
Conversin de tipos
Cuando escribimos una expresin aritmtica a+b, en la cual hay variables o valores de
distintos tipos, el compilador realiza determinadas conversiones antes de que evale la
expresin. Estas conversiones pueden ser para 'aumentar' o 'disminuir' la precisin del
Se puede programar con un grupo de sentencias if then else anidadas, aunque ello puede
ser farragoso y de complicada lectura. Para evitarlo nos puede ayudar la sentencia switch.
Su utilizacin es:
switch (valor) {
case valor1: <sentencias>
case valor2: <sentencias>
...
default: <sentencias>
}
Cuando se encuentra una sentencia case que concuerda con el valor del switch se
ejecutan las sentencias que le siguen y todas las dems a partir de ah, a no ser que se
introduzca una sentencia break para salir de la sentencia switch. Por ejemplo:
ver_opcion ( char c )
{
switch(c){
case 'a': printf("Op A\n");
break;
case 'b': printf("Op B\n");
break;
case 'c':
case 'd': printf("Op C o D\n");
break;
default: printf("Op ?\n");
}
}
Setencia while
Otras sentencias de control de flujo son las que nos permiten realizar iteraciones sobre un
conjunto de sentencias. En C tenemos tres formas principales de realizar iteraciones. La
sentencia while (<e>) <s> es seguramente la ms utilizada. La sentencia, o grupo de
sentencias <s> se ejecuta mientras la evaluacin de la expresin <e> sea verdadera.
long raiz ( long valor )
{
long r = 1;
while ( r * r <= valor )
r++;
return r;
}
Una variacin de la sentencia while es: do <s> while ( <e> ); En ella la sentencia se
ejecuta al menos una vez, antes de que se evale la expresin condicional.
Setencia for
Otra sentencia iterativa, que permite inicializar los controles del bucle es la sentencia for
( <i>; <e>; <p> ) <s>. La sentencia for se puede escribir tambin como:
<i>;
while ( <e> ) {
<s>;
<p>;
}
El ejemplo anterior se podra escribir como:
long raiz ( long valor )
{
long r;
double x,y,z;
};
Los campos de cada registro son accesibles mediante el nombre del registro seguido de
punto y el nombre del campo, como por ejemplo venus.r.x = 1.0;. Cada campo se
comporta como lo hace su tipo bsico. C no proporciona mecanismos de inicializacin, ni
copia de registros, por lo que debe ser el programador el que los implemente.
A veces los datos se ajustan a series ordenadas en las cuales un elemento sigue, o
precede, a otro. Un caso tpico son los das de la semana. Si se desea realizar iteraciones
con los das de la semana una forma es, por ejemplo, asignar un nmero a cada da con
#define. C proporciona un mecanismo compacto para realizar esto; son las
enumeraciones. Una enumeracin toma la forma: enum nombre { lista de elementos };.
Veamos un ejemplo:
void planning ( void )
{
enum diasemana {lunes, martes, miercoles,
jueves, viernes, sabado, domingo };
int dia;
for ( dia = lunes; dia <= viernes; dia++ )
trabajar(dia);
if ( dia == sabado )
salir();
}
A cada elemento de la enumeracin se le asigna un valor consecutivo, comenzando por 0.
Si se desea que el valor asignado sea distinto se puede hacer de la siguiente forma:
enum puntos { t_6_25 = 3, t_zona = 2, t_libre = 1 };
Muchas veces es conveniente renombrar tipos de datos para que la escritura del
programa se nos haga ms sencilla y la lectura tambin. Esto se puede conseguir con la
palabra typedef. Con ella damos un nombre a cierto tipo, o combinacin de ellos.
typedef struct planeta PLANETA;
PLANETA mercurio, venus, tierra, marte;
Al igual que podemos inicializar las variables de tipos bsicos en la misma declaracin,
tambin lo podemos hacer con los registros. Los valores de cada campo de un registro
van separados por comas y encerrados entre llaves.
PLANETA mercurio = {{ 0.350, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
100,"Mercurio" };
Captulo 9.
Ambito de funciones y variables.
El mbito, o visibilidad, de una variable nos indica en que lugares del programa est
activa esa variable. Hasta ahora, en los ejemplos que hemos visto, se han utilizado
variables definidas en el cuerpo de funciones. Estas variables se crean en la memoria del
ordenador cuando se llama a la funcin y se destruyen cuando la funcin termina de
ejecutarse. Es necesario a veces, que una variable tenga un valor que pueda ser
accesible desde todas las funciones de un mismo fuente, e incluso desde otros fuentes.
En C, el mbito de las variables depende de dnde han sido declaradas y si se les ha
aplicado algn modificador. Una variable definida en una funcin es, por defecto, una
variable local. Esto es, que slo existe y puede ser accedida dentro de la funcin. Para
que una variable sea visible desde una funcin cualquiera del mismo fuente debe
declararse fuera de cualquier funcin. Esta variable slo ser visible en las funciones
definidas despus de su declaracin. Por esto, el lugar ms comn para definir las
variables globales es antes de la definicin de ninguna funcin. Por defecto, una variable
global es visible desde otro fuente. Para definir que existe una variable global que est
definida en otro fuente tenemos que anteponer la palabra extern a su declaracin. Esta
declaracin nicamente indica al compilador que se har referencia a una variable
declarada en un mdulo distinto al que se compila.
Las variables locales llevan implcito el modificador auto. Este indica que se crean al inicio
de la ejecucin de la funcin y se destruyen al final. En un programa sera muy ineficiente
en trminos de almacenamiento que se crearan todas las variables al inicio de la
ejecucin. Por contra, en algunos casos es deseable. Esto se consigue anteponiendo el
modificador static a una variable local. Si una funcin necesita una variable que
nicamente sea accedida por la misma funcin y que conserve su valor a travs de
sucesivas llamadas, es el caso adecuado para que sea declarada local a la funcin con el
modificador static. El modificador static se puede aplicar tambin a variables globales.
Una variable global es por defecto accesible desde cualquier fuente del programa. Si, por
cualquier motivo, se desea que una de estas variables no se visible desde otro fuente se
le debe aplicar el modificador static. Lo mismo ocurre con las funciones. Las funciones
definidas en un fuente son utilizables desde cualquier otro. En este caso conviene incluir
los prototipos de las funciones del otro fuente. Si no se desea que alguna funcin pueda
ser llamada desde fuera del fuente en la que est definida se le debe anteponer el
modificador static.z
void contar ( void )
{
static long cuenta = 0;
cuenta++;
printf("Llamada%ld veces\n", cuenta );
}
Un modificador muy importante es const. Con l se pueden definir variables cuyo valor
debe permanecer constante durante toda la ejecucin del programa. Tambin se puede
utilizar con argumentos de funciones. En esta caso se indica que el argumento en
cuestin es un parmetro y su valor no debe ser modificado. Si al programar la funcin,
modificamos ese parmetro, el compilador nos indicar el error.
#define EULER 2.71828
const double pi = 3.14159;
double lcercle (const double r )
{
return 2.0 * pi * r;
}
double EXP ( const double x )
{
return pow (EULER, x );
}
double sinh (const double x )
{
return (exp(x) - exp(-x)) / 2.0;
}
Debemos fijarnos que en el ejemplo anterior pi es una variable, la cual no podemos
modificar. Por ello pi slo puede aparecer en un nico fuente. Si la definimos en varios, al
linkar el programa se nos generar un error por tener una variable duplicada. En el caso
en que queramos acceder a ella desde otro fuente, debemos declararla con el modificador
extern.
imprimir_char(*p);
}
Definimos un vector de N_PLA componentes de tipo PLANETA. Este tipo est formado
por un registro. Vemos que en la funcin de inicializacin del vector el puntero a la primera
componente se inicializa con el nombre del vector. Esto es una caracterstica importante
de C. La direccin de la primera componente de un vector se puede direccionar con el
nombre del vector. Esto es debido a que en la memoria del ordenador, los distintos
elementos estn ordenados de forma ascendente. As, SSolar se puede utilizar como
&SSolar[0]. A cada iteracin llamamos a una funcin que nos inicializar los datos de cada
planeta. A esta funcin le pasamos como argumento el puntero a la componente en curso
para que, utilizando la notacin ->, pueda asignar los valores adecuados a cada campo
del registro. Debemos fijarnos en el incremento del puntero de control de la iteracin, p++.
Con los punteros se pueden realizar determinadas operaciones aritmticas aunque, a
parte del incremento y decremento, no son muy frecuentes. Cuando incrementamos un
puntero el compilador le suma la cantidad necesaria para que apunte al siguiente
elemento de la memoria. Debemos fijarnos que esto es aplicable slo siempre que haya
distintas variables o elementos situados consecutivamente en la memoria, como ocurre
con los vectores.
De forma similar se pueden utilizar funciones que tengan como parmetros punteros, para
cambiar el valor de una variable. Veamos:
void intercambio ( void ) {
int a, b;
a = 1;
b = 2;
swap( &a, &b );
printf(" a = %d b = %d\n", a, b );
}
void swap ( int *x, int *y ) {
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
La sintaxis de C puede, a veces, provocar confusin. Se debe distinguir lo que es un
prototipo de una funcin de lo que es una declaracin de una variable. As mismo, un
puntero a un vector de punteros, etc...
int f1(); funcin que devuelve un entero
int (*pf2)(int *pi); puntero a funcin que toma un puntero a entero y devuelve un
entero
int (*apf[5])(int *pi); vector de 5 punteros a funcin que toman un puntero a entero y
devuelven un entero.
En los programas que se escriban se debe intentar evitar declaraciones complejas que
dificulten la legibilidad del programa. Una forma de conseguirlo es utilizando typedef para
redefinir/renombrar tipos.
typedef int *intptr;
typedef intptr (*fptr) ( intptr );
fptr f1, f2;
Captulo 11.
El Preprocesador.
El preprocesador es una parte del compilador que se ejecuta en primer lugar, cuando se
compila un fuente C y que realiza unas determinadas operaciones, independientes del
propio lenguaje C. Estas operaciones se realizan a nivel lxico y son la inclusin de otros
textos en un punto del fuente, realizar sustituciones o eliminar ciertas partes del fuente.
Debemos tener en cuenta que el preprocesador trabaja nicamente con el texto del fuente
y no tiene en cuenta ningn aspecto sintctico ni semntico del lenguaje.
El control del preprocesador se realiza mediante determinadas directivas incluidas en el
fuente. Una directiva es una palabra que interpreta el preprocesador, que siempre va
precedida por el smbolo # y que est situada a principio de lnea.
La directiva #define se utiliza para definir una macro. Las macros proporcionan
principalmente un mecanismo para la sustitucin lxica. Una macro se define de la forma
#define id secuencia. Cada ocurrencia de id en el fuente es sustituida por secuencia.
Puede definirse una macro sin una secuencia de caracteres. Una macro se puede
"indefinir" mediante la directiva #undef.
#define MSG01 "SCI-I-START: Starting system kernel\n"
#define MSG02 "SCI-I-STOP: Stopping system kernel\n"
void print_msg ( void ) {
if ( check_state() == START ) printf(MSG01);
else printf(MSG02);
}
El estado de una macro, si est definida o no, se puede comprobar mediante las
directivas #ifdef y #ifndef. Estas dos directivas se deben completar con una #endif y, el
texto comprendido entre ambas es procesado si la macro est definida. Todas las
directivas deben ser completadas en el mismo fuente y pueden ser anidadas.
#ifndef M_PI
#define M_PI 3.1415927
#endif
El preprocesador nos permite tambin incluir tambin otros ficheros en un fuente C. Esto
se consigue con la directiva #include. Esta puede tomar tres formas: #include , #include
"fichero" y #include macro. La diferencia entre la primera y la segunda est en el lugar
dnde se buscar el fichero en cuestin. Normalmente se utiliza la primera para ficheros
proporcionados por la librera del compilador y la segunda para ficheros creados por el
programador.
Captulo 12.
Funciones de entrada/salida.
En este apartado y los siguientes vamos a ver algunas de las funciones ms importantes
que nos proporcionan las libreras definidas por ANSI y su utilizacin. Como hemos visto
hasta ahora, el lenguaje C no proporciona ningn mecanismo de comunicacin ni con el
usuario ni con el sistema operativo. Ello es realizado a travs de las funciones de librera
proporcionadas por el compilador.
El fichero de declaraciones que normalmente ms se utiliza es el stdio.h. Vamos a ver
algunas funciones definidas en l.
Una funcin que ya hemos utilizado y que, ella y sus variantes, es la ms utilizadas para
la salida de informacin es printf. Esta permite dar formato y enviar datos a la salida
estndar del sistema operativo.
#include <stdio.h>
int printf ( const char *format [, argumentos, ...] );
Acepta un string de formato y cualquier nmero de argumentos. Estos argumentos se
aplican a cada uno de los especificadores de formato contenidos en format. Un
especificador de formato toma la forma %[flags][width][.prec][h|l] type. El tipo puede ser:
d, i
un carcter
imprime el carcter %
puntero
blank
si es positivo, imprime un es
0n
imprime un entero sh
Otra funcin similar a printf pero para la entrada de datos es scanf. Esta toma los datos de
la entrada estndar del sistema operativo. En este caso, la lista de argumentos debe estar
formada por punteros, que indican dnde depositar los valores.
#include <stdio.h>
int scanf ( const char *format [, argumentos, ...] );
Hay dos funciones que trabajan con strings. La primera lee un string de la entrada
estndar y la segunda lo imprime en el dispositivo de salida estndar.
#include <stdio.h>
char *gets ( char *s );
int puts ( char *s );
Tambin hay funciones de lectura y escritura de caracteres individuales.
#include <stdio.h>
int getchar ( void );
int putchar ( int c );
Veamos, por ejemplo, un programa que copia la entrada estndar a la salida estndar del
sistema operativo, carcter a carcter.
#include <stdio.h>
main()
{
int c;
while ( (c = getchar()) != EOF )
putchar(c);
}
Accin
ignora espacios en operaciones de lectura
ajusta la salida a la izquierda
ajusta la salida a la derecha
deja hueco despus del signo o el indicador de
internal
base
dec
conversin a decimal
oct
conversin a octal
hex
conversin a hexadecimal
showbase muestra el indicador de base en la salida
muestra el punto decimal en salidas en punto
showpoint
flotante
uppercase muestra las salidas hexadecimales en maysculas
showpos muestra el signo '+' en enteros positivos
muestra los nmeros en punto flotante en
scientific
notacin exponencial
fixed
unitbuf
stdio