Conceptos Básicos de C




Elementos del lenguaje

Comenzaremos viendo los elementos mas simples que integran un programa escrito en C++, es decir palabras, sımbolos y las reglas para su formacion.

1.     Identificadores

Son nombres elegidos por el programador para representar entidades (variables, tipos, constantes, procedimientos, modulos) en el programa. El usuario puede elegir cualquier identificador excepto un peque no grupo que se reserva para usos especıficos.

C++ distingue entre letras mayusculas y minusculas, por lo que a efectos del programa seran identificadores distintos "hola", "Hola" o "hoLa".

No se impone ningun lımite en cuanto a la longitud de los identificadores.

<Ident> ::= <letra> {<letra>|<digito>}

2.    Palabras reservadas

Tienen un significado predeterminado para el compilador y s´olo pueden ser usadas con dicho sentido.

and
and


eq
asm
auto
bitand
bitor


bool
break
case
catch
chat
class
compl
const
const

cast
continue
default
delete
do
double
dynamic

cast
else
enum
explicit
export
extern
false
float
for
friend
goto
if
inline
int
long
mutable
namespace
new
not
not

eq
operator
or
or

eq
private
protected
public
register
reinterpret

cast
return
short
signed
sizeof
static
static

cast
struct
switch
template
this
throw
true
try
typedef
typeid
typename
union
unsigned
using
virtual
void
volatile
wchar

t
while
xor
xor

eq

















3.     Literales constantes

Se distingue entre n´umeros reales, n´umeros enteros y cadenas de caracteres.

<num_entero> ::= <digito> {<digito>}
|

<digito_octal> {<digito_octal>} (u|U|l|L)|

<digito> {<digito_hex>} H

<num_real>
::= <digito> {<digito>}.{<digito>} [<factor_esc>]
<factor_esc>
::= E (+|-|e) {<digito>}



Si el numero lleva u como sufijo, es un numero sin signo. Si lleva l como sufijo es de tamano long. Todo numero al que se le antepone el caracter 0 esta expresado en base 8. Si se le antepone 0x, esta expresado en base 16. Cuando se usa E en un literal constante real se dice que el numero esta expresado en punto flotante (notacion cientıfica). e representa la cadena vacıa.

Una cadena de caracteres (string) en C++ es una secuencia de caracteres encerrados entre comillas dobles (). Las constantes que representan un solo caracter se encierran entre comillas simples(’ ’).

4.     Delimitadores

Son símbolos (con o sin significado propio) que indican comienzo o fin de una entidad. Son elementos indivisibles: por ejemplo al escribir == se debe hacer sin ningún carácter intercalado.

{
}
[
]
#
##
(
)
<:
>:
<%
>%
%:%:
%:
;
:
?
::  .
.*  +
-
*
/
%
^
&
|
~
!
=
< 
> 
+=
-=
*=
/=
%=
^=
&=
|=
<<=
>>= <<
>> 
==
!=
<=
>=
&&
||
++
--
,
->
->* ...










5.     Comentarios

Un comentario es una secuencia de caracteres que es ignorada por el compilador. Se usan para documentar el programa, de manera que aunque no contribuyan a resolver el problema, sı ayudan a mejorar la comprensión del programa. Hay dos formas de incluir un comentario en C++. El texto que hay entre // y el fin de lınea se considera un comentario. Tambien es comentario el texto que se encuentra entre los sımbolos /* y */. Los comentarios de este estilo no se pueden anidar.

Debe tenerse cuidado para no encerrar trozos de codigo util dentro de un comen-tario, ya que un comentario puede extenderse a lo largo de multiples lıneas. Encerrar trozos de codigo como comentarios es util cuando se esta desarrollando un programa para comprobar si ciertas partes funcionan o no, pero es un error muy comun encerrar por descuido otras zonas de codigo que son necesarias o bien olvidarse de sacar sentencias de dentro de un comentario.

6.     Separadores

Son espacios en blanco, tabuladores, retornos de carro, fin de fichero y fin de lınea. Habra ocasiones en que se pongan para dar legibilidad al programa, y otras por necesidad. Los comentarios son considerados tambien separadores por el compilador.

2.2.          Constantes, variables y tipos de datos

En un programa intervienen objetos sobre los que actuan las instrucciones que lo componen. Algunos de estos objetos tomaran valores a lo largo del programa. Dependiendo de si pueden cambiar de valor o no, podemos distinguir dos tipos de objetos:

Constante: Objeto, referenciado mediante un identificador, que tomar´ un valor al principio (zona de declaraciones) y no se podra modificar a lo largo del programa.
Variable: Objeto, referenciado por un identificador, que puede tomar distintos val-ores a lo largo del programa.
Sera mision del programador asignar el identificador que desee a cada constante y variable. El identificador o nombre de cada objeto sirve para identificar sin ning´un tipo de ambig¨uedad a cada objeto, diferenciandolo de los demas objetos que intervienen en el programa.

En C++ hay que indicar el nombre de las constantes y variables que vamos a usar, para que el compilador pueda asociar internamente a dichos nombres las posiciones de memoria correspondientes. La declaracion tiene que encontrarse en el codigo antes de cualquier instruccion que las use.

Al realizar las declaraciones de las variables, ademas de indicar su identificador o nombre, hay que indicar explıcitamente el tipo de los datos que pueden contener.

Un tipo determina la clase de valores que puede asumir una variable, constante o expresion. Cada valor pertenece a un tipo. Sobre los tipos de datos hay que destacar:

Importancia de poseer tipo. Cada variable, constante y expresion tienen asocia-do un unico tipo. La informacion de tipo determina la representacion de los valores, y la cantidad de espacio de memoria que debe serle asignado. Esa informacion tambien determina la forma en que deben ser interpretados los operadores aritmeticos, y permite al compilador detectar errores semanticos en aquellos programas que contienen operaciones inapropiadas. El tipo de una variable no solo determina el conjunto de valores que puede almacenar sino tambien el conjunto de operaciones permitidas sobre dicha variable. Esto ultimo es el principio fundamental de la programacion usando Tipos Abstractos de Datos (TADs).
Cardinalidad. El numero de valores que tiene un tipo de datos.

Operadores b´asicos. A cada tipo se le asocia un conjunto de operadores b´asicos, destinados a ser de utilidad en el dise˜no de programas y que, adem´as, tienen por
 lo menos una implementaci´on razonablemente eficiente en un computador. Por supuesto, la selecci´on de operadores b´asicos es, en cierta medida, arbitraria, y podr´ıa haberse aumentado o disminuido. El principio que suele seguirse es posibilitar al programador construir cualquier operaci´on adicional en funci´on de las b´asicas, y permitir hacerlo de una forma eficiente. Las operaciones m´as importantes y m´as generales definidas para los datos de cualquier tipo, son la asignaci´on (representada por =) y la verificaci´on de igualdad (==).

Compatibilidad de tipos. Cada operador act´ua sobre operandos de un mismo tipo, y da como resultado un valor siempre de un mismo tipo determinado. Como ya se ha dicho la informaci´on de tipo ayuda a los compiladores para detectar si se est´an realizando operaciones inapropiadas con tipos de datos distintos. Cuando el mismo s´ımbolo es aplicado para varios tipos distintos (por ejemplo + para la suma de enteros y la de reales –se le llama operador sobrecargado–), dicho s´ımbolo puede considerarse ambig¨uo, denotando varios operadores concretos diferentes.
En un lenguaje de programaci´on existen normalmente una serie de tipos de datos pre-definidos (tipos b´asicos) que el programador puede utilizar directamente para declarar variables. Por otro lado se pueden definir nuevos tipos propios para satisfacer las necesi-dades particulares del programador. Los principales tipos de datos predefinidos en C++ son:

El tipo int. N´umeros enteros.
El tipo bool. Valores l´ogicos Verdadero y Falso.
El tipo char. Caracteres del c´odigo ASCII.
El tipo float. N´umeros reales.
Todos ellos tienen dos propiedades en com´un: cada uno est´a formado por elemen-tos indivisibles o at´omicos que adem´as est´an ordenados. Los tipos de datos con estas caracter´ısticas se denominan tipos de datos escalares. Cuando decimos que un valor es at´omico, nos referimos a que no contiene partes componentes a las que pueda acceder-se independientemente. Por ejemplo, un car´acter es indivisible, mientras que la cadena de caracteres ”Hola”no. Cuando hablamos de que un conjunto de valores est´a ordena-do, queremos decir que los operadores relacionales est´andares (<, >, ==, <=, >=, !=) pueden aplicarse a aqu´ellos.

Todos estos tipos, excepto float, poseen una propiedad adicional. Cada valor tiene un predecesor y un sucesor unicos´ (excepto el primer y ultimo´ valor, respectivamente).

Los tipos de datos escalares que tienen esta propiedad se denominan tipos de datos ordinales. De los tipos de datos predefinidos s´olo el tipo float no es ordinal, pues 0.0501 es el predecesor de 0.0502 con cuatro d´ıgitos de precisi´on, pero 0.05019 es el predecesor de 0.05020 con un d´ıgito m´as de precisi´on.


El tipo int

Los valores que pertenecen a este tipo son los n´umeros enteros. Los operadores apli-cables a los enteros son:

+ suma
- resta
* producto
/ cociente de la division entera
% resto de la divisi´on entera.
Cada computador restringir´a el conjunto de valores de este tipo a un conjunto finito de enteros, comprendido en el intervalo −2(N − 1) ... 2(N − 1) − 1, donde N es el n´umero de bits que el computador usa para representar internamente un entero.

En nuestro caso, para el tipo int, N = 32, por lo que este rango es: - 2147483648 .. 2147483647. Se pueden definir variables para valores enteros con un rango menor indi-cando que son de tipo short int. En nuestro compilador, para los short int N = 16 y el rango es: -32768 .. 32767. Asimismo, long int est´a pensado para un rango mayor de valores, pero en el caso de nuestro compilador coincide con los int.


El tipo unsigned int

No es tipo independiente de int, sino una variaci´on de aqu´el. Sus valores son los n´umeros enteros no negativos, esto es, los n´umeros naturales (incluido el 0). Los oper-adores aplicables son los mismos que para int. La ventaja de usar unsigned int en lugar de int es que hacemos expl´ıcito que una determinada variable s´olo puede ser positiva. Adem´as de esto, si un computador usa N bits para almacenar un entero, el rango de los valores unsigned int ser´a 0...2N - 1, con lo que podemos almacenar un n´umero entero positivo m´as grande que con el tipo int. En nuestro caso los rangos para unsigned int y short unsigned int son, respectivamente: 0 .. 65535 y 0 .. 4294967295.

El tipo float

Los valores del tipo float son los n´umeros reales. Los operadores disponibles son los b´asicos anteriormente mencionados. La divisi´on se denota por /, siendo la divisi´on real, no la entera. Las constantes de tipo float se caracterizan por tener un punto decimal y, posiblemente, un factor de escala. Por ejemplo:

1.5           1.50         1.5E2        2.34E-2         0.0         0.         5.

Si se quieren representar n´umeros con mayor precisi´on, se puede usar el tipo double. En C++ el mayor real representable es 3.40282347e+38F (6 d´ıgitos de precisi´on) y el
menor n´umero positivo distinto de 0 es 1.17549435e-38F.


El tipo bool

Un valor bool es uno de los dos valores de verdad l´ogicos denotados por los iden-tificadores est´andares del lenguaje: true y false (Verdadero y Falso). Las expresiones de tipo bool son muy importantes en programaci´on. Estos valores no pueden leerse o escribirse directamente desde el teclado o al monitor, al contrario de lo que ocurre con los tipos num´ericos.

Cuando se eval´ua una expresi´on en C++, cualquier valor distinto de 0 es considerado true y 0 es considerado false.


El tipo char

Cada computador se comunica con su entorno mediante alg´un dispositivo de entrada y salida. Lee, escribe, o imprime elementos pertenecientes a un conjunto fijo de carac-teres. Este conjunto constituye el rango de valores del tipo char. El conjunto fijo de caracteres m´as estandarizado es el denominado ASCII (American Standard Code for In-formation Interchange). Este conjunto est´a ordenado y cada car´acter tiene una posici´on fija o n´umero ordinal.

Las constantes de tipo char se denotan por el car´acter encerrado entre comillas sim-ples(’ ’). Un valor car´acter puede ser asignado a una variable de tipo char, pero no puede usarse en operaciones aritm´eticas. Sin embargo, las operaciones aritm´eticas pueden apli-carse a sus n´umeros obtenidos por la funci´on de cambio de tipo int(ch). De forma inversa el car´acter con el n´umero n asociado, se obtiene con la funci´on est´andar char(n). Estas dos funciones se complementan se relacionan con las ecuaciones:


int(char(ch)) = ch                   y           char(int(n)) = n

Chequeo de tipos

En C++ cada variable y constante tiene un tipo concreto, y cuando se efect´ua una operaci´on, sus operandos deben tener el tipo apropiado.

En principio, y hasta que no presentemos las reglas para el uso de tipos, supondremos que las operaciones s´olo est´an definidas entre operandos del mismo tipo. Dos tipos son iguales si tienen el mismo nombre, y no si su composici´on es la misma. Esto resultar´ es-pecialmente importante cuando se trabaje con tipos de datos estructurados.

Si el programador necesita usar expresiones en las que los operandos sean de distintos tipos, debe efectuar conversi´on de tipos expl´ıcita (casting). Para ello se especifica el tipo al que se convierte y, entre par´entesis, la expresi´on que se convierte.

int(Valor)                //Convierte el parametro Valor al tipo int.

float(Valor)           //Convierte el parametro Valor al tipo float.

etc...

Estructura de un programa en C++

Comenzaremos viendo la estructura global de un programa escrito en C++ para a continuaci´on ir desglosando y analizando cada uno de sus componentes.


Esquema general de un programa

//lista de inclusiones //declaraciones globales


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

{

//declaraciones locales //sentencias de programa

}


Listas de inclusiones

Dentro de un programa podemos necesitar algunos procesos que por ser muy fre-cuentes est´an disponibles en el lenguaje y por tanto no nos debemos preocupar de pro-gramarlos. Para ello hay que indicar expl´ıcitamente que estamos incluyendo en nuestro programa los ficheros que contienen esos recursos. Una l´ınea de inclusi´on consta de la  expresi´on reservada #include y el nombre del fichero a incluir entre los caracteres ’<’ y’>’:
Cuerpo del programa

Es la zona del programa formada por las sentencias a ejecutar, especific´andose los

pasos a seguir para la resoluci´on del problema.

En C++ hay diversos tipos de sentencias:

Asignaci´on
switch
for
exit
Llamada a funci´on
while
return
break
if
do-while
continue


Entre estas sentencias no hay ninguna dedicada a entrada/salida (E/S). Lo que ocurre es que la E/S en C++ se efect´ua mediante llamadas a procedimientos que hay que
importar mediante listas de inclusiones.

Los procedimientos que se importan se encuentran en bibliotecas. Aunque existe un conjunto est´andar de bibliotecas, cada compilador de C++ puede a˜nadir sus propias librer´ıas predefinidas e informar de las caracter´ısticas de los procedimientos que contiene.
´
Este es un aspecto a revisar siempre que, a´un usando el mismo lenguaje, cambiemos de compilador.

<sec_sent>  ::=
<sentencia>; {<sentencia>}
<sentencia> ::=
<sent_asignacion>
|

<llamada_funcion>
|

<sent_if>
|

<sent_switch>
|

<sent_while>
|

<sent_do_while>
|
  
<sent_for>
exit
break
continue
return[<expresion>]
<sent_vacia>

Asignacion

Es el operador que permite dar un valor a una variable.

<sent_asignacion> ::= <variable> = <expresion>

Ejemplo:

i = 10;

El operador de asignaci´on es ”=”, y se lee toma el valor. La variable (izquierda) toma el valor de la expresi´on (derecha). Por defecto, las variables, despu´es de haber sido declaradas, no tienen ning´un valor (est´an indefinidas) y el programador debe encargarse de inicializarlas, es decir, asignarles un valor conocido, en el caso de que se vaya a utilizar su contenido.

En el lado izquierdo de la sentencia de asignaci´on s´olo puede haber una variable. Se eval´ua la expresi´on de la derecha y el resultado se guarda en la variable.

Las variables mantienen el valor que se les asigna hasta que cambian mediante otra sentencia de asignaci´on (u otro mecanismo), momento en que pierden el antiguo valor.

Expresiones

En los lenguajes de programaci´on el concepto de expresi´on es similar al usado en matem´aticas. Una expresi´on ser´a un conjunto de operadores y operandos que tras su evaluaci´on devolver´a un unico´ valor. Para saber el resultado de una expresi´on debemos conocer la precedencia de los operadores, es decir, el orden en el que se eval´uan dentro de la misma. De mayor a menor precedencia, los operadores disponibles son:


!

*      /       %   &&

+     -  ||

== != <        >           <= >=

 ENTRADA/SALIDA EN C++
13


En caso de igualdad de precedencia se eval´uan de izquierda a derecha. Estas reglas

pueden alterarse mediante el uso de par´entesis.

Ejemplos:

A = 3
* B - 7
↔  A = (3*B)-7
A = 3 - B - C  ↔  A = (3-B)-C
A = 3
- B * 7
↔  A = 3-(B*7)

Entrada/salida en C++

Trataremos por el momento la entrada y salida de datos en forma de caracteres. En principio supondremos que nuestros programas de C++ son procesos (programas en ejecución) que toman información de un flujo de entrada y entregan información a un flujo de salida, utilizando para ello dispositivos externos capaces de manejar información en forma de caracteres organizados como una sucesión de líneas.

Se conocen como flujos de entrada/salida estandares aquellos que se realizan con la pantalla y con el teclado (E/S interactiva).

Otra alternativa de comunicación con un programa consiste en preparar un fichero de datos, por ejemplo en el disco, de donde el programa los pueda leer cuando los necesite o grabar cuando tenga resultados ( E/S diferida).

En C++ las instrucciones para efectuar E/S se encuentran en modulos de librea, es decir, módulos preprogramados disponibles para el programador. A continuacion se describirán algunas de las instrucciones de E/S interactiva contenidas en la librería iostream.h.

Salida

Para enviar datos a la salida por defecto (generalmente la pantalla del monitor del ordenador), vamos a usar el flujo de salida cout. Este flujo se encuentra en el fichero de biblioteca iostream.h. Aunque se pueden efectuar muchas operaciones diferentes sobre este flujo, por ahora s´olo vamos a ver la operaci´on <<. Esta operaci´on manda un valor al flujo cout. Este valor puede ser de cualquier tipo. Ejemplo:

cout << "El valor de la variable cuyo nombre es i es "; cout << i;

cout << endl;

El primer ejemplo escribe una cadena de caracteres, el segundo el contenido de la variable i y en el tercero se escribe el valor del caracter endl, lo que hace que se escriba una nueva lınea. Tambien se pueden concatenar los valores que se vayan a mandar a la salida. La siguiente instruccion equivale a las tres anteriores:

cout << "El valor de la variable cuyo nombre es i es " << i << endl;

Entrada

Este apartado se refiere a todas aquellas instrucciones que hacen posible introducir datos para que el programa los maneje. A continuación veremos instrucciones que tambien se encuentran en el fichero de biblioteca iostream.h. En este caso, el flujo de entrada en cin y la operacion que vamos a ver de momento para la lectura de datos es >>. Como en el caso de la salida, el parametro puede ser de cualquier tipo. Ejemplo:

int i, j; char c; cin >> i; cin >> j; cin >> c;

Finalmente vamos a se˜nalar algunas notas importantes que hay que tener en cuenta al hacer entrada/salida interactiva:

·    Las entradas y salidas de nuestro programa tienen eco normalmente en el monitor y se mezclan. El programador debe prever este efecto para que el resultado sea legible.

·    El computador normalmente no se percata de lo que se teclea hasta pulsar la tecla ENTER, quien provoca adem´as un salto de l´ınea en la pantalla. Por tanto es posible una edici´on limitada de los valores que se est´an tecleando (borrarlos, cambiarlos, etc...) antes de pulsar ENTER.

·    Hay otras instrucciones que permiten hacer una salida con formato para que sea m´as visible, aunque por ahora no lo vamos a ver.

Ejemplos

1.     Copiar (editar), compilar y ejecutar el siguiente programa que permite introducir una medida en cent´ımetros y muestra la medida equivalente en pulgadas (una pulgada mide 2,54 cent´ımetros).
ENTRADA/SALIDA EN C++
15


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


const float cent_por_pulgada = 2.54;


int main()

{

float centimetros, pulgadas;


cout << "Teclee una medida en centimetros\n"; cin >> centimetros;

pulgadas = centimetros / cent_por_pulgada; // Calculo de pulgadas cout << "Sus " << centimetros << " centimetros equivalen a " <<

pulgadas << "pulgadas" << endl;


system("PAUSE"); return 0;

}

·          Escribir (editar), compilar y ejecutar el programa siguiente, que recibe el radio de un c´ırculo y que muestra en pantalla el di´ametro, la longitud de la circunferencia y el ´area de ese c´ırculo.


#include <iostream.h> #include <stdlib.h> const float PI = 3.14;


int main() {

float radio, diametro, longitud, area;

cout << "Teclee la medida del radio de la circunferencia en cm\n"; cin >> radio;

//      C\’{a}lculos de magnitudes diametro = 2.0 * radio; longitud = PI * diametro; area = PI * radio * radio;

//      Salida de resultados
cout << "DATOS DEL CIRCULO:" << endl;

cout << "Radio introducido por el usuario: " << radio << " cm" << endl;

cout << "Diametro de la circunferencia: " << diametro << " cm" << endl;

cout << "Longitud de la circunferencia: " << longitud << " cm" << endl;

cout << "Area de la circunferencia: " << area << " cm2" << endl;


system("PAUSE"); return 0;

}

Comentarios