Foro de Informatica
" Hay la misma diferencia entre un sabio y un ignorante que entre un hombre vivo y un cadáver "

- Aristóteles -



        


Google
 
Web www.ComputerFacil.com
Forista del Mes:

rafa games




  Reply to this topicStart new topicStart Poll

> Tutorial C, By TvK10
TvK10
  Publicado: Jul 27 2007, 11:16 AM
Quote Post


**Ubuntero**
Group Icon

Grupo: Colaboradores
Mensajes: 1.398
Miembro nº: 22.588
Registrado: 1-May 07



Tutorial C

Este es un curso para principiantes así que intentaré que no haga falta ningún conocimiento anterior para seguirlo.

¿Qué es C?

El lenguaje C es uno de los más rápidos y potentes que hay hoy en dia. Algunos dicen que está desfasado y que el futuro es Java. No se si tendrá futuro pero está claro que presente si tiene. No hay más que decir que el sistema operativo Linux está desarrollado en C en su práctica totalidad. Así que creo que no sólo no perdemos nada aprendiendolo sino que ganamos mucho. Para empezar nos servirá como base para aprender C++ e introducirnos en el mundo de la programación Windows. Si optamos por Linux existe una biblioteca llamada gtk (o librería, como prefieras) que permite desarrollar aplicaciones estilo windows con C.

No debemos confundir C con C++, que no son lo mismo. Se podría decir que C++ es una extensión de C. Para empezar en C++ conviene tener una sólida base de C.

Existen otros lenguajes como Visual Basic que son muy sencillos de aprender y de utilizar. Nos dan casi todo hecho. Pero cuando queremos hacer algo complicado o que ea rápido debemos recurrir a otros lenguajes (c++, delphi,...).

Compiladores

Un compilador es un programa que convierte nuestro código fuente en un programa ejecutable (Me imagino que la mayoría ya lo sabeís, pero más vale asegurar). El ordenador trabaja con 0 y 1. Si escribiéramos un programa en el lenguaje del ordenador nos volveríamos locos. Para eso están lenguajes como el C. Nos permiten escribir un programa de manera que sea fácil entenderlo por una persona (el código fuente). Luego es el compilador el que se encarga de convertirlo al complicado idioma de un ordenador.

Para programar con Windows recomiendo el Dev-C++ por la comodidad y facilidad que supone para los principiantes.

El editor

El compilador en sí mismo sólo es un programa que traduce nuestro código fuente y lo convierte en un ejecutable. Para escribir nuestros programas necesitamos un editor. Si nuestro compilador no trae editor la solución más simple en MS-Dos puede ser usar el edit, en windows el notepad. Pero no son más que editores sin ninguna otra funcionalidad. Otra posibilidad es un entorno de desarrollo llamado RHIDE, un programa muy útil que automatiza muchas de las tareas del programador. Si queremos una herramienta muy avanzada podemos usar Emacs, que es un editor muy potente, aunque para algunos puede parecer muy complicado. Estos dos programas están disponibles tanto en Linux como en MS-Dos.

El primer programa..

Vamos a hacer nuestro primer programa...HOLA MUNDO

Nadie puede llegar muy lejos en el mundo de la programación sin haber empezado su carrera con este original y funcional programa.

CODE
#include <stdio.h>

int main() {
   printf("Hola mundo\n");
   return 0;
}


Este programa lo único que hace es sacar por pantalla el mensaje: Hola mundo

Vamos ahora a comentar el programa línea por línea

CODE
#include <stdio.h>


#include es lo que se llama una directiva. Sirve para indicar al compilador que incluya otro archivo. Cuando en compilador se encuentra con esta directiva la sustituye por el archivo indicado. En este caso es el archivo stdio.h que es donde está definida la función printf, que veremos luego.

CODE
int main()


Es la función principal del programa. Todos los programas de C deben tener una función llamada main. Es la que primero se ejecuta. El int (viene de Integer=Entero) que tiene al principio significa que cuando la función main acabe devolverá un número entero. Este valor se suele usar para saber cómo ha terminado el prorama. Normalmente este valor será 0 si todo ha ido bien, o un valor distinto si se ha producido algún error (pero esto lo decidimos nosotros, ya lo veremos). De esta forma si nuestro programa se ejecuta desde otro el programa 'padre' sabe como ha finalizado, si ha habido errores o no.

Se puede usar la definición 'void main()', que no necesita devolver ningún valor, pero se recomienda la forma con 'int' que es más correcta. A lo largo de este curso verás muchos ejemplos que uso 'void main' y falta el return 0; del final, el código funciona correctamente pero puede dar un 'warning' al compilar. En estos momentos estoy intentando corregir esto...

CODE
{


Son las llaves que indican el comienzo de una función, en este caso la función main.

QUOTE
/* Aquí va el cuerpo del programa */


Esto es un comentario, no se ejecuta.

CODE
printf( "Hola mundo\n" );


Aquí es donde por fin el programa hace algo que podemos ver al ejecutarlo. La función printf muestra un mensaje por la pantalla. Al final del mensaje "Hola mundo" aparece el símbolo '\n'; este hace que después de imprimir el mensaje se pase a la línea siguiente.

Fíjate en el ";" del final. Es la forma que se usa en C para separar una instrucción de otra. Se pueden poner varias en la misma línea siempre que se separen por el punto y coma.

CODE
return 0;


Como he indicado antes el programa al finalizar develve un valor entero. Como en este programa no se pueden producir errores la salida siempre será 0. La forma de hacer que el programa devuelva un 0 es usando return. Esta línea significa 'finaliza la función main haz que devuelva un 0.

CODE
}


Y cerramos la llave..

El primer programa..

Siempre he creído que cuando empiezas con un nuevo lenguaje suele gustar el ver los resultados, ver que nuestro programa hace 'algo'. Por eso creo que el curso debe comenzar con la función printf, que sirve para sacar información por pantalla.

Para utilizar la función printf en nuestros programas debemos incluir la directiva:

CODE
#include <stdio.h>


al principio de programa. Como hemos visto en el programa hola mundo.

Si sólo queremos imprimir una cadena basta con hacer (no olvides el ";" al final):

CODE
printf( "Cadena" );


Esto resultará por pantalla: Cadena

Lo que pongamos entre las comillas es lo que vamos a sacar por pantalla.

Si volvemos a usar otro printf, por ejemplo:

CODE
#include <stdio.h>

int main()
{
printf( "Cadena" );
printf( "Segunda" );

return 0;
}


Obtendremos: Cadena Segunda

Este ejemplo nos muestra cómo funciona printf. Para escribir en la pantalla se usa un cursor que no vemos. Cuando escribimos algo el cursor va al final del texto. Cuando el texto llega al final de la fila, lo siguiente que pongamos irá a la fila siguiente. Si lo que queremos es sacar cada una en una línea deberemos usar "\n". Es el indicador de retorno de carro. Lo que hace es saltar el cursor de escritura a la línea siguiente:

CODE
#include <stdio.h>

int main()
{
printf( "Cadena\n" );
printf( "Segunda" );

return 0;
}


y tendremos:
Cadena
Segunda

También podemos poner más de una cadena dentro del printf:

CODE
printf( "Primera cadena" "Segunda cadena" );


Lo que no podemos hacer es meter cosas entre las cadenas:

CODE
printf( "Primera cadena" texto en medio  "Segunda cadena" );


esto no es válido. Cuando el compilador intenta interpretar esta sentencia se encuentra "Primera cadena" y luego texto en medio, no sabe qué hacer con ello y da un error.

Pero ¿qué pasa si queremos imprimir el símbolo " en pantalla? Por ejemplo imaginemos que queremos escribir: Esto es "extraño"

El problema es que el símbolo " se usa para indicar al compilador el comienzo o el final de una cadena. Así que en realidad le estaríamos dando la cadena "Esto es", luego extraño y luego otra cadena vacía "". Pues resulta que printf no admite esto y de nuevo tenemos errores.

La solución es usar \". Veamos:

CODE
printf( "Esto es \"extraño\"" );


Como vemos la contrabarra '\' sirve para indicarle al compilador que escriba caracteres que de otra forma no podríamos.

Esta contrabarra se usa en C para indicar al compilador que queremos meter símbolos especiales. Pero ¿Y si lo que queremos es usar '\' como un carácter normal y poner por ejemplo Hola\Adiós? Pues muy fácil, volvemos a usar '\':

CODE
printf( "Hola\\Adiós" );


y esta doble '\' indica a C que lo que queremos es mostrar una '\'.

Esto no ha sido mas que una introducción a printf. Luego volveremos sobre ella.

Gotoxy: Posicionando el cursor (DOS)

Esta función sólo está disponible en compiladores de C que dispongan de la biblioteca <conio.h>

Hemos visto que cuando usamos printf se escribe en la posición actual del cursor y se mueve el cursor al final de la cadena que hemos escrito.

Vale, pero ¿qué pasa cuando queremos escribir en una posición determinada de la pantalla? La solución está en la función gotoxy. Supongamos que queremos escribir 'Hola' en la fila 10, columna 20 de la pantalla:

CODE
#include <stdio.h>
#include <conio.h>

int main()
{
gotoxy( 20, 10 );
printf( "Hola" );

return 0;
}


Para utilizar el comando gotoxy, hay que añadir la biblioteca conio.h

Fíjate que primero se pone la columna (x) y luego la fila (y). La esquina superior izquierda es la posición (1, 1).

Clrscr: Borrar la pantalla (DOS)

Ahora ya sólo nos falta saber cómo se borra la pantalla. Pues es tan fácil como usar:

CODE
clrscr()


Esta función nó solo borra la pantalla, sino que además sitúa el cursor en la posición (1, 1), en la esquina superior izquierda.

CODE
#include <stdio.h>
#include <conio.h>

int main()
{
clrscr();
printf( "Hola" );

return 0;
}


Este método sólo vale para compiladores que incluyan el fichero stdio.h.

Otros metodos

Existen otras formas de borrar la pantalla aparte de usar stdio.h.

Si usas DOS:

CODE
system ("cls"); //Para DOS


Si usas Linux:

CODE
system ("clear"); // Para Linux


Otra forma válida para ambos sistemas:

CODE
char a[5]={27,'[','2','J',0}; /* Para ambos (en DOS cargando antes ansi.sys) */
printf("%s",a);


Bueno, ya hemos aprendido a sacar información por pantalla. Si quieres puedes practicar con las instrucciones printf, gotoxy y clrscr. Lo que hemos visto hasta ahora no tiene mucho secreto, pero ya veremos cómo la función printf tiene mayor complejidad.

Cuando usamos un programa es muy importante manejar datos. En C podemos almacenar los datos en variables. El contenido de las variables se puede ver o cambiar en cualquier momento. Estas variables pueden ser de distintos tipos dependiendo del tipo de dato que queramos meter. No es lo mismo guardar un nombre que un número. Hay que recordar también que la memoria del ordenador es limitada, así que cuando guardamos un dato, debemos usar sólo la memoria necesaria. Por ejemplo si queremos almacenar el número 400 usaremos una variable tipo int (la estudiamos más abajo) que ocupa sólo 16 bits, y no una de tipo long que ocupa 32 bits. Si tenemos un ordenador con 32Mb de Ram parece una tontería ponernos a ahorrar bits (1Mb=1024Kb, 1Kb=1024bytes, 1byte=8bits), pero si tenemos un programa que maneja muchos datos puede no ser una cantidad despreciable. Además ahorrar memoria es una buena costumbre.

A las variables no se les puede dar cualquier nombre. No se pueden poner más que letras de la 'a' a la 'z' (la ñ no vale), números y el símbolo '_'. No se pueden poner signos de admiración, ni de interrogación... El nombre de una variable puede contener números, pero su primer carácter no puede serlo.

Ejemplos de nombres válidos:

camiones
numero
buffer
a1
j10hola29
num_alumnos

Ejemplos de nombres no válidos:

1abc
nombre?
num/alumnos

Tampoco valen como nombres de variable las palabras reservadas que usa el compilador. Por ejemplo: for, main, do, while.

Por cierto...C Distingue entre MAYUSCULAS y minusculas, por lo que siempre que pongais un nombre al que luego le haces referencia ponerlo igual.

Int

En una variable de este tipo se almacenan números enteros (sin decimales). El rango de valores que admite es -32767 a 32767. Cuando definimos una variable lo que estamos haciendo es decirle al compilador que nos reserve una zona de la memoria para almacenar datos de tipo int. Para guardarla necesitaremos 16 bits de la memoria del ordenador (216=32767). Para poder usar una variable primero hay que declararla (definirla). Hay que decirle al compilador que queremos crear una variable y hay que indicarle de qué tipo. Por ejemplo:

CODE
int numero;


Esto hace que declaremos una variable llamada numero que va a contener un número entero.

Tenemos dos posibilidades, una es declararla como global y otra como local. Por ahora vamos a decir que global es aquella variable que se declara fuera de la función main y local la que se declara dentro:

Global:

CODE
#include <stdio.h>

int x;

int main()
{
}


La diferencia práctica es que las variables globales se pueden usar en cualquier procedimiento. Las variables locales sólo pueden usarse en el procedimiento en el que se declaran. Como por ahora sólo tenemos el procedimiento main esto no debe preocuparnos mucho por ahora. Cuando estudiemos cómo hacer un programa con más funciones aparte de main volveremos sobre el tema. Sin embargo debes saber que es buena costumbre usar variables locales que globales. Ya veremos por qué. Por ahora solo saber las globales..

Vamos a ir u poco más allá con la función printf. Supongamos que queremos mostrar el contenido de la variable

x

por pantalla:

CODE
printf( "%i", x );


Suponiendo que x valga 10 (x=10) en la pantalla tendríamos: 10

Empieza a complicarse un poco ¿no? Vamos poco a poco. ¿Recuerdas el símbolo "\" que usábamos para sacar ciertos caracteres? Bueno, pues el uso del "%" es parecido. "%i" no se muestra por pantalla, se sustituye por el valor de la variable que va detrás de las comillas. ( %i, de integer=entero en inglés).

Para ver el contenido de dos variables, por ejemplo x e y, podemos hacer:

CODE

printf( "%i ", x );
printf( "%i", y );


resultado (suponiendo x=10, y=20): 10 20

Pero hay otra forma mejor:

CODE
printf( "%i %i", x, y );


... y así podemos poner el número de variables que queramos. Obtenemos el mismo resultado con menos trabajo. No olvidemos que por cada variable hay que poner un %i dentro de las comillas.

También podemos mezclar texto con enteros:

CODE
printf( "El valor de x es %i, ¡que bien!\n", x );


Como vemos %i al imprimir se sustituye por el valor de la variable.

La asignación de valores es tan sencilla como:

CODE
x = 10;


También se puede dar un valor inicial a la variable cuando se define:

CODE
int x = 15;


Veamos un ejemplo para resumir todo:

CODE
#include <stdio.h>

int main()
{
int x = 10;

prinft( "El valor inicial de x es %i\n", x );
x = 50;
printf( "Ahora el valor es %i\n", x );
}


Char

Las variables de tipo char sirven para almacenar caracteres. Los caracteres se almacenan en realidad como números del 0 al 255. Los 128 primeros (0 a 127) son el ASCII estándar. El resto es el ASCII extendido y depende del idioma y del ordenador. Consulta la tabla ASCII en el anexo.

Para declarar una variable de tipo char hacemos:

CODE
char letra;


En una variable char sólo podemos almacenar solo una letra, no podemos almacenar ni frases ni palabras. Eso lo veremos más adelante.

El modificador Unsigned

Este modificador (que significa sin signo) modifica el rango de valores que puede contener una variable. Sólo admite valores positivos. Si hacemos:

CODE
unsigned char variable;


Esta variable en vez de tener un rango de -128 a 128 pasa a tener un rango de 0 a 255.

Float

En este tipo de variable podemos almacenar números decimales, no sólo enteros como en los anteriores. El rango de posibles valores es del 3,4E-38 al 3,4E38.

Declaración de una variable de tipo float:

CODE
float numero;


Para imprimir valores tipo float Usamos %f. Si queremos escribirlo en notación exponencial usamos %e

Double

En las variables tipo double se almacenan números reales del 1,7E-307 al 1,7E308. Se declaran como double:

CODE
double numero;


Para imprimir se usan los mismos modificadores que en float.

Cómo calcular el máximo valor que admite un tipo de datos

Lo primero que tenemos que conocer es el tamaño en bytes de ese tipo de dato. Vamos a ver un ejemplo con el tipo INT. Hagamos el siguiente programa:

CODE
#include <stdio.h>

int main()
    {
    int num1;

    printf( "El tipo int ocupa %i bytes\n", sizeof(int) );
    }


En mi ordenador el resultado es:

CODE
El tipo int ocupa 4 bytes.


Como sabemos 1byte = 8bits. Por lo tanto el tipo int ocupa 4*8=32 bits.

Ahora para calcular el máximo número debemos elevar 2 al número de bits obtenido. En nuestro ejemplo: 2^32=4.294.967.296. Es decir en un int se podría almacenar un número entre 0 y 4.294.967.296.

Sin embargo esto sólo es cierto si usamos un tipo unsigned (sin signo, se hace añadiendo la palabra unsigned antes de int). Para los tipos normales tenemos que almacenar números positivos y negativos. Así que de los 4.294.967.296 posibles números la mitad serán positivos y la mitad negativos. Por lo tanto tenemos que dividir el número anterior entre 2 = 2.147.483.648. Como el 0 se considera positivo el rango de números posibles que se pueden almacenar en un int sería: -2.147.483.648 a 2.147.483.647.

Resumen:

1. Obtenemos el número de bytes.
2. Multiplicamos por ocho (ya lo tenemos en bits).
3. Elevamos 2 al número de bits.
4. Dividimos entre 2.

Overflow: Qué pasa cuando nos saltamos el rango

El overflow es lo que se produce cuando intentamos almacenar en una variable un número mayor del máximo permitido. El comportamiento es distinto para variablesde números enteros y para variables de números en coma flotante.

Con números enteros

En mi ordenador y usando DJGPP bajo Dos el tamaño del tipo int es de 4bytes(4*8=32bits). El número máximo que se puede almacenar en una variable tipo int es por tanto 2.147.483.647 (ver apartado anterior). Si nos pasamos de este número el que se guardará será el siguiente pero empezando desde el otro extremo, es decir, el -2.147.483.648. El compilador seguramente nos dará un aviso (warning) de que nos hemos pasado.

CODE
#include <stdio.h>

int main()
    {
    int num1;

    num1 = 2147483648;
    printf( "El valor de num1 es: %i\n", num1 );
    }


El resultado que obtenemos es: El valor de num1 es: -2147483648

Comprueba si quieres que con el número anterior (2.147.483.647) no pasa nada.

Con números en coma flotante

El comportamiento con números en coma flotante es distinto. Dependiendo del ordenador si nos pasamos del rango al ejecutar un programa se puede producir un error y detenerse la ejecución.

Con estos números también existe otro error que es el underflow. Este error se produce cuando almacenamos un número demasiado pequeño (3,4E-38 en float).

Constantes (uso de #define)

Las constantes son aquellos datos que no pueden cambiar a lo largo de la ejecución de un programa.

CODE
#include <stdio.h>

int main()
{
int radio, perimetro;

radio = 20;
perimetro = 2 * 3.1416 * radio;


printf( "El perímetro es: %i", perimetro  );

return 0;
}


radio y perimetro son variables, su valor puede cambiar a lo largo del programa. Sin embargo 20, 2 y 3.1416 son constantes, no hay manera de cambiarlas. El valor 3.1416 no cambia a lo largo del programa , ni entre ejecución y ejecución. Sólo cambiará cuando edites el programa y lo cambies tu mismo. Esto es obvio, y no tiene ningún misterio así que no le des vueltas. Sólo quería indicarlo porque en algunos libros le dan muchas vueltas.

Supongamos que tenemos que hacer un programa en el que haya que escribir unas cuantas veces 3.1416 (como todos sabreis es PI). Es muy fácil que nos confundamos alguna vez al teclearlo y al compilar el programa no tendremos ningún error, sin embargo el programa no dará resultados correctos. Para evitar esto usamos las constantes con nombre. Al definir una constante con nombre estamos dando un nombre al valor, a 3.1416 le llamamos PI.

Estas constantes se definen de la manera siguiente:

CODE
#define nombre_de_la_constante valor_de_la_constante


De esta forma cada vez que el compilador encuentre el nombre PI lo sustituirá por 3.1416.

A una constante no se le puede dar un valor mientras se ejecuta, no se puede hacer PI = 20;. Sólo se le puede dar un valor con #define, y sólo una vez. Tampoco podemos usar el scanf para dar valores a una constante:

CODE
#define CONSTANTE 14

int main()
 {
 ...
 scanf( "%i", CONSTANTE );
 ...
 }


eso sería como hacer:

CODE
scanf( "%i", 14 );


Esto es muy grave, estamos diciendo que el valor que escribamos en scanf se almacene en la posición 14 de la memoria, lo que puede bloquear el ordenador.

Las constantes se suelen escribir en mayúsculas sólo se puede definir una constante por fila. No se pone ";" al final.

Las constantes nos proporcionan una mejor comprensión del código fuente. Mira el siguiente programa:

CODE
#include <stdio.h>

int main()
{
int precio;

precio = ( 4 * 25 * 100 ) * ( 1.16 );

printf( "El precio total es: %i", precio  );

return 0;
}


#define tiene más usos aparte de éste, ya los veremos...

¿Qué es un operador?

Un operador sirve para manipular datos. Los hay de varios tipos: de asignación, de relación, lógicos, aritméticos y de manipulación de bits. En realidad los nombres tampoco importan mucho.

Operador de asignación

Sirve para dar un valor a una variable. Este valor puede ser un número que tecleamos directamente u otra variable:

CODE
a = 3;  /* Metemos un valor directamente */

CODE
a = b;  /* Le damos el valor de una variable */


Podemos dar valores a varias variables a la vez..

Operador (+) : Suma

Este operador permite sumar variables:

CODE
#include <stdio.h>

int main()
 {
 int a = 2;
 int b = 3;
 int c;
 
 c = a + b;
 printf ( "Resultado = %i\n", c );
 }


El resultado será 5.

Por supuesto se pueden sumar varias variables o variables más constantes:

CODE
#include <stdio.h>

int main()
 {
 int a = 2;
 int b = 3;
 int c = 1;
 int d;

 d = a + b + c + 4;
 printf ( "Resultado = %i\n", c );
 }


El resultado es 10.

Podemos utilizar este operador para incrementar el valor de una variable:

CODE
x = x + 5;


Esto suma el valor 5 al valor que tenía la variable x. Veamos un ejemplo:

CODE
#include <stdio.h>

int main()
 {
 int x, y;

 x = 3;
 y = 5;

 x += 2;
 printf( "x = %i\n", x );
 x += y;  /* esto equivale a x = x + y */
 printf( "x = %i\n", x );
 }


Operador (-) : Resta

Este operador tiene dos usos, uno es la resta que funciona como el operador suma y el otro es cambiar de signo.

Resta:

CODE
x = x - 5;


Pero también tiene el uso de cambiar de signo. Poniendolo delante de una variable o constante equivale a multiplicarla por -1.

CODE
#include <stdio.h>

int main()
 {
 int a, b;

 a = 1;

 b = -a;
 printf( "a = %i, b = %i\n", a, b );
 }


Operador (*) : Multiplicación

Este operador sirve para multiplicar y funciona de manera parecida a los anteriores.

Operador (/) : División

Este funciona también como los anteriores pero hay que tener cuidado. Si dividimos dos número en coma flotante (tipo float) tenemos las división con sus correspondientes decimales. Pero si dividimos dos enteros obtenemos un número entero. Es decir que si dividimos 4/3 tenemos como resultado 1. El redondeo se hace por truncamiento, simplemente se eliminan los decimales y se deja el entero.

Si dividimos dos enteros el resultado es un número entero, aunque luego lo saquemos por pantalla usando %f o %d no obtendremos la parte decimal.

Cuando dividimos dos enteros, si queremos saber cual es el resto (o módulo) usamos el operador %.

Operador (%) : Resto

Si con el anterior operador obteníamos el módulo o cociente de una división entera con éste podemos tener el resto. No funciona más que con enteros, no vale para números float o double.

CODE
#include <stdio.h>

int main()
 {
 int a, b;

 a = 18;
 b = 5;
 printf( "Resto de la división: %d \n", a % b );
 }


Operadores de comparación

Los operadores de condición se utilizan para comprobar las condiciones de las sentencias de control de flujo. Cuando se evalúa una condición el resultado que se obtiene es 0 si no se cumple y un número distinto de 0 si se cumple. Normalmente cuando se cumplen devuelven un 1.

Los operadores de comparación son:

== se cumple si son iguales
!= se cumple 1 si son diferentes
> se cumple si el primero es mayor que el segundo
< se cumple si el primero es menor que el segundo
>= se cumple si el primero es mayor o igual que el segundo
<= se cumple si el primero es menor o igual que el segundo

Unos ejemplos:


CODE
#include <stdio.h>

int main()
 {
 printf( "10 > 5 da como resultado %i\n", 10>5 );
 printf( "10 > 5 da como resultado %i\n", 10>5 );
 printf( "5== 5 da como resultado %i\n", 5==5 );
 printf( "10==5 da como resultado %i\n", 10==5 );
 }


No sólo se pueden comparar constantes, también se pueden comparar variables.

Operadores lógicos

Estos son los que nos permiten unir varias comparaciones: 10>5 y 6==6. Los operadores lógicos son: AND (&&), OR (||), NOT(!).

Operador && (AND, en castellano Y): Devuelve un 1 si se cumplen dos condiciones.

CODE
printf( "Resultado: %i", (10==10 && 5>2 );


Operador || (OR, en castellano O): Devuelve un 1 si se cumple una de las dos condiciones.

Operador ! (NOT, negación): Si la condición se cumple NOT hace que no se cumpla y viceversa.

Introducción a los bits y bytes

Los bits son la unidad de información más pequeña, digamos que son la base para almacenar la información. Son como los átomos a las moléculas. Los valores que puede tomar un bit son 0 ó 1. Si juntamos ocho bits tenemos un byte.

Un byte puede tomar 256 valores diferentes (de 0 a 255). ¿Cómo se consigue esto? Imaginemos nuestro flamante byte con sus ocho bits. Supongamos que los ocho bits valen cero. Ya tenemos el valor 0 en el byte. Ahora vamos a darle al último byte el valor 1.

CODE
00000001 -> 1


Este es el uno para el byte. Ahora vamos a por el dos y el tres:

CODE
00000010 -> 2
00000011 -> 3


y así hasta 255. Como vemos con ocho bits podemos tener 256 valores diferentes, que en byte corresponden a los valores entre 0 y 255.

Operadores de bits

Ya hemos visto que un byte son ocho bits. Pues bien, con los operadores de bits podemos manipular las variables por dentro. Los diferentes operadores de bits son:

Operador - Descripción

| - OR (O)
& - AND (Y)
^ - XOR
~ - Complemento a uno o negación
>> - Desplazamiento a la derecha
<< - Desplazamiento a la izquierda

OR

Toma los valores y hace con ellos la operación OR. Vamos a ver un ejemplo:

CODE
#include <stdio.h>

int main()
 {
 printf( "El resultado de la operación 235 | 143 es: %i\n", 235 | 143 );
 }


Se obtiene: El resultado de la operación 235 | 143 es: 239

Veamos la operación a nivel de bits:

CODE
235 -> 11101011
143 -> 10001111 |
239 -> 11101111


La operación OR funciona de la siguiente manera: Tomamos los bits dos a dos y los comparamos si alguno de ellos es uno, se obtiene un uno. Si ambos son cero el resultado es cero. Primero se compara los dos primeros (el primero de cada uno de los números, 1 y 1 -> 1), luego la segunda pareja (1 y 0 -> 1) y así sucesivamente.

AND (Y)

Este operador compara los bits también dos a dos. Si ambos son 1 el resultado es 1. Si no, el resultado es cero.

CODE
#include <stdio.h>

int main()
 {
 printf( "El resultado de la operación 170 & 155 es: %i\n", 170 & 155 );
 }


Tenemos: El resultado de la operación 170 & 155 es: 138

A nivel de bits:

CODE
170 -> 10101010
155 -> 10011011 &
138 -> 10001010


XOR

Compara los bits y los pone a unos si son distintos.

CODE
235 -> 11101011
143 -> 10001111 ^
100 -> 01100100


Complemento a uno o negación

Este operador acepta un sólo dato (operando) y pone a 0 los 1 y a 1 los 0, es decir los invierte. Se pone delante del operando.

CODE
#include <stdio.h>

int main()
 {
 printf( "El resultado de la operación ~152 es: %i\n", ~152 );
 }

El resultado de la operación ~152 es: 103


CODE
152 -> 10011000 ~
103 -> 01100111


Desplazamiento a la derecha

Este operador mueve cada bit a la derecha. El bit de la izquierda se pone a cero, el de la derecha se pierde. Si realizamos la operación inversa no recuperamos el número original. El formato es:

CODE
variable o dato >> número de posiciones a desplazar


El número de posiciones a desplazar indica cuantas veces hay que mover los bits hacia la derecha. Ejemplo:

CODE
#include <stdio.h>

int main()
 {
 printf( "El resultado de la operación 150 >> 2 es: %i\n", ~152 );
 }


El resultado de la operación 150 >> 2 es: 37

Un desplazamiento a la izquierda equivale a dividir por dos. Esto es muy interesante porque el desplazamiento es más rápido que la división. Si queremos optimizar un programa esta es una buena idea. Sólo sirve para dividir entre dos. Si hacemos dos desplazamientos sería dividir por dos dos veces, no por tres.

Desplazamiento a la izquierda

Funciona igual que la anterior pero los bits se desplazan a la izquierda. Esta operación equivale a multiplicar por 2.

Operador Sizeof

Este es un operador muy útil. Nos permite conocer el tamaño en bytes de una variable. De esta manera no tenemos que preocuparnos en recordar o calcular cuanto ocupa. Además el tamaño de una variable cambia de un compilador a otro, es la mejor forma de asegurarse. Se usa poniendo el nombre de la variable después de sizeof y separado de un espacio:

CODE
#include <stdio.h>

int main()
 {
 int variable;

 printf( "Tamaño de la variable: %i\n", sizeof variable );
 }


Tambíen se puede usar con los especificadores de tipos de datos (char, int, float, double...). Pero en éstos se usa de manera diferente, hay que poner el especificador entre paréntesis:

CODE
#include <stdio.h>

int main()
 {
 printf( "Las variables tipo int ocupan: %i\n", sizeof(int) );
 }


Scanf

El uso de scanf es muy similar al de printf con una diferencia, nos da la posibilidad de que el usuario introduzca datos en vez de mostrarlos. No nos permite mostrar texto en la pantalla, por eso si queremos mostrar un mensaje usamos un printf delante. Un ejemplo:

CODE
#include <stdio.h>

int main()
{
int num;
printf( "Introduce un número " );
scanf( "%i", &num );
printf( "Has tecleado el número %i\n", num );
return 0;
}


Primero vamos a ver unas nota de estética, para hacer los programas un poco más elegantes. Parece una tontería, pero los pequeños detalles hacen que un programa gane mucho. El scanf no mueve el cursor de su posición actual, así que en nuestro ejemplo queda:

CODE
Introduce un número _  /* La barra horizontal indica dónde esta el cursor */


Esto es porque en el printf no hemos puesto al final el símbolo de salto de línea '\n'. Además hemos dejado un espacio al final de Introduce un número: para que así cuando tecleemos el número no salga pegado al mensaje. Si no hubiésemos dejado el espacio quedaría así al introducir el número 120 (es un ejemplo): Introduce un número120

Bueno, esto es muy interesante pero vamos a dejarlo y vamos al grano. Veamos cómo funciona el scanf. Lo primero nos fijamos que hay una cadena entre comillas. Esta es similar a la de printf, nos sirve para indicarle al compilador qué tipo de datos estamos pidiendo. Como en este caso es un integer usamos %i. Después de la coma tenemos la variable donde almacenamos el dato, en este caso 'num'.

Fíjate que en el scanf la variable 'num' lleva delante el símbolo &, este es muy importante, sirve para indicar al compilador cual es la dirección (o posición en la memoria) de la variable. Por ahora no te preocupes por eso, ya volveremos más adelante sobre el tema.

Podemos preguntar por más de una variable a la vez en un sólo scanf, hay que poner un %i por cada variable:

CODE
#include <stdio.h>

int main()
{
int a, b, c;

printf( "Introduce tres números: " );
scanf( "%i %i %i", &a, &b, &c );
printf( "Has tecleado los números %i %i %i\n", a, b, c );
return 0;
}


De esta forma cuando el usuario ejecuta el programa debe introducir los tres datos separados por un espacio.

A cada modificador (%i, %f) le debe corresponder una variable de su mismo tipo. Es decir, al poner un %i el compilador espera que su variable correspondiente sea de tipo int. Si ponemos %f espera una variable tipo float.

Getch y getche

usuario introduzca un carácter por el teclado. La diferencia entre getche y getch es que la primera saca por pantalla la tecla que hemos pulsado y la segunda no (la e del final se refiere a echo=eco). Ejemplos:

CODE
#include <stdio.h>

int main()
{
char letra;

printf( "Introduce una letra: " );
fflush( stdout );
letra = getche();
printf( "\nHas introducido la letra: %c", letra );
return 0;
}


Resultado:
Introduce una letra: a
Has introducido la letra: a

Quizás te estés preguntando qué es eso de fflush( stdout ). Pues bien, cuando usamos la función printf, no escribimos directamente en la pantalla, sino en una memoria intermedia (lo que llaman un bufer). Cuando este bufer se llena o cuando metemos un carácter '\n' es cuando se envia el texto a la pantalla. En este ejemplo yo quería que apareciera el mensaje Introduce una letra: y el cursor se quedara justo después, es decir, sin usar '\n'. Si se hace esto, en algunos compiladores el mensaje no se muestra en pantalla hasta que se pulsa una tecla (pruébalo en el tuyo). Y la función fflush( stdout ) lo que hace es enviar a la pantalla lo que hay en ese bufer.

Y ahora un ejemplo con getch:

CODE
#include <stdio.h>

int main()
{
char letra;

printf( "Introduce una letra: " );
fflush( stdout );
letra = getch();
printf("\n has introducido la letra :%c", letra );
return 0;
}


Resultado:
Introduce una letra:
Has introducido la letra: a

Como vemos la única diferencia es que en el primer ejemplo se muestra en pantalla lo que escribimos y en el segundo no.


Hasta ahora los programas que hemos visto eran lineales. Comenzaban por la primera instrucción y acababan por la última, ejecutándose todas una sola vez. . Lógico ¿no?. Pero resulta que muchas veces no es esto lo que queremos que ocurra. Lo que nos suele interesar es que dependiendo de los valores de los datos se ejecuten unas instrucciones y no otras. O también puede que queramos repetir unas instrucciones un número determinado de veces. Para esto están las sentencia de control de flujo.

Bucles

Los bucles nos ofrecen la solución cuando queremos repetir una tarea un número determinado de veces. Supongamos que queremos escribir 100 veces la palabra hola. Con lo que sabemos hasta ahora haríamos:

CODE
#include <stdio.h>

int main()
 {
 printf( "Hola\n");
 printf( "Hola\n");
 printf( "Hola\n");
 printf( "Hola\n");
 }


Y asi hasta 100..

¡¡Vaya locura!! Y si queremos repetirlo más veces nos quedaría un programa de lo más largo.

Sin embargo usando un bucle for el programa quedaría:

CODE
#include <stdio.h>
int main()
 {
 int i;
 for ( i=0; i<100; i++ )
  {
  printf( "Hola\n" );
  }
 }


Con lo que tenemos un programa más corto.

El bucle For

El formato del bucle for es el siguiente:

CODE
for( dar valores iniciales; condiciones; incrementos )
 {
 conjunto de intrucciones a ejecutar en el bucle
 }


Vamos a verlo con el ejemplo anterior:

CODE
...
for ( i=0; i<100; i++ )
...


Como vemos, el for va delante del grupo de instrucciones a ejecutar, de manera que si la condición es falsa, esas instrucciones no se ejecutan ni una sola vez.

Cuidado: No se debe poner un ";" justo después de la sentencia for, pues entonces sería un bucle vacío y las instrucciones siguientes sólo se ejecutarían una vez. Veamoslo con un ejemplo:

CODE
#include <stdio.h>
int main()
 {
 int i;
 for ( i=0; i<100; i++ );
  {
  printf( "Hola\n" );
  }
 }


Esto escribirá Hola en pantalla, una vez.

Tambíen puede suceder que quieras ejecutar un cierto número de veces una sóla instrucción (como sucede en nuestro ejemplo). Entonces no necesitas las llaves:

CODE
#include <stdio.h>
int main()
 {
 int i;
 for ( i=0; i<100; i++ ) printf( "Hola\n" );
 }


Sin embargo, yo me he encontrado muchas veces que es mejor poner las llaves aunque sólo haya una instrucción; a veces al añadir una segunda instrucción más tarde se te olvidan las comillas y no te das cuenta. Parece una tontería, pero muchas veces, cuando programas, son estos los pequeños fallos los que te vuelven loco.

También se pueden poner más de una variable a inicializar, más de una condición y más de un incremento. Por ejemplo, el siguiente programa sería perfectamente correcto:

CODE
#include <stdio.h>

int main()
{
int i, j;

for( i=0, j=5; i<10; i++, j=j+5 )
 {
 printf( "Hola " );
 printf( "Esta es la línea %i", i );
 printf( "j vale = %i\n", j );
 }
}


Como vemos en el ejemplo tenemos más de una variable en la sección de inicialización y en la de incrementos. También podíamos haber puesto más de una condición. Los elementos de cada sección se separan por comas. Cada sección se separa por punto y coma.

While

El formato del bucle while es es siguiente:

CODE
while ( condición )
 {
 bloque de instrucciones a ejecutar
 }


While quiere decir mientras. Aquí se ejecuta el bloque de intrucciones mientras se cumpla la condición impuesta en while.

Vamos a ver un ejemplo:

CODE
#include <stdio.h>

int main()
 {
 int contador = 0;

 while ( contador<100 )
  {
  contador++;
  printf( "Ya voy por el %i, pararé enseguida.\n", contador );
  }
 }


Este programa imprime en pantalla los valores del 1 al 100. Cuando i=100 ya no se cumple la condición.

Do While

El formato del bucle do-while es:

CODE
do
 {
 instrucciones a ejecutar
 } while ( condición );


La diferencia entre while y do-while es que en este último, la condición va despues del conjunto de instrucciones a ejecutar. De esta forma, esas instrucciones se ejecutan al menos una vez.

Sentencias de condición

Hasta aquí hemos visto cómo podemos repetir un conjunto de instrucciones las veces que deseemos. Pero ahora vamos a ver cómo podemos controlar totalmente el flujo de un programa. Dependiendo de los valores de alguna variable se tomarán unas acciones u otras. Empecemos con la sentencia if.

If

La palabra if significa si (condicional), pero supongo que esto ya lo sabías. Su formato es el siguiente:

CODE
if ( condición )
 {
 instrucciones a ejecutar
 }


Cuando se cumple la condición entre paréntesis se ejecuta el bloque inmediatamente siguiente al if (bloque instrucciones a ejecutar).

En el siguiente ejemplo tenemos un programa que nos pide un número, si ese número es 10 se muestra un mensaje. Si no es 10 no se muestra ningún mensaje:

CODE
#include <stdio.h>

int main()
 {
 int num;

 printf( "Introduce un número " );
 scanf( "%i", &num );
 if (num==10)
  {
  printf( "El número es correcto\n" );
  }
 }


>>






--------------------
user posted imageuser posted imageuser posted image
user posted image
PMEmail PosterUsers WebsiteMSN
Top
TvK10
Publicado: Jul 28 2007, 12:20 PM
Quote Post


**Ubuntero**
Group Icon

Grupo: Colaboradores
Mensajes: 1.398
Miembro nº: 22.588
Registrado: 1-May 07



Punteros

Si hasta ahora te había parecido complicado prepárate. Este es uno de los temas que más suele costar a la gente al aprender C. Los punteros son una de las más potentes características de C, pero a la vez uno de sus mayores peligros. Los punteros nos permiten acceder directamente a cualquier parte de la memoria. Esto da a los programas C una gran potencia. Sin embargo son una fuente ilimitada de errores. Un error usando un puntero puede bloquear el sistema (si usamos ms-dos o win95, no en Linux) y a veces puede ser difícil detectarlo.

Otros lenguajes no nos dejan usar punteros para evitar estos problemas, pero a la vez nos quitan parte del control que tenemos en C. No voy a entrar a discutir si es mejor o no poder usar punteros, aunque pienso que es mejor. Yo me voy a limitar a explicar cómo funcionan.

A pesar de todo esto no hay que tenerles miedo. Casi todos los programas C usan punteros. Si aprendemos a usarlos bien no tendremos mas que algún problema esporádico.

¿Qué son los Punteros?

Un puntero es una variable un tanto especial. Con un puntero podemos almacenar direcciones de memoria. En un puntero podemos tener guardada la dirección de una variable.

Vamos a ver si cogemos bien el concepto de puntero y la diferencia entre éstos y las variables normales.

user posted image

En el dibujo anterior tenemos una representación de lo que sería la memoria del ordenador. Cada casilla representa un byte de la memoria. Y cada número es su dirección de memoria. La primera casilla es la posición 00001 de la memoria. La segunda casilla la posición 00002 y así sucesivamente.

Supongamos que ahora declaramos una variable char: char numero = 43. El ordenador nos guardaría por ejemplo la posición 00003 para esta variable. Esta posición de la memoria queda reservada y ya no la puede usar nadie más. Además esta posición a partir de ahora se le llama numero. Como le hemos dado el valor 43 a numero, el valor 43 se almacena en numero, es decir, en la posición 00003.

user posted image

Si ahora usáramos el programa anterior:

CODE
#include <stdio.h>

int main()
    {
    int numero;

    numero = 43;
    printf( "Dirección de numero = %p, valor de numero = %i\n", &numero, numero );
    }


Creo que así ya está clara la diferencia entre el valor de una variable (43) y su dirección (00003). Ahora vamos un poco más allá, vamos a declarar un puntero. Hemos dicho que un puntero sirve para almacenar la direcciones de memoria. Muchas veces los punteros se usan para guardar las direcciones de variables. Vimos en el capítulo Tipos de Datos que cada tipo de variable ocupaba un espacio distinto. Por eso cuando declaramos un puntero debemos especificar el tipo de datos cuya dirección almacenará. En nuestro ejemplo queremos que almacene la dirección de una variable char. Así que para declarar el puntero punt debemos hacer:

CODE
char *punt;


El * (asterisco) sirve para indicar que se trata de un puntero, debe ir justo antes del nombre de la variable, sin espacios. En la variable punt sólo se pueden guardar direcciones de memoria, no se pueden guardar datos. Vamos a volver sobre el ejemplo anterior un poco ampliado para ver cómo funciona un puntero:

CODE
#include <stdio.h>

int main()
    {
    int numero;
    int *punt;

    numero = 43;
    punt = &numero;
    printf( "Dirección de numero = %p, valor de numero = %i\n", &numero, numero );
    }


int numero -> Reservamos memoria para numero (supongamos que queda como antes, posición 00003). Por ahora numero no tiene ningún valor.

int *punt; -> Reservamos una posición de memoria para almacenar el puntero. Lo normal es que según se declaran variables se guarden en posiciones contiguas. De modo que quedaría en la posición 00004. Por ahora punt no tiene ningún valor, es decir, no apunta a ninguna variable. Esto es lo que tenemos por ahora:

user posted image

numero = 43; -> Aquí ya estamos dando el valor 43 a numero. Se almacena 43 en la dirección 00003, que es la de numero.

punt = &numero; -> Por fin damos un valor a punt. El valor que le damos es la dirección de numero (ya hemos visto que & devuelve la dirección de una variable). Así que punt tendrá como valor la dirección de numero, 00003. Por lo tanto ya tenemos:

user posted image

Cuando un puntero tiene la dirección de una variable se dice que ese puntero apunta a esa variable.

En general la declaración es:

CODE
tipo_de_dato *nombre_del_puntero;


Si en vez de querer apuntar a una variable tipo char como en el ejemplo hubiese sido de tipo int:

CODE
int *punt;


Otras utilidades Puntero

Los punteros tienen muchas utilidades, por ejemplo nos permiten pasar argumentos (o parámetros) a una función y modificarlos. También permiten el manejo de cadenas y de arrays. Otro uso importante es que nos permiten acceder directamente a la pantalla, al teclado y a todos los componenetes del ordenador. Pero esto ya lo veremos más adelante.

Pero si sólo sirvieran para almacenar direcciones de memoria no servirían para mucho. Nos deben dejar también la posibilidad de acceder a esas posiciones de memoria. Para acceder a ellas se usa el operador *, que no hay que confundir con el de la multiplicación.

CODE
#include <stdio.h>

int main()
    {
    int numero;
    int *punt;

    numero = 43;
    punt = &numero;
    printf( "Dirección de numero = %p, valor de numero = %i\n", &numero, *punt );
    }


Si nos fijamos en lo que ha cambiado con respecto al ejemplo anterior, vemos que para acceder al valor de número usamos *punt en vez de numero. Esto es así porque punt apunta a numero y *punt nos permite acceder al valor al que apunta punt.

CODE
#include <stdio.h>

int main()
    {
    int numero;
    int *punt;

    numero = 43;
    punt = &numero;
    *punt = 30;
    printf( "Dirección de numero = %p, valor de numero = %i\n", &numero, numero );
    }


Ahora hemos cambiado el valor de numero a través de *punt.

En resumen, usando punt podemos apuntar a una variable y con *punt vemos o cambiamos el contenido de esa variable.

Veamos el siguiente ejemplo. Queremos comprobar si dos variables son iguales usando punteros:

CODE
#include <stdio.h>

int main()
    {
    int a, b;
    int *punt1, *punt2;

    a = 5; b = 5;
    punt1 = &a; punt2 = &b;

    if ( punt1 == punt2 )
    printf( "Son iguales\n" );
    }


Alguien podría pensar que el if se cumple y se mostraría el mensaje Son iguales en pantalla. Pues no es así, el programa es erróneo. Es cierto que a y b son iguales. También es cierto que punt1 apunta a 'a' y punt2 a 'b'. Lo que queríamos comprobar era si a y b son iguales. Sin embargo con la condición estamos comprobando si punt1 apunta al mismo sitio que punt2, estamos comparando las direcciones donde apuntan. Por supuesto a y b están en distinto sitio en la memoria así que la condición es falsa. Para que el programa funcionara deberíamos usar los asteriscos:

CODE
#include <stdio.h>

int main()
    {
    int a, b;
    int *punt1, *punt2;

    a = 5; b = 5;
    punt1 = &a; punt2 = &b;

    if ( *punt1 == *punt2 )
    printf( "Son iguales\n" );
    }


Ahora sí. Estamos comparando el contenido de las variables a las que apuntan punt1 y punt2. Debemos tener mucho cuidado con esto porque es un error que se cuela con mucha facilidad.

Ahora vamos a ver cómo los punteros nos permites modificar varias variables en una función.

Hasta ahora para pasar una variable a una función hacíamos lo siguiente:

CODE
#include <stdio.h>

int suma( int a, int b )
    {
    return a+b;
    }

int main()
    {
    int var1, var2, resultado;

    var1 = 5; var2 = 8;
 resultado = suma(var1, var2);
    printf( "La suma es : %i\n", resultado );
    }


Bien aquí hemos pasado a la función los parámetros 'a' y 'b' (que no podemos modificar) y nos devuelve la suma de ambos. Supongamos ahora que queremos tener la suma pero además queremos que var1 se haga cero dentro de la función. Para eso haríamos lo siguiente:

CODE
#include <stdio.h>

int suma( int *a, int b )
    {
    int c;

    c = *a + b;
    *a = 0;
    return c;
    }

int main()
    {
    int var1, var2, resultado;

    var1 = 5; var2 = 8;
 resultado = suma(&var1, var2);
    printf( "La suma es: %i y a vale: %i\n", resultado , var1 );
    }


Fijémonos en lo que ha cambiado, en la función suma hemos declarado 'a' como puntero. En la llamada a la función (dentro de main) hemos puesto & para pasar la dirección de la variable var1. Ya sólo queda hacer cero a var1 a través de *a=0.

También usamos una variable 'c' que nos servirá para almacenar la suma de 'a' y 'b'.

Es importante no olvidar el operador & en la llamada a la función ya que sin el no estaríamos pasando la dirección de la variable sino cualquier otra cosa.

Podemos usar tantos punteros como queramos en la definición de la función.

Array

Un array es un conjunto de variables del mismo tipo que tienen el mismo nombre y se diferencian en el índice.

Supongamos que somos un metereólogo y queremos guardar en el ordenador la temperatura que ha hecho cada hora del dia. Para darle cierta utilidad al final calcularemos la media de las temperaturas. Con lo que sabemos hasta ahora sería algo así (que nadie se moleste ni en probarlo):

CODE
#include <stdio.h>

int main()
    {
    /* Declaramos 24 variables, una para cada hora del dia */
    int temp1,  temp2,  temp3,  temp4,  temp5,  temp6,  temp7,  temp8;
    int temp9,  temp10, temp11, temp12, temp13, temp14, temp15, temp16;
    int temp17, temp18, temp19, temp20, temp21, temp22, temp23, temp0;
    int media;

    /* Ahora tenemos que dar el valor de cada una */
    printf( "Temperatura de las 0: " );
    scanf( "%i", &temp0 );
    printf( "Temperatura de las 1: " );
    scanf( "%i", &temp1 );
    printf( "Temperatura de las 2: " );
    scanf( "%i", &temp2 );
    ...
    printf( "Temperatura de las 23: " );
    scanf( "%i", &temp23 );

    media = ( temp0 + temp1 + temp2 + temp3 + temp4 + ... + temp23 ) / 24;
    printf( "\nLa temperatura media es %i\n", media );
    }


(Los puntos suspensivos los he puesto para no tener que escribir todo y que no ocupe tanto, no se pueden usar en un programa).

Para acortar un poco el programa podríamos hacer algo así:

CODE
#include <stdio.h>

int main()
    {
    /* Declaramos 24 variables, una para cada hora del dia */
    int temp1,  temp2,  temp3,  temp4,  temp5,  temp6,  temp7,  temp8;
    int temp9,  temp10, temp11, temp12, temp13, temp14, temp15, temp16;
    int temp17, temp18, temp19, temp20, temp21, temp22, temp23, temp0;
    int media;

    /* Ahora tenemos que dar el valor de cada una */
    printf( "Introduzca las temperaturas desde las 0 hasta las 23 separadas por un espacion: " );
    scanf( "%i %i %i ... %i", &temp0, &temp1, &temp2, ... &temp23 );

    media = ( temp0 + temp1 + temp2 + temp3 + temp4 + ... + temp23 ) / 24;
    printf( "\nLa temperatura media es %i\n", media );
    }


Y esto con un ejemplo que tiene tan sólo 24 variables, ¡¡imagínate si son más!!

Y precisamente aquí es donde nos vienen de perlas los arrays. Vamos a hacer el programa con un array. Usaremos nuestros conocimientos de bucles for y de scanf.

CODE
#include <stdio.h>

int main()
    {
    int temp[24]; /* Con esto ya tenemos declaradas las 24 variables */
    float media = 0;
    int hora;

    /* Ahora tenemos que dar el valor de cada una */
    for( hora=0; hora<24; hora++ )
         {
         printf( "Temperatura de las %i: ", hora );
         scanf( "%i", &temp[hora] );
         media += temp[hora];
         }
    media = media / 24;

    printf( "\nLa temperatura media es %f\n", media );
    }


Como ves es un programa más rápido de escribir (y es menos aburrido hacerlo), y más cómodo para el usuario que el anterior.

Como ya hemos comentado cuando declaramos una variable lo que estamos haciendo es reservar una zona de la memoria para ella. Cuando declaramos un array lo que hacemos (en este ejemplo) es reservar espacio en memoria para 24 variables de tipo int. El tamaño del array (24) lo indicamos entre corchetes al definirlo. Esta es la parte de la definición que dice: Un array es un conjunto de variables del mismo tipo que tienen el mismo nombre.

La parte final de la definición dice: y se diferencian en el índice. En ejemplo recorremos la matriz mediante un bucle for y vamos dando valores a los distintos elementos de la matriz. Para indicar a qué elemento nos referimos usamos un número entre corchetes (en este caso la variable hora), este número es lo que se llama Indice. El primer elemento de la matriz en C tiene el índice 0, El segundo tiene el 1 y así sucesivamente. De modo que si queremos dar un valor al elemento 4 (índice 3) haremos:

CODE
temp[ 3 ] = 20;


Declaración de un Array

La forma general de declarar un array es la siguiente:

CODE
tipo_de_dato nombre_del_array[ dimensión ];


El tipo_de_dato es uno de los tipos de datos conocidos (int, char, float...) o de los definidos por el usuario con typdef. En el ejemplo era int.

El nombre_del_array es el nombre que damos al array, en el ejemplo era temp.

La dimensión es el número de elementos que tiene el array.

Inicializar un Array

En C se pueden inicializar los arrays al declararlos igual que hacíamos con las variables. Recordemos que se podía hacer:

CODE
int hojas = 34;


Pues con arrays se puede hacer:

CODE
int temperaturas[24] = { 15, 18, 20, 23, 22, 24, 22, 25, 26, 25, 24, 22,
                           21, 20, 18, 17, 16, 17, 15, 14, 14, 14, 13, 12 };


Ahora el elemento 0 (que será el primero), es decir temperaturas[0] valdrá 15. El elemento 1 (el segundo) valdrá 18 y así con todos. Vamos a ver un ejemplo:

CODE
#include <stdio.h>

int main()
    {
    int hora;
    int temperaturas[24] = { 15, 18, 20, 23, 22, 24, 22, 25, 26, 25, 24,
                                 22, 21, 20, 18, 17, 16, 17, 15, 14, 14, 14, 13, 12 };

    for (hora=0; hora<24; hora++ )
        {
        printf( "La temperatura a las %i era de %i grados.\n", hora, temperaturas[hora] );
        }
    }


Hemos indicado al compilador que nos reserve memoria para un array de 24 elementos de tipo int. ¿Qué ocurre si metemos menos de los reservados? Pues no pasa nada, sólo que los elementos que falten valdrán cero.

De Puntero a Array

Aquí tenemos otro de los importantes usos de los punteros, los punteros a arrays. Estos están íntimamente relacionados.

Para que un puntero apunte a un array se puede hacer de dos formas, una es apuntando al primer elemento del array:



CODE
int *puntero;
int temperaturas[24];

puntero = &temperaturas[0];


Ahora vamos a ver cómo acceder al resto de los elementos. Para ello empezamos por cómo funciona un array: Un array se guarda en posiciones seguidas en memoria, de tal forma que el segundo elemento va inmediatamente después del primero en la memoria. En un ordenador en el que el tamaño del tipo int es de 32 bits (4 bytes) cada elemento del array ocupará 4 bytes. Veamos un ejemplo:

CODE
#include <stdio.h>

int main()
    {
    int i;
    int temp[24];

    for( i=0; i<24; i++ )
         {
         printf( "La dirección del elemento %i es %p.\n", i, &temp[i] );
         }
    }


Recuerda que %p sirve para imprimir en pantalla la dirección de una variable en hexadecimal.

De Array a Función

En C no podemos pasar un array entero a una función. Lo que tenemos que hacer es pasar un puntero al array. Con este puntero podemos recorrer el array:

CODE
#include <stdio.h>

int sumar( int *m )
    {
    int suma, i;

    suma = 0;
    for( i=0; i<10; i++ )
         {
         suma += m[i];
         }
    return suma;
    }

int main()
    {
    int contador;
    int matriz[10] = { 10, 11, 13, 10, 14, 9, 10, 18, 10, 10 };

    for( contador=0; contador<10; contador++ )
         printf( "   %3i\n", matriz[contador] );
    printf( "+ -----\n" );
    printf( "   %3i", sumar( matriz ) );
    }


Este programa tiene alguna cosilla adicional como que muestra toda la matriz en una columna. Además se usa para imprimir los números %3i. El 3 indica que se tienen que alinear los números a la derecha, así queda más elegante.

Como he indicado no se pasa el array, sino un puntero a ese array. Si probamos el truquillo de más arriba de usar sizeof para calcular el número de elementos no funcionará aquí. Dentro de la función suma añadimos la línea:

CODE
   printf( "Tamaño del array: %i Kb, %i bits\n", sizeof m, (sizeof m)*8 );


Devolverá 4 (depende del compilador) que serán los bytes que ocupa el int (m es un puntero a int). ¿Cómo sabemos entonces cual es el tamaño del array dentro de la función? En este caso lo hemos puesto nosotros mismos, 10. Pero es mejor utilizar constantes.

Strings

Vamos a ver por fin cómo manejar texto con C, hasta ahora sólo sabíamos cómo mostrarlo por pantalla.

Para empezar diré que en C no existe un tipo string como en otros lenguajes. No existe un tipo de datos para almacenar texto, se utilizan arrays de chars. Funcionan igual que los demás arrays con la diferencia que ahora jugamos con letras en vez de con números.

Se les llama cadenas, strings o tiras de caracteres. A partir de ahora les llamaremos cadenas.

Para declarar una cadena se hace como un array:

CODE
char texto[20];


Al igual que en los arrays no podemos meter más de 20 elementos en la cadena. Vamos a ver un ejemplo para mostrar el nombre del usuario en pantalla:

CODE
#include <stdio.h>

int main()
    {
    char nombre[20];

    printf( "Introduzca su nombre (20 letras máximo): " );
    scanf( "%s", nombre );
    printf( "\nEl nombre que ha escrito es: %s\n", nombre );
    }


Es interesante saber cómo funciona una cadena por dentro, por eso vamos a ver primero cómo se inicializa una cadena.

CODE
#include <stdio.h>

int main()
    {
    char nombre[] = "TvK10";

    printf( "Texto: %s\n", nombre );
    printf( "Tamaño de la cadena: %i bytes\n", sizeof nombre );
    }


Funciones de manejo de cadenas

Existen unas cuantas funciones el la biblioteca estándar de C para el manejo de cadenas:
  • strlen
  • strcpy
  • strcat
  • sprintf
  • strcmp
Para usar estas funciones hay que añadir la directiva:

CODE
#include <string.h>


strlen

Esta función nos devuelve el número de caracteres que tiene la cadena (sin contar el '\0').

CODE
#include <stdio.h>
#include <string.h>

int main()
    {
    char texto[]="Gorka";
    int longitud;

    longitud = strlen(texto);
    printf( "La cadena \"%s\" tiene %i caracteres.\n", texto, longitud );
    }


Para medir la longitud de la cadena usamos un puntero para recorrerla (el puntero p). Hacemos que p apunte a texto. Luego entramos en un bucle while. La condición del bucle comprueba si se ha llegado al fin de cadena ('\0'). Si no es así suma 1 a longitud, muestra la letra por pantalla e incrementa el puntero en 1 (con esto pasamos a la siguiente letra).

strcpy

CODE
#include <string.h>

    char *strcpy(char *cadena1, const char *cadena2);


Copia el contenido de cadena2 en cadena1. cadena2 puede ser una variable o una cadena directa (por ejemplo "hola"). Debemos tener cuidado de que la cadena destino (cadena1) tenga espacio suficiente para albergar a la cadena origen (cadena2).



CODE
#include <string.h>

    char *strcat(char *cadena1, const char *cadena2);


Copia la cadena2 al final de la cadena1.

sprintf

CODE
#include <stdio.h>

    int sprintf(char *destino, const char *format, ...);


Funciona de manera similar a printf, pero en vez de mostrar el texto en la pantalla lo guarda en una variable (destino). El valor que devuelve (int) es el número de caracteres guardados en la variable destino.

strcmp

CODE
#include <string.h>

    int strcmp(const char *cadena1, const char *cadena2);


Compara cadena1 y cadena2. Si son iguales devuelve 0. Un número negativo si cadena1 va antes que cadena2 y un número positivo si es al revés.

tolower

La función tolower() nos permite convertir una cadena a minúsculas:

CODE
char *tolower( char *cadena );


toupper

toupper cumple la función contraria, convierte la cadena a mayúsculas:

CODE
char *toupper( char *cadena );


gets

Esta función nos permite introducir frases enteras, incluyendo espacios.

CODE
#include <stdio.h>

    char *gets(char *buffer);


Almacena lo que vamos tecleando en la variable buffer hasta que pulsamos ENTER. Si se ha almacenado algún caracter en buffer le añade un '\0' al final y devuelve un puntero a su dirección. Si no se ha almacenado ninguno devuelve un puntero NULL.

CODE
#include <stdio.h>
#include <string.h>

int main()
    {
    char cadena[30];
    char *p;

    printf( "Escribe una palabra: " );
    fflush( stdout );
    p = gets( cadena );
    if (p) printf( "He guardado: \"%s\" \n", cadena );
    else printf( "No he guardado nada!\n" );
    }


Esta función es un poco peligrosa porque no comprueba si nos hemos pasado del espacio reservado (de 29 caracteres en este ejemplo: 29letras+'\0').

Hasta aqui este Tutorial de C..espero que os haya gustado..

TvK10


¿Quieres ganar dinero escribiendo sobre tus aficiones? - www.Redactores.es



--------------------
user posted image