Programación: datos y operaciones básicas
Recupero la serie Programación, que la tenía un poco abandonada últimamente tras ese paréntesis para hablar de gcc, gdb, etc. Si lo recuerdas, en los artículos previos a esos sobre herramientas, aprendimos lo básico sobre la programación: lenguajes de alto nivel, lenguajes de bajo nivel, proceso de compilación, las etapas de la programación, lo que era un algoritmo, etc. Recuerda que todo está orientado al lenguaje de programación C, que es el que estoy usando como referencia.
Pues bien, tras esos pasos previos que entiendo que son indispensables, ahora vamos a comenzar a aprender el lenguaje C. Y lo haremos empezando por los tipos de datos que se pueden manejar y las operaciones esenciales que podrás usar en tus códigos fuente. Igualmente aprenderás a identificar y diferenciar los elementos elementales del programa: palabras reservadas, variables, constantes, funciones, etc.
ÍNDICE:
Ingredientes
Richard Stallman hizo una analogía entre las recetas y el código fuente de los programas que me gustó, por eso vamos a ver esos «ingredientes» necesarios para tu receta en C.
Si no entiendes algo, no te preocupes, con los próximos artículos con ejemplos prácticos lo entenderás todo mejor…
Preprocesador de C
¿Recuerdas el diagrama que puse cuando hablamos del proceso de compilación? Se incluía el preprocesador de C. Él será el encargado primero de manipular el texto o código fuente previamente a la compilación. Lo que hará es limpiar los comentarios, reemplazar todos los valores existentes en las directivas por lo necesario para generar el código objeto, etc.
Aunque siempre se escriben las directivas destinadas al preprocesador al principio del programa, no es estrictamente necesario. Se pueden poner en cualquier parte del código.
#include | Sirve para incluir un fichero especificado, como los de cabecera para llamar a bibliotecas. Por ejemplo:
#include <stdio.h> #include «nombre.h» En el primer caso busca el .h en los directorios estándar. En el segundo buscará primero en el directorio actual de trabajo. |
#define | Define macros y constantes simbólicas. Por ejemplo:
#define ANCHO 38 #define LARGO (ANCHO + 47) También existen macros predefinidos. En ANSI C, se reconocen 5 de ellos. __DATE__ para describir fecha tipo mmm/dd/aaaa, __TIME__ para la hora hh:mm:ss, __FILE__ para el nombre del fichero fuente actual, __LINE__ sustituye al número de línea actual, y __STDC__ que verifica que todo el código esté en ANSI. |
#if
#elif #else #endif |
Para formar directivas condicionales. Por ejemplo:
#if expresión1 instrucción; #elif expresión2 instrucción; #else instrucción; #endif |
#ifdef | Comprueba si el identificador está definido. Por ejemplo:
#ifdef identificador |
#ifndef | Comprueba si el identificador no está definido. |
#line | Cambia contenidos del fichero de mensajes de compilación, donde se registran los errores. Por ejemplo:
#line 60 «mensaje» Entonces, en caso de haber un error aparecería algo así: mensaje(60): warning C4013… |
#undef | Anula la definición LINE/FILE, es decir, borra la definición de un identificador creado con #define previamente. Por ejemplo:
#undef identificador |
#error | Se emplea para abortar una compilación y mostrar un mensaje de error. Por ejemplo, si quieres crear un programa que de error si PSICINA no ha sido definida como directriz, entonces:
#if !defined(PISCINA) #Error PSICINA no definida #endif |
#pragma | Pasa opciones al compilador. Cada compilador podrá definir las suyas propias. |
También se puede usar \ al final de una línea para partir directivas si ocupan más de una linea, # como operador cadena para macros que tienen parámetros, y ## como concatenador para unir tokens…
Bibliotecas
A estas alturas, si lees el blog con frecuencia, ya deberías saber qué es una biblioteca. Pues bien, en ANSI C puedes usar gran cantidad de ellas. 24 ficheros de cabecera están incluidos en las estándares. Para no alargar demasiado este artículo, si quieres saber cuáles son, las tienes aquí. En los próximos ejemplos iremos usando algunas de ellas para que veas mejor para qué sirven…
A parte de esas, también puedes usar las tuyas propias o las del entorno o sistema operativo para el que estés desarrollando. Por ejemplo, POSIX/SUS tiene otras…
Identificadores
Con un identificador se puede bautizar o dar nombre a variables, constantes, tipos de datos, procedimientos, nombres de funciones, etc. Para crear estos nombres, de debe respetar algunas reglas:
- Puedes usar todas las letras minúsculas de la a-z y mayúsculas de A-Z. Además, cuenta con case-sensitive, es decir, diferencia entre mayúsculas y minúsculas. Por tanto, nombre, Nombre, NOMBRE y noMbre las reconocerá como diferentes…
- Los números de 0-9
- No se aceptan espacios, pero puedes unir con _
- Siempre deben comenzar por una letra o _
Por ejemplo:
Mal | Bien |
«Y» | X |
6area | suma1 |
mis-arch | num_3 |
error cuenta | PRODUCTO_NUEVO |
$var | _tiempo |
Por otro lado, los símbolos soportados en el código solo son: -, /, &, ?, ‘, |, (), [], {}, :, ;, _, ^, <>, ~, #, =, *, %, !, \, @, $, y también el punto, coma y espacio.
Tipos de datos y sistemas numéricos
Los programas en C pueden trabajar con diferentes tipos de datos:, tanto simples (enteros, reales, lógicos o booleanos [true/false], caracteres) o compuestos por varios simples. Los tipos básicos son:
int | Entero. Ocupa 2 bytes y va desde el -32.768 a 32.767 |
float | Flotante. Ocupa 4 bytes y va desde el 3,4 E-38 a 3,4 E+38 |
double | Flotante de precisión doble. Ocupa 8 bytes y va desde 1,7 E-308 a 1,7 E+308 |
char | Caracter o cadenas. De 1 byte (8 bits). De -127 a 127 |
void | Ocupa 0 bytes, es un valor vacío. Es frecuente usarlo en la función main, que no regresa nada ni tiene parámetros. Por ejemplo: void main() o void main(void). |
Se puede usar también long para valores de longitud mayor, y sizeof para indicar el tamaño exacto en bytes de un tipo.
Otros lenguajes usan Unicode, etc., pero aquí también sería interesante conocer ANSI
Sería interesante también que conozcas los caracteres ASCII para consultarlos por si los necesitas, y los sistemas numéricos que puedes emplear en los códigos. Los sistemas son binario (base 2), decimal (base 10), octal (base 8) y hexadecimal (base 16).
Variables
Una variable es un dato cuyo valor (de alguno de los tipos vistos en el apartado anterior) puede variar a lo largo de la ejecución del programa. Es decir, es un valor almacenado en la memoria que puede variar, ya sea por alguna operación previa que afecte al valor de dicha variable o porque los datos se deban insertar por el usuario, etc. La variable tendrá un identificador asignado. Por ejemplo, sum puede ser una variable en este programa y será diferente en función de los valores de las otras variables que debe introducir un usuario (num1 y num2):
#include <stdio.h> int main() { int sum, num1, num2; printf("Introduce un número: "); scanf("%d", &num1); printf("Introduce otro número: "); scanf("%d", &num2); suma = num1+num2; prinft("El resultado de la suma es: %d", suma); return 0; }
La variable debe declararse siempre, o el compilador dará un código de error al intentar compilarlo. Muchos de los errores típicos son olvidar declarar una variable o teclear mal el nombre y que no coincida. Además, se declarará en un lugar específico según el tipo:
- Global: fuera de todos los subprogramas o funciones.
- Local: dentro de un subprograma o función. También puede hacerse dentro de un bloque, de una función o como parámetro formal.
Ten en cuenta también que cuando se declara una variable se reserva un espacio de memoria para ella. El espacio ocupado dependerá del tipo de dato usado. Por ejemplo, si es un entero como en el caso de suma, entonces será de 2 bytes. Por ahora no entraré en temas de segmentación y paginación… con eso es suficiente, pero es posible que en la serie sobre CPUs veamos algo más adelante.
Constantes
Similar a la variable, también con un identificador, pero en este caso, la constante permanecerá siempre con el mismo valor (de ahí su nombre). También pueden ser de diversos tipos como las variables, y se almacenarán en su espacio correspondiente de memoria que le asigne el compilador al generar las instrucciones, datos y direcciones de memoria en el binario generado.
Puedes usar const o macros para definirlas. Por ejemplo:
#define MAX 100 const float PI = 3.14
Operadores
Los operadores son símbolos que permiten relacionar datos en una expresión y evaluar el resultado. Pueden ser de tipo aritmético, lógico, relacionales y de asignación.
Los aritméticos son:
+ | Suma |
– | Resta |
* | Multiplica |
/ | Divide |
% | Resto de una división |
pow | Potencia |
Los de incremento y decremento son
++ | Incrementa. Por ejemplo i++ usa el valor actual de i en la expresión donde se encuentra i, y luego lo incrementa en 1. En cambio, ++i incrementa i en 1 y luego se utiliza el nuevo valor de i en la expresión en la que se encuentra i. |
— | Decrementa. Sirve lo dicho anteriormente, en función de si usas –i o i– |
Los lógicos son:
&& | AND (Y) |
|| | OR (O) |
! | NOT o negación |
Los relacionales son:
> | Mayor que |
< | Menor que |
== | Igual que |
>= | Mayor o igual que |
<= | Menor o igual que |
!= | Distinto a |
Los de asignación sirven para asignar el resultado de una expresión a una variable. Por ejemplo, el caso de la suma anterior lo era, ya que se asignaba el valor a la variable suma de num1+num2. Otors ejemplos:
= | En este caso promedio pasa a valer la media de edades:
promedio = edad1+edad2/2 |
+= | Se emplea para x = x + algo. Por ejemplo: s+=10 equivale a s = s+10 |
-= | Se emplea para x = x – algo. Por ejemplo: y-=12 equivale a y = y-12 |
*= | Igual a los anteriores, pero multiplicando. |
/= | Igual pero dividiendo. |
%= | Lo mismo para el resto. |
También existe un operador condicional como sustituto de if…else, es ?. Por ejemplo, esto sería equivalente:
#Siempre que a>3, b toma el valor 5
b = (a<3) ? 5 : 10; |
if (a<3) b = 5;
else b=10; |
Importante la prioridad, ya que al ser operaciones matemáticas se tiene prioridad según el símbolo empleado, las agrupaciones tendrán prioridad, etc.
1º Asociación | Con () y [], de izquierda a derecha |
2º Monarios | Con -,++,–,!,sizeof(), de derecha a izquierda |
3º Otros aritméticos | Con *, /, %, de izquierda a derecha |
4º Suma y resta | Con +, -, de izquierda a derecha |
5º Relacionales | Con <,<=, >, >=, de izquierda a derecha |
6º Igualdad | Con == y !=, de izquierda a derecha |
7º AND | Con &&, de izquierda a derecha |
8º OR | Con ||, de izquierda a derecha |
9º Condicional | Con ?:, de derecha a izquierda |
10º Asignación | Con =, +=, -=, *=, /=, %=, de derecha a izquierda |
Por ejempo, si tienes lo siguiente:
total = num1 + (num2 – num3 * x) + y/2
Lo que primero hará es multiplicar num3 y x. Lugo divide y/2. También se resta el resultado de num3*x a num2. Después se suma el resultado dentro del paréntesis a num1 y finalmente todo eso se suma al resultado de y/2. El resultado es asignado a la variable total.
Secuencias de escape
En cuanto a las secuencias de escape, tienes estas:
\a | Hace un sonido de alerta |
\b | Retroceso o espacio hacia atrás |
\t | Tabula el texto de forma horizontal |
\n | Cambia de línea el texto que va detrás de esta secuencia |
\v | Hace una tabulación en vertical del texto |
\f | El texto tras esta secuencia se muestra en una nueva página |
\r | Retroceso de carro. Es el valor 013 de ASCII |
\» | Comillas. Corresponde al ASCII 034 |
\’ | Comillas simple o apóstrofo. Código ASCII 039 |
\? | Para poner el signo de interrogación en el código |
\\ | Para insertar la barra invertida |
\0 | Valor nulo o null. Es el ASCII 000 |
\ooo | Permite insertar el número octal «ooo» de tres dígitos |
\xhh | Permite insertar un número hexadecimal hh (de cualquier cantidad de dígitos) |
Expresiones
Una expresión simplemente es el resultado de unir varios operandos (variables o constantes) mediante operadores. Por ejemplo, sum=num1+num2 sería una expresión.
Palabras reservadas
Son palabras reservadas las que no se pueden usar para identificadores, ya que están reservadas por el lenguaje para otros usos:
- ada
- asm
- auto
- break
- case
- char
- const
- continue
- default
- do
- double
- else
- entry
- enum
- extern
- far
- float
- for
- fortran
- goto
- huge
- sizeof
- if
- static
- int
- struct
- long
- switch
- near
- typedef
- pascal
- union
- register unsigned
- return
- void
- short
- volatile
- signed
- while
Además de estas, estarán también las de algunas funciones que aportan las bibliotecas, como scanf, printf, etc., que tampoco puedes usar como identificadores. Ya estudiaremos más adelante para qué sirve cada una…
Comentarios
Los comentarios son el texto que quieres que el compilador ignore, pero que es necesario para hacer una breve explicación de una parte del programa o para que otro desarrollador entienda mejor lo que se ha pretendido hacer, etc. Se puede usar dos formas para insertarlos:
/* Cuando el texto ocupa más de una línea puedes usar este método encerrando entre estos símbolos todo lo que quieras que se tome como comentario */ //Para una nota más breve puedes usar esto al comienzo del comentario...
Conversión de tipos
Si has usado varios tipos de datos en una misma expresión, el compilador los transformará todos a un tipo para poder realizar la operación. El tipo al que transformará dependerá de la prioridad de cada uno de los tipos (mayor prioridad el de más a la derecha):
char > int > unsigned int > long > unsigned long > float > double > long double
En el siguiente veremos cómo está constituido un programa y algunas estructuras básicas, y una vez hecho eso, ya podrás empezar a crear tus primeras recetas… Iré publicando más entradas sobre programación con ejemplos prácticos que incluirán el algoritmo, pseudocódigo y el código fuente. 😉
Pingback: Programación: estructura de un programa C - Parte 2 | ArchiTecnologia
Pingback: viagra