-^Blue Hacking^-

El mejor hacking al alcance de todos
 
ÍndiceFAQRegistrarseConectarse

Comparte | 
 

 Curso programación en C

Ver el tema anterior Ver el tema siguiente Ir abajo 
Ir a la página : 1, 2, 3  Siguiente
AutorMensaje
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Curso programación en C   Jue Oct 16, 2008 6:06 pm

Curso C -La idea es que hire insertando temario poco a poco-
TEMAS BASICOS.
Tema 0. Sobre el curso.
Tema 1. Generalidades.
Tema 2. Introd. a variables
Tema 3. Recapitulación.
Tema 4. Entrada/Salida básica.
Tema 5. Operaciones matemáticas.
Tema 6. Condiciones.
Tema 7. Bucles.
Tema 8. Constantes y tipos.
Tema 9. Funciones.
Tema 10. Punteros.
Tema 11. Ficheros.
Tema 12. Cadenas de texto.
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Jue Oct 16, 2008 6:38 pm

CURSO DE C. TEMA 0: SOBRE EL CURSO.

Este curso nace como ampliación de un curso de Pascal que impartí en la conferencia Pascal_E de Fidonet entre Enero y Agosto de 1995 (los que tengan dicho curso podrán comprobar que sigo prácticamente la misma estructura).

Por ello, supondré que se entienden términos como compilador, editor, linker, etc., y que se tienen unos conocimientos básicos de programación, a fin de poder avanzar más rápido.

En cuanto a estos conocimientos básicos, daré por supuesto también que son conocimientos de lenguaje Pascal (Turbo Pascal), que es en el que me apoyaré para la mayoría de las comparaciones. Aun así, no debería ser difícil seguirlo si se ha programado en otros lenguajes, como Basic (especialmente si es alguno "moderno", como QBasic).

Este programa se distribuye "tal cual", sin garantía de ningún tipo, implícita ni explícita. Aun así, mi intención es que resulte útil, así que le rogaría que me comunique cualquier error que encuentre.

Esta es una versión de libre distribución del curso. Es un programa GRATIS, que puede grabar a quien quiera, siempre y cuando lo distribuya completo y no lo modifique. Gracias.

(Si desea profundizar más, también existe una versión ampliada de este curso).


Para cualquier sugerencia, no dude en contactar conmigo.
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Vie Oct 17, 2008 5:16 pm

CURSO DE C. TEMA 1.

Generalidades del C

Nota: Para que todo esto no resulte demasiado pesado, voy a procurar ir lo más directo al grano que me sea posible, intentando que haya poca teoría y mucha práctica. Para ello, supondré que ya se tienen unos ciertos conocimientos de programación (me apoyaré principalmente en el lenguaje Pascal, como he mencionado en el apartado anterior.

Como a programar se aprende programando, voy a tratar de enfocar este curso al revés de como lo hace la mayoría de los libros: en vez de dar primero toda la carga teórica y después aplicarlo, voy a ir poniendo ejemplos, y a continuación la explicación.

Así que empezamos. Ahí va uno:

/*-------------------------*/
/* Primer ejemplo en C: */
/* EJ01.C */

/* */
/* Programa elemental */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

main()
{
printf("Hola");


/*-------------------------*/


Este es un programa que escribe "Hola" en la pantalla. Nos lo creemos, verdad? Bueno, pues ahora vamos a ir comentando cosas sobre él:

· Lo que hay escrito entre /* y */ es un COMENTARIO, que sirve para aclararnos algo a nosotros, pero que el compilador "se salta" sin ningún tipo de reparo. Es conveniente escribir comentarios que aclaren la misión de las partes de nuestros programas que puedan resultar menos claras a simple vista. Incluso es aconsejable que el programa comience con un comentario (como en este caso), que nos recuerde qué hace el programa sin que necesitemos mirarlo de arriba a abajo. Un comentario puede empezar en una línea y terminar en otra distinta, así:

/* Esto
es un comentario que
ocupa más de una línea
*/

· Eso de "#include" recuerda mucho al "uses" de Turbo Pascal, y de momento me limitaré a comentar que también nos permite AMPLIAR el lenguaje base. En este caso, hemos incluido un fichero "de cabecera" llamado "stdio.h" (standard i/o, entrada y salida estándar), que es el que define la orden "printf".

¿Y por qué se pone entre < y >? ¿Y por qué eso de # al principio? "Porque sí..." No, esto no es cierto del todo, hay razones... que ya iremos viendo más adelante.

· Ya que estamos con él: por si es poco evidente, "printf" es la orden que se encarga de mostrar un texto en pantalla. Como he comentado de pasada, esta función es la responsable de que hayamos escrito "stdio.h" al principio del programa. Resulta que en el lenguaje C base no hay predefinida ninguna orden para escribir en pantalla (!), sino que están definidas en "stdio.h". Pero esto tampoco es mayor problema, porque vamos a encontrar el dichoso "stdio.h" en cualquier compilador que usemos.

· Aun quedan cosas: ¿qué pintan esas llaves { y } ? Al igual que el Pascal y la mayoría de los lenguajes actuales, el C es un lenguaje estructurado, en el que un programa está formado por diversos "bloques". Todos los elementos que componen este bloque deben estar relacionados entre sí, lo que se indica encerrándolos entre llaves: { y } (el equivalente de "begin" y "end" de Pascal).

· Finalmente, qué es eso de "main"? Es algo que debe existir siempre, e indica el punto en el que realmente comenzará a funcionar el programa. Después de "main" van dos llaves { y }, que delimitan lo que realmente es el cuerpo del programa.

Por cierto, esta función llamada "main" debe existir siempre.

· Y por qué tiene un paréntesis vacío a continuación? Pues precisamente para indicar que se trata de una función (ya las estudiaremos más adelante, para quien aún no sepa lo que son). En Pascal, cuando una función no tiene parámetros, no se pone ni siquiera los paréntesis; en C hay que ponerlos, aunque queden vacíos (si no hay ningún parámetro, como en este caso).

Y la cosa no acaba aquí. Aún queda más miga de la que parece en este programa, pero cuando ya vayamos practicando un poco iremos concretando más alguna que otra cosa de las que aquí han quedado un tanto por encima.


Sólo un par de cosas más antes de seguir adelante:

· Cada orden de C debe terminar con un PUNTO Y COMA (al igual que en Pascal; aun así, hay algunas pequeñas diferencias que ya iremos viendo).

· El C es un lenguaje de formato libre, de modo que puede haber varias órdenes en una misma línea, u órdenes separadas por varias líneas o espacios entre medias. Lo que realmente indica dónde termina una órden y donde empieza la siguiente son los puntos y coma, como acabo de comentar. Por ese motivo, el programa anterior se podría haber escrito también así (aunque no es aconsejable, porque puede resultar menos legible):

#include <stdio.h>
main() { printf("Hola");

· La gran mayoría de las órdenes que encontraremos en el lenguaje C son palabras en inglés o abreviaturas de éstas, al igual que ocurre en la mayoría de los lenguajes de programación. En cambio, en C y al contrario que en otros lenguajes (como Pascal o Basic, por ejemplo) sí existe DISTINCION entre mayúsculas y minúsculas, por lo que "printf" es una palabra reconocida, pero "Printf", "PRINTF" o "PrintF" no lo son.

· Como veremos más adelante, en Pascal se distingue entre "funciones" (function), que realizan una serie de operaciones y devuelven un valor, y "procedimientos" (procedure), que no devuelven ningún valor. Ahora sólo tendremos FUNCIONES, pero algunas de ellas podrán ser de un cierto tipo "nulo", con lo cual equivalen a los procedimientos de Pascal.

Ya sabemos escribir, pero eso no nos bastará en la mayoría de los casos, así que sigamos viendo cosas nuevas...
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Dom Oct 19, 2008 5:51 pm

CURSO DE C. TEMA 2.
Introducción al manejo de variables

Las variables son algo que no contiene un valor predeterminado, un espacio de memoria al que nosotros asignamos un nombre y en el que podremos almacenar datos.

En el primer ejemplo nos permitía escribir "Hola", pero normalmente no sabremos de antemano lo que vamos a escribir, sino que dependerá de una serie de cálculos previos (el total de una serie de números que hemos leído, por ejemplo).

Por eso necesitaremos usar variables, en las que guardemos los datos con los que vamos a trabajar y también los resultados temporales.

Vamos a ver primero cómo sumaríamos dos números enteros que fijemos en el programa:

/*-------------------------*/
/* Ejemplo en C nº 2: */
/* EJ02.C */
/* */
/* Introd. a variables */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */

/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int primerNumero; /* Nuestras variables */
int segundoNumero;
int suma;

main()
{
primerNumero = 234;
segundoNumero = 567;
suma = primerNumero + segundoNumero;

printf("Su suma es %d", suma);
}

/*-------------------------*/

Para usar una cierta variable primero hay que declararla: indicar su nombre y el tipo de datos que querremos guardar.

En este ejemplo vemos como se declaran las variables en C: indicando primero el tipo del que son (en este caso "int", números enteros) y a continuación el nombre que les vamos a dar:

int primerNumero;

Esta línea quiere decir que usaremos una variable, cuyo nombre es "primerNumero", y que el valor que guardará esa variable será un número entero. Posteriormente, con

primerNumero = 234;


asignamos un valor a esa variable.

Estos nombres de variable (identificadores) siguen prácticamente las mismas reglas de sintaxis que en otros lenguajes como Pascal: pueden estar formados por letras, números o el símbolo de subrayado (_) y deben comenzar por letra o subrayado. No deben tener espacios entre medias, y hay que recordar que las vocales acentuadas y la eñe son problemáticas, porque no son letras "estándar" en todos los idiomas. Algunos compiladores permiten otros símbolos, como el $, pero es aconsejable no usarlos, de modo que el programa sea más portable.

Por eso, no son nombres de variable válidos:

1numero (empieza por número)

un numero (contiene un espacio)
Año1 (tiene una eñe)
MásDatos (tiene una vocal acentuada)

Tampoco podremos usar como identificadores las palabras reservadas de C. Por ejemplo, la palabra "int" se refiere a que cierta variable guardará un número entero, así que esa palabra "int" no la podremos usar tampoco como nombre de variable. No voy a incluir una lista de palabras reservadas de C, porque eso supondría tener que comentar al menos para que sirven, y además nos encontramos con que hay incluso ciertas palabras que están reservadas en unos compiladores sí y en otros no... La conclusión es que deberíamos usar nombres de variables que a nosotros nos resulten claros, y que tengan pinta de poder ser alguna orden de C.

Sigamos... Insisto en que en C las mayúsculas y minúsculas se consideran diferentes, de modo que si intentamos hacer

PrimerNumero = 0;
primernumero = 0;

o cualquier variación similar, el compilador protestará y nos dirá que no conoce esa variable, porque la habíamos declarado como

int primerNumero;

El número de letras que puede tener un "identificador" (el nombre de una variable, por ejemplo) depende del compilador que usemos. Es frecuente que permitan cualquier longitud, pero que realmente sólo se fijen en unas cuantas letras (por ejemplo, en las primeras 8 o en las primeras 32). Eso quiere decir que puede que algún compilador considerase como iguales las variables NumeroParaAnalizar1 y NumeroParaAnalizar2, porque tienen las primeras 18 letras iguales. El C estándar (ANSI C) permite cualquier longitud, pero sólo considera las primeras 31.

Por cierto, como las tres variables van a guardar números enteros, podemos declararlas a la vez, separadas por comas:

int primerNumero;
int segundoNumero;
int suma;

es lo mismo que

int primerNumero, segundoNumero, suma;

o que

int primerNumero,
segundoNumero,
suma;

Pero aquí hay más cosas "raras". Porque ahora en printf aparece ese "%d"? Habíamos hablado de printf como si escribiera en pantalla lo que nosotros le indicamos entre comillas. Esto no es del todo cierto:

Eso que le hemos indicado entre comillas es realmente un código de FORMATO. Dentro de ese código de formato podemos tener caracteres especiales, con los que le indicamos dónde y cómo queremos que aparezca un número. Esto lo veremos con detalle un poco más adelante, pero de momento anticipo que cuando el mensaje aparezca en pantalla, ese "%d" se sustituirá por un número entero. Qué número? El que le indicamos a continuación, separado por una coma (en este caso, "suma").
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Dom Oct 19, 2008 5:52 pm

CURSO DE C. TEMA 2.2 (de Cool.


En C es posible dar un valor a las variables a la vez que se las declara (algo parecido a lo que se puede hacer Turbo Pascal empleando "constantes con tipo"). Así, el programa anterior quedaría:

/*-------------------------*/
/* Ejemplo en C nº 3: */
/* EJ03.C */
/* */
/* Inicialización de */
/* variables */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int primerNumero = 234; /* Nuestras variables */
int segundoNumero = 567;
int suma;

main()
{
suma = primerNumero + segundoNumero;

printf("Su suma es %d", suma);
}

/*-------------------------*/

Al igual que en el caso anterior, como las tres variables son del mismo tipo, podemos declararlas a la vez haciendo:

int primerNumero=234, segundoNumero=567, suma;

¿Y cómo escribimos más de un valor a la vez? Pues vamos a verlo con otro ejemplo...
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Dom Oct 19, 2008 5:52 pm

CURSO DE C. TEMA 2.3 (de Cool.

Vamos a ver cómo imprimir más de un valor, también ampliando el ejemplo anterior:

/*-------------------------*/
/* Ejemplo en C nº 4: */
/* EJ04.C */
/* */
/* Escribir más de una */
/* variable */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int primerNumero = 234; /* Nuestras variables */
int segundoNumero = 567;
int suma;

main()
{
suma = primerNumero + segundoNumero;

printf("El primer número es %d, el segundo %d y su suma %d.",
primerNumero, segundoNumero, suma);
}

/*-------------------------*/

Un único comentario a este programa: hemos dicho que el C es un lenguaje de formato libre. Por eso, no hay ningún problema en dividir en dos la línea de la orden "printf", como hemos hecho, con la intención de que se vea la orden entera en una pantalla "normal". Lo de que la segunda línea del "printf" comience un poco más a la derecha es simplemente buscando mayor legibilidad: para que se vea que es continuación de la línea anterior, en vez de ser una orden nueva.

Sigamos. Hasta ahora hemos estado viendo cómo escribir variables, pero si queremos que realmente sean variables (que sus valores puedan variar), es lógico pensar que no tendríamos que ser nosotros quienes les damos su valor, sino los usuarios de nuestros programas. Entonces, debe haber alguna forma de que el usuario introduzca datos. Vamos a verlo...
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Dom Oct 19, 2008 5:52 pm

CURSO DE C. TEMA 2.4 (de Cool.


Veamos cómo dejar que el usuario sea quien introduzca los datos:

/*-------------------------*/
/* Ejemplo en C nº 5: */
/* EJ05.C */
/* */
/* Leer valores para */
/* variables */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int primerNumero, segundoNumero, suma; /* Nuestras variables */

main()
{
printf("Introduce el primer número ");
scanf("%d", &primerNumero);
printf("Introduce el segundo número ");
scanf("%d", &segundoNumero);
suma = primerNumero + segundoNumero;
printf("Su suma es %d", suma);
}

/*-------------------------*/

Por si alguien no cae, la instrucción para que el usuario pueda dar un valor a una variable es "scanf".

Una vez que hemos visto que era ese %d de "printf", ya intuimos que en este caso servirá para indicar que lo que vamos a leer es un número entero.

Pero ¿qué es ese & que aparece antes de cada variable? Es porque lo que le estamos indicando a "scanf" es la DIRECCION en la que se debe guardar los datos. En nuestro caso, será la dirección de memoria que habíamos reservado para la variable "primerNumero" y posteriormente la reservada para "segundoNumero".

Bueno, ahora que ya vamos viendo cómo podemos ver en pantalla el contenido de una variable, cómo podemos fijarlo, y como podemos dejar que sea el usuario quien le dé un valor, creo que ya va siendo hora de ver qué tipos de variables más habituales que podemos usar...

· int. Ya comentado: es un número entero (en el DOS, desde -32768 hasta 32767; en otros sistemas operativos, como UNIX, pueden ser valores distintos -hasta unos dos mil millones-).

· char. Un carácter (una letra, una cifra, un signo de puntuación, etc.). Se indica entre comillas simples: letra = 'W'
· float. Un numero real (con decimales).
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Dom Oct 19, 2008 5:52 pm

CURSO DE C. TEMA 2.5 (de Cool.



Hemos visto son los tipos más sencillos. También podemos crear arrays y registros:

· Un array es un conjunto de elementos, todos los cuales son del mismo tipo. Es la estructura que emplearemos normalmente para crear vectores y matrices. Por ejemplo, para definir un grupo de 5 números enteros y hallar su suma podemos hacer:

/*-------------------------*/
/* Ejemplo en C nº 6: */
/* EJ06.C */
/* */
/* Primer ejemplo de */
/* arrays */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int numero[5]; /* Un array de 5 números enteros */
int suma; /* Un entero que será la suma */

main()
{
numero[0] = 200; /* Les damos valores */
numero[1] = 150;
numero[2] = 100;
numero[3] = -50;
numero[4] = 300;
suma = numero[0] + /* Y hallamos la suma */
numero[1] + numero[2] + numero[3] + numero[4];
printf("Su suma es %d", suma);
/* Nota: esta es la forma más ineficiente y engorrosa */

/* Ya lo iremos mejorando */
}

/*-------------------------*/

Una primera observación: hemos declarado un array de 5 elementos. Para numerarlos, se empieza en 0, luego tendremos desde "numero[0]" hasta "numero[4]", como se ve en el ejemplo.

Esto es muy mejorable. La primera mejora evidente (o casi) es no tener que dar los valores uno por uno. Podemos dar un valor a las variables, como hicimos en el ejemplo 3...
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Dom Oct 19, 2008 5:53 pm

CURSO DE C. TEMA 2.6 (de Cool.


Vamos a dar un valor inicial a un "array":

/*-------------------------*/
/* Ejemplo en C nº 7: */
/* EJ07.C */
/* */
/* Inicialización de */
/* arrays */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int numero[5] = /* Un array de 5 números enteros */
{200, 150, 100, -50, 300;
int suma; /* Un entero que será la suma */

main()
{
suma = numero[0] + /* Y hallamos la suma */
numero[1] + numero[2] + numero[3] + numero[4];
printf("Su suma es %d", suma);
/* Nota: esta forma es algo menos engorrosa, pero todavía no está */
/* bien hecho. Lo seguiremos mejorando */
}

/*-------------------------*/

Quien haya llegado hasta aquí y ya sepa algo de programación, imaginará que la siguiente mejora es no repetir los valores en

suma = numero[0] + ...

La forma de hacerlo será empleando algún tipo de estructura que nos permita repetir varios pasos sin tener que indicarlos uno a uno. Es el caso del bucle "for" en Pascal (o en Basic), que ya veremos cómo usar en C.

Podemos declarar arrays de dos o más dimensiones, para guardar matrices, por ejemplo. A quien no haya estudiado nada de matrices, esto le puede sonar a chino, así que pongamos un ejemplo: Queremos guardar datos sobre 100 personas, y para cada persona nos interesa almacenar 15 números, todos ellos reales. Haríamos:

float datos[100][15]

El dato número 10 de la persona 20 sería "datos[19][9]" (recordemos que se empieza a numerar en 0).

Aún nos queda algo por ver...
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Dom Oct 19, 2008 5:53 pm

CURSO DE C. TEMA 2.7 (de Cool.


Sigamos. El próximo paso es ver qué es eso de los registros.

· Un registro es una agrupación de datos, los cuales no necesariamente son del mismo tipo. Se definen con la palabra clave "struct", y su manejo (muy parecido a como se usan los "records" en Pascal) es: para acceder a cada uno de los datos que forman el registro, se debe indicar el nombre de la variable y el del dato (o campo) separados por un punto:

/*-------------------------*/
/* Ejemplo en C nº 8: */
/* EJ08.C */
/* */
/* Registros (struct) */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

struct {
char inicial;
int edad;
float nota;
persona;

main()
{
persona.inicial = 'J';
persona.edad = 20;
persona.nota = 7.5;
printf("La edad es %d", persona.edad);
}

/*-------------------------*/

Como es habitual en C, primero hemos indicado el tipo de la variable: (struct { ... ) y después el nombre de la variable (persona).

Hemos guardado varios datos de una persona. Se pueden almacenar los de varias personas si combinamos esto con los array que vimos anteriormente. Por ejemplo, si queremos guardar los datos de 100 alumnos podríamos hacer:

struct {
char inicial;
int edad;
float nota;
alumnos[100];
}

La inicial del primer alumno sería "alumnos[0].inicial", y la edad del último sería "alumnos[99].edad".

También hay otros tipos especiales de "struct", aunque de manejo más avanzado. Es el caso de uniones y campos de bits


Los tipos permiten modificadores: unsigned o signed, y long o short.

Por ejemplo, un char por defecto se considera que es un valor con signo, luego va desde -128 hasta +127. Si queremos que sea positivo, y entonces que vaya desde 0 hasta 255, deberíamos declararlo como "unsigned char".

De igual modo, un int va desde -32768 hasta 32767. Si queremos que sea positivo, y entonces vaya desde 0 hasta 65535, lo declararemos como "unsigned int".

Podemos ampliar el rango de valores de un entero usando "long": un "long int" irá desde -2147483648 hasta 2147483647. Por contraposición, un "short int" será un entero no largo ("normal").

También hay otros tipos de datos "menos habituales". Se trata de valores reales que permiten una mayor precisión y un mayor rango de valores que "float". Estos son "double" y "long double".

Los modificadores permitidos son:


Modificador Aplicable a

short int
long int, double
signed int, char
unsigned int, char

Pero quizá sea mejor recopilar todo esto en una tabla...
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Dom Oct 19, 2008 5:53 pm

CURSO DE C. TEMA 2.8 (de Cool.

Vamos a recopilar todo esto de los modificadores en una tabla. Los paréntesis indican que una cierta parte del nombre es el valor "por defecto" (el que se considera, mientras no se indique lo contrario). A la derecha indico el valor mínimo y el valor máximo que puede tomar una variable de ese tipo:


Nombre Bytes Min Max

(signed) char 1 -128 127
unsigned char 1 0 255

(signed) (short) int 2 -32768 32767
unsigned (short) (int) 2 0 65535
(signed) long (int) 4 -2147483648 2147483647

unsigned long (int) 4 0 4294967295

float 2 3.4E-38 3.4E+38
double 4 1.7E-308 1.7E+308
long double 5 3.4E-4932 1.1E+4932

Con los paréntesis me refiero a que "signed char" es lo mismo que "char", y que "long" es lo mismo que "long int" y que "signed long int", por ejemplo.

Nota: estos tamaños y rangos de valores son válidos en la mayoría de los compiladores bajo DOS (16 bits). Puede existir compiladores para otros sistemas operativos (incluso algún caso bajo DOS) en los que estos valores cambien. Por ejemplo, con GCC para Linux, el rango de los "int" coincide con el que en MsDos suele ser un "long int".

En cualquier caso, estos valores se pueden comprobar, porque tenemos definidas unas constantes como MAXINT o MAXLONG (en el fichero de cabecera "values.h"), que nos dicen hasta qué valor podemos llegar con cada tipo de número.

¿Y los Booleanos? Recordemos que en Pascal (y en otros lenguajes) contamos con un tipo especial de datos que puede valer "verdadero" o "falso". En C no es así, sino que se trabaja con enteros. Entonces, al comprobar una condición no obtendremos directamente "verdadero" o "falso", sino 0 (equivalente a FALSO) o un número distinto de cero (equivalente a VERDADERO; normalmente será 1).

¿Y las cadenas de texto? Aquí la cosa se complica un poco. No existe un tipo "string" como tal, sino que las cadenas de texto se consideran "arrays" de caracteres. Están formadas por una sucesión de caracteres terminada con un carácter nulo (0), y no serán tan fáciles de manejar como lo son en Pascal y otros lenguajes. Por ejemplo, no podremos hacer cosas como

Nombre := 'Don ' + Nombre;

Es decir, algo tan habitual como concatenar cadenas se va a complicar (para quien venga de Pascal o Basic). Tendremos que usar unas funciones específicas, pero eso lo veremos más adelante. Ahora vamos a ver un primer ejemplo del uso de cadenas de texto, en su forma más sencilla, pero que también es la menos habitual en la práctica.

/*-------------------------*/
/* Ejemplo en C nº 9: */
/* EJ09.C */
/* */
/* Introducción a las */
/* cadenas de texto */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

char texto1[80] = "Primer texto";
char texto2[80];

main()
{
printf("Introduzca un texto: ");
scanf("%s", &texto2);

printf("El primer texto es %s", texto1);
printf(" y Vd. ha tecleado %s", texto2);
}

/*-------------------------*/

Creo que el ejemplo se entiende por sí mismo, porque la única novedad con respecto a ejemplos anteriores es "%s" para indicar que lo que queremos leer o escribir es una cadena de texto.

Eso sí, varios comentarios:

· Hemos reservado 80 caracteres (realmente 79, porque recordemos que al guardarlo en memoria se le añade un carácter 0 para indicar el final de la cadena), así que si tecleamos más de 79 caracteres, nadie nos asegura lo que vaya a pasar: puede que nuestro programa intente guardar todo lo que hemos tecleado, sin pensar que, como no cabe, puede estar "machacando" otros datos o incluso instrucciones de nuestro programa.

· Segundo comentario: si la cadena contiene espacios, se lee sólo hasta el primer espacio. Esto se puede considerar una ventaja o un inconveniente, según el uso que se le quiera dar. En cualquier caso, en el próximo apartado veremos cómo evitarlo.

· Tercero: no hace falta el "&" de "&texto2" en "scanf", porque habíamos dicho que ese símbolo hacía referencia a la dirección en la que se nos había reservado la memoria para esa variable, cosa que no es necesaria en un array, porque es el propio nombre lo que está haciendo referencia a la dirección. A que parece un trabalenguas? No es tan complicado: para que se vea a qué me refiero, va un ejemplo, comparando una variable "normal" y un array:

int Dato = 5;

Dato vale 5;
&Dato nos da la dirección en que está guardado

char Texto[40] = "Una prueba";

Texto[0] vale 'U' (la primera letra).
Texto[1] vale 'n' (la segunda), y así sucesivamente.
Texto (sin corchetes) da la dirección en está guardado el array.

Por tanto, como "scanf" espera que le digamos la dirección en la que queremos guardar la cadena de texto (un array), podemos usar

scanf("%s", texto2);

· Cuarto (y último): Algo que igual alguien ha pasado por alto, así que lo quiero recalcar. Las cadenas de texto se encierran entre comillas dobles ("Hola") y las letras aisladas entre comillas simples ('H').
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Mar Oct 21, 2008 4:08 pm

CURSO DE C. TEMA 3. Pequeña recapitulación.

Bueno, parece que ya vamos sabiendo algo. Pero antes de avanzar, va siendo el momento de puntualizar y/o concretar algunas de las cosas que hemos ido viendo, para que esto tenga también algo de rigor...

Si asusta, pues no hay más que saltar al siguiente tema, y volver más adelante, cuando ya se tenga más base.


#include y .h

Es muy frecuente que un programa en C esté dividido en varios módulos, que se deben ensamblar en el momento de crear el programa ejecutable.

Entonces puede ocurrir que en "prog2.c" hayamos definido una función que necesita "prog1.c". Cuando "prog1" comienza a compilar descubre que no conoce una de las funciones que aparecen por ahí, y el compilador protesta.

Una forma de evitarlo es poniendo "la cabecera" de la función que falta, es decir, su nombre y sus parámetros (pero sin detallar los pasos que debe dar; de eso ya se encarga "prog2.c").

Así "prog1" sabe que esa función existe, que no es que hayamos tecleado algo mal, sino que "está ahí", y que ya le llegarán los detalles concretos más adelante, cuando termine de ensamblar todos los módulos.

A quien venga de Pascal, eso de "la cabecera" ya le sonará, porque es igual que lo que ponemos en la sección "interface" de las unidades que creemos nosotros mismos.

Pero además tenemos más casos que éstos, porque incluso si nuestro programa está formado por un sólo módulo, normalmente necesitaremos funciones como "printf", que, como hemos comentado, no forman parte del lenguaje base. Nos encontramos con el mismo problema: si no ponemos la cabecera, el compilador no sabrá que esa función "existe pero aún no se la hemos explicado", sino que supondrá que hemos escrito algo mal y protestará.

Así que, entre unas y otras, tendríamos que llenar nuestro programa con montones y montones de cabeceras. La forma habitual de evitarlo es juntar esas cabeceras en "ficheros de cabecera", que luego incluimos en nuestro programa.

Así, todas las funciones que están relacionadas con la entrada y salida estándar, y que se enlazan en el momento de crear el ejecutable, las tenemos declaradas en el fichero de cabecera "stdio.h". Por eso, cuando escribimos

#include <stdio.h>

el compilador coge el fichero "stdio.h", lee todas las cabeceras que contiene y las "inserta" en ese mismo punto de nuestro programa.

¿Y porque eso de #? Pues porque no es una orden del lenguaje C, sino una orden directa al compilador (una "directiva"). Cuando llega el momento de comprobar la sintaxis del lenguaje C ya no existe eso de "include", sino que en su lugar el compilador ya ha dejado todas las cabeceras que queríamos.

¿Y eso de < >? Pues podemos encontrar líneas como

#include <stdio.h>

y como

#include "misdatos.h"

El primer caso es un fichero de cabecera estándar del compilador. Lo indicamos entre < y > y así el compilador sabe que tiene que buscarlo en su directorio de "includes". El segundo caso es un fichero de cabecera que hemos creado nosotros, por lo que lo indicamos entre " y ", y así el compilador sabe que no debe buscarlo entre SUS directorios, sino en el mismo directorio en el que está nuestro programa.


Warnings y main()

Según el compilador que se use, puede que con los ejemplos anteriores haya aparecido un "warning" que diga algo como

Warning: function should return a value in function main

Es decir "aviso: la función debería devolver un valor, en la función MAIN".

Vayamos por partes:

· Eso de los WARNING son avisos del compilador, una forma de decirnos "Cuidado, que puede que esto no esté del todo bien"

· ¿Por qué avisa en este caso? Recordemos que ya comentamos en el primer tema que en C no hay funciones y procedimientos, sino sólo funciones. Por tanto, siempre deberán devolver un valor, aunque puede que este sea de un tipo especial "nulo". Y en cambio, en nuestros programas se veía por ahí ningún valor devuelto en "main"...

· ¿Formas de hacer que esté del todo correcto, para que el compilador no proteste? Hay dos: una (menos correcta) es decir que "main" es de ese tipo "nulo", con lo cual no hay que devolver ningún valor, y otra (más correcta) es obligar a que devuelva un valor, que normalmente será 0 (para indicar que todo ha funcionado correctamente; otro valor indicaría algún tipo de error). Este valor es el "errorlevel" que se devuelve al DOS cuando termina la ejecución del programa. Pues vamos con la forma "buena":

/*-------------------------*/
/* Ejemplo en C nº 10: */
/* EJ10.C */
/* */
/* "main" como int */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

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

/*-------------------------*/

Con eso de "int main()" decimos que la función "main" va a devolver un valor entero. Es lo que se considera por defecto (si no ponemos "int", el compilador considera de todas formas que lo es).

Con eso de "return 0" devolvemos el valor 0 a la salida de "main", que indica que todo ha ido correctamente. Como la función ya devuelve un valor, el Warning desaparece.
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Jue Oct 23, 2008 7:35 pm

CURSO DE C. TEMA 3.2 (de 2).


La otra forma (la "menos buena") de que desaparezca el "Warning" es

/*-------------------------*/
/* Ejemplo en C n 11: */
/* EJ11.C */
/* */
/* "main" como void */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

void main()
{
printf("Hola");
}

/*-------------------------*/

Eso de "void" es el tipo nulo al que nos referíamos. Así indicamos que la función no va a devolver valores.

Esta es la opción "menos buena" porque puede que a algún compilador no le guste eso de que "main" no devuelva un valor entero, aunque no es lo habitual: les suele bastar con que exista la función "main", sea del tipo que sea.
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Jue Oct 23, 2008 7:35 pm

CURSO DE C. TEMA 4. Entrada/Salida básica

Hemos visto por encima cómo mostrar datos en pantalla y cómo aceptar la introducción de datos por parte del usuario, mediante "printf" y "scanf", respectivamente. Veamos ahora su manejo y algunas de sus posibilidades con más detalle, junto con otras órdenes alternativas:

El formato de printf es

printf( formato, lista de variables);

Dentro del apartado de "formato" habíamos comentado que "%d" indicaba que se iba a escribir un número entero, y que "%s" indicaba una cadena de texto. Vamos a resumir en una tabla las demás posibilidades, que no habíamos tratado todavía:


Código Formato

%d Número entero con signo, en notación decimal

%i Número entero con signo, en notación decimal
%u Número entero sin signo, en notación decimal
%o Número entero sin signo, en notación octal (base Cool
%x Número entero sin signo, en hexadecimal (base 16)
%X Número entero sin signo, en hexadecimal, mayúsculas
%f Número real (coma flotante, con decimales)
%e Número real en notación científica
%g Usa el más corto entre %e y %f
%c Un único carácter
%s Cadena de caracteres

%% Signo de tanto por ciento: %
%p Puntero (dirección de memoria)
%n Se debe indicar la dirección de una variable entera
(como en scanf), y en ella quedará guardado el
número de caracteres impresos hasta ese momento

Además, las órdenes de formato pueden tener modificadores, que se sitúan entre el % y la letra identificativa del código.
· Si el modificador es un número, especifica la anchura mínima en la que se escribe ese argumento.

· Si ese número empieza por 0, los espacios sobrantes (si los hay) de la anchura mínima se rellenan con 0.
· Si ese número tiene decimales, indica el número de dígitos enteros y decimales si los que se va a escribir es un número, o la anchura mínima y máxima si se trata de una cadena de caracteres.
· Si el número es negativo, la salida se justificará a la izquierda (en caso contrario, es a la derecha -por defecto-).
· Hay otros dos posibles modificadores: la letra l, que indica que se va a escribir un long, y la letra h, que indica que se trata de un short.

Todo esto es para printf, pero coincide prácticamente en el caso de scanf.

Antes de seguir, vamos a ver un ejemplo con los casos más habituales...
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Jue Oct 23, 2008 7:36 pm

CURSO DE C. TEMA 4.2 (de 4).


Este es un ejemplo de los formatos más habituales:

/*-------------------------*/
/* Ejemplo en C nº 12: */
/* EJ12.C */
/* */
/* Formatos con "printf" */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int entero = 1234;
int enteroNeg = -1234;
float real = 234.567;
char letra = 'E';
char mensaje[20] = "Un texto";
int contador;

main()
{
printf("El número entero vale %d en notación decimal,\n", entero);
printf(" y %o en notación octal,\n", entero);
printf(" y %x en notación hexadecimal,\n", entero);
printf(" y %X en notación hexadecimal en mayúsculas,\n", entero);
printf(" y %ld si le hacemos que crea que es entero largo,\n", entero);

printf(" y %10d si obligamos a una cierta anchura,\n", entero);
printf(" y %-10d si ajustamos a la izquierda.\n", entero);
printf("El entero negativo vale %d\n", enteroNeg);
printf(" y podemos hacer que crea que es positivo: %u (incorrecto).\n",
enteroNeg);
printf("El número real vale %f en notación normal\n", real);
printf(" y %3.2f si limitamos a dos decimales,\n", real);
printf(" y %e en notación científica (exponencial).\n", real);
printf("La letra es %c y el texto %s.\n", letra, mensaje);
printf(" Podemos poner \"tanto por ciento\": 50%%.\n");
printf("Finalmente, podemos escribir direcciones. de memoria: %p.\n",
&letra);
printf(" y contar lo escrito hasta aquí%n", &contador);

printf(", que ha sido: %d letras.\n", contador);
}

/*-------------------------*/

Aparecen cosas nuevas, como eso de "\n", hace que avancemos una línea en la pantalla, y que veremos con más detalle en un instante, pero antes vamos a analizar el resultado de este programa con Turbo C++:

- - - - - - - - - - - - - - - - - - - - - - - - - - -

El número entero vale 1234 en notación decimal,
y 2322 en notación octal,
y 4d2 en notación hexadecimal,
y 4D2 en notación hexadecimal en mayúsculas,
y 1234 si le hacemos que crea que es entero largo,
y 1234 si obligamos a una cierta anchura,
y 1234 si ajustamos a la izquierda.
El entero negativo vale -1234
y podemos hacer que crea que es positivo: 64302 (incorrecto).
El número real vale 234.567001 en notación normal
y 234.57 si limitamos a dos decimales,
y 2.345670e+02 en notación científica (exponencial).
La letra es E y el texto Un texto.
Podemos poner "tanto por ciento": 50%.
Finalmente, podemos escribir direcciones. de memoria: 00B0.
y contar lo escrito hasta aquí, que ha sido: 32 letras.

- - - - - - - - - - - - - - - - - - - - - - - - - - -

Creo que queda todo bastante claro (puede volver al apartado anterior para consultar los distintos formatos si no es así), pero aun así hay una cosa desconcertante: Por qué el número real aparece como 234.567001, si nosotros lo hemos definido como 234.567? Porque los números reales se almacenan con una cierta pérdida de precisión. Si esta pérdida es demasiado grande para nosotros, deberemos usar otro tipo, como double.

Lo de que el número negativo quede mal al intentar escribirlo como positivo, lo comento de pasada para quien sepa ya algo de aritmética binaria: el primer bit a uno en un número con signo indica que es un número negativo, mientras que en uno positivo es el más significativo. Por eso, tanto el número -1234 como el 64302 se traducen en la misma secuencia de ceros y unos, que la sentencia "printf" interpreta de una forma u otra según le digamos que el número el positivo o negativo.

Y aun hay más: si lo compilamos y lo ejecutamos con Symantec C++, vemos que hay dos diferencias:

-> Finalmente, podemos escribir direcciones. de memoria: 0068.

Esto no es problema, porque la dirección de memoria en la que el compilador nos reserve una variable no nos importa; nos basta con saber que realmente contamos con esa memoria para nuestros datos.

-> y 182453458 si le hacemos que crea que es entero largo,

Esto ya asusta más. ¿Por qué el 1234 se ha convertido en esa cosa tan rara? Pues porque un entero largo ocupa el doble que un entero normal, así que es muy posible que si hacemos cosas como éstas, esté intentando leer 4 bytes donde nosotros sólo hemos definido 2, tomará datos que hayamos reservado para otras variables, y el resultado puede ser erróneo.

Para evitar esto, se puede hacer una "conversión de tipos" (en inglés "typecast"), para que el valor que vayamos a imprimir sea realmente un entero largo:

printf(" y %ld si le hacemos que crea que es entero largo,\n",
(long) entero);

Así, antes de imprimir coge nuestro valor, lo convierte realmente en un entero largo (el dato leído, porque no modifica el original) y lo muestra correctamente. Así nos aseguramos de que funcionará en cualquier compilador.

Finalmente, si lo compilamos con GCC (bajo Linux) los resultados también son "casi iguales", y esta vez las diferencias son:

-> Finalmente, podemos escribir direcciones. de memoria: 0x2010.

Esto, como antes, no debe preocuparnos.

-> El entero negativo vale -1234
-> y podemos hacer que crea que es positivo: 4294966062 (incorrecto).

Este valor es distinto del visto anteriormente simplemente porque para GCC bajo Linux, un entero ocupa 4 bytes en vez de 2. Por tanto, -1234 y 4294966062 dan lugar a la misma secuencia de ceros y unos, pero esta vez con 32 bits en vez de 16.

Este es el mismo resultado que se obtiene con Djgpp 2.01.


En el caso del compilador PCC 2.1c, obtenemos "casi" lo mismo, pero no idéntico, porque no permite algunos de los códigos de formato, como "%p" y "%n":

- - - - - - - - - - - - - - - - - - - - - - - - - - -

El número entero vale 1234 en notación decimal,
y 2322 en notación octal,
y 4D2 en notación hexadecimal,
y FFEC04D2 en notación hexadecimal en mayúsculas,
y -1309486 si le hacemos que crea que es entero largo,
y 1234 si obligamos a una cierta anchura,
y 1234 si ajustamos a la izquierda.
El entero negativo vale -1234
y podemos hacer que crea que es positivo: 64302 (incorrecto).
El número real vale 234.567001 en notación normal
y 234.57 si limitamos a dos decimales,
y 2.345670E2 en notación científica (exponencial).
La letra es E y el texto Un texto.
Podemos poner "tanto por ciento": 50%.
Finalmente, podemos escribir direcciones. de memoria: p.
y contar lo escrito hasta aquín, que ha sido: 0 letras.
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Jue Oct 23, 2008 7:36 pm

CURSO DE C. TEMA 4.3 (de 4).


Sigamos. Vamos a ver ahora qué era eso de "\n". Las letras que escribamos después de una barra invertida (en inglés, "backslash") tendrán un significado especial. Se trata simplemente de códigos de control (llamados también "secuencias de escape") que podemos meter entre medias del texto. En este caso, ese es el carácter de avance de línea (en inglés "new line"), que hace que se siga escribiendo al comienzo de la línea siguiente. Veamos en una tablita cuáles podemos usar:

Código Significado

\n nueva línea (new line / line feed)
\r retorno de carro (carriage return)

\b retroceso (backspace)
\f salto de página (form feed)
\t tabulación horizontal
\v tabulación vertical
\" comillas dobles (")
\' apóstrofe o comillas simples (')
\\ barra invertida (\)
\a alerta (un pitido)
\0 carácter nulo
\ddd constante octal (máximo tres dígitos)
\xddd constante hexadecimal (ídem)


Estos códigos equivalen a ciertos caracteres de control del código ASCII. Por ejemplo, el carácter de salto de página es el 12, luego sería equivalente hacer:

char FF = 12; /* Asignación normal, sabiendo el código */
char FF = '\f'; /* Como secuencia de escape */
char FF = '\xC'; /* Como constante hexadecimal */
char FF = '\140; /* Como constante octal */
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Jue Oct 23, 2008 7:36 pm

CURSO DE C. TEMA 4.4 (de 4).


Para leer datos del teclado, hemos visto cómo usar "scanf". Una vez vista la base y conocidos los códigos de formato, no tiene mayor dificultad. Por ejemplo, para leer un número real, haríamos:

scanf("%f", &real);

Podemos leer más de un dato seguido, que el usuario deje separados por espacios, usando construcciones como

scanf("%f %f", &real1, &real2);

pero su uso es peligroso. Personalmente, yo prefiero leerlo como una cadena de texto y analizarlo yo mismo, para evitar errores. Y cómo leemos cadenas de texto, si habíamos visto que "scanf" paraba en cuanto encontraba un espacio? Vamos a verlo...

Cuando queremos trabajar con cadenas de texto, tenemos otras posibilidades: con "puts" podemos escribir un texto y con "gets" leer lo que se teclee (esta vez no se para en cuanto lea un espacio en blanco).

Va el ejemplo de turno:

/*-------------------------*/
/* Ejemplo en C nº 13: */
/* EJ13.C */
/* */
/* "gets" y "puts" */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

char texto[80];

main()
{
puts("Teclee una frase.");
gets(texto);
puts("Ha escrito: ");
puts(texto);
}

/*-------------------------*/

Al ejecutar este programa, vemos que "puts" ya avanza automáticamente de línea tras escribir el texto, sin necesidad de que pongamos un '\n' al final.

En "stdio.h" tenemos muuuuchas más funciones, pero vamos sólo a comentar dos más: "getchar()" lee un carácter y "putchar()" escribe un carácter.

En la práctica, es más habitual usar otras funciones como "getch()", pero estas dependen (en teoría) del compilador que se use, así que las veremos cuando tratemos la pantalla en modo texto.
Volver arriba Ir abajo
Ver perfil de usuario
seon one
Moderador
Moderador


Mensajes : 9
Fecha de inscripción : 03/10/2008
Edad : 22
Localización : ibizaaaa

MensajeTema: Re: Curso programación en C   Jue Oct 23, 2008 9:30 pm

Esta todo muy bien explicado
Volver arriba Ir abajo
Ver perfil de usuario http://www.metroflog.com/seonyonc
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Vie Oct 24, 2008 11:35 pm

CURSO DE C. TEMA 5. Operaciones matemáticas

Al igual que en Pascal, Basic y otros lenguajes, contamos con una serie de operadores para realizar sumas, restas, multiplicaciones y otras operaciones no tan habituales. Vamos a empezar por las cuatro elementales:


Operador Operación

+ Suma
- Resta, negación
* Multiplicación
/ División
% Resto de la div.

¿Qué ocurre en casos como el de 10/3? Si 10 y 3 son números enteros, ¿qué ocurre con su división? El resultado sería 3, la parte entera de la división. Será 3.3333 cuando ambos números sean reales.


/*-------------------------*/
/* Ejemplo en C nº 14: */
/* EJ14.C */

/* */
/* Operaciones con */
/* números enteros */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int e1 = 10;
int e2 = 4;
float r1 = 10.0;
float r2 = 4.0;

main()
{
printf("La suma de los enteros es: %d\n", e1+e2);
printf(" Su producto: %d\n", e1*e2);
printf(" Su resta: %d\n", e1-e2);
printf(" Su división: %d\n", e1/e2);
printf(" El resto de la división: %d\n", e1%e2);
printf("La suma de los reales es: %f\n", r1+r2);
printf(" Su producto: %f\n", r1*r2);
printf(" Su resta: %f\n", r1-r2);
printf(" Su división: %f\n", r1/r2);
printf("Un real entre un entero, como real: %f\n", r1/e2);
printf(" Lo mismo como entero: %d (erróneo)\n", r1/e2);

printf(" Un entero entre un real, como real: %f\n", e1/r2);
}

/*-------------------------*/

Estos operadores son "binarios". Se llaman así porque trabajan con dos datos: sumamos dos números, restamos dos números, multiplicamos dos números, etc. Por otro lado, tenemos operadores "unarios", que sólo afectan a un dato. El ejemplo más claro es el de la negación: -a pero veremos más adelante otros (++, --, &, ...)

Cuidado quien venga de Pascal, porque en C el operador + (suma) NO se puede utilizar también para concatenar cadenas de texto. Tendremos que utilizar funciones específicas (en este caso "strcat"). Tampoco podemos asignar valores directamente, haciendo cosas como "texto2 = texto1", sino que deberemos usar otra función ("strcpy"). Todo esto lo veremos más adelante, en un tema dedicado sólo a las cadenas de texto.

En Turbo Pascal (no en cualquier versión de Pascal), tenemos también formas abreviadas de incrementar una variable:

inc(a); en vez de a := a+1;

Algo parecido existe en C, aunque con otra notación:

a++; es lo mismo que a = a+1;
a--; es lo mismo que a = a-1;

Pero esto tiene más misterio todavía del que puede parecer en un primer vistazo: podemos distinguir entre "preincremento" y "postincremento". En C es posible hacer asignaciones como

b = a++;

Así, si "a" valía 2, lo que esta instrucción hace es dar a "b" el valor de "a" y aumentar el valor de "a". Por tanto, al final tenemos que b=2 y a=3 (postincremento: se incrementa "a" tras asignar su valor).

En cambio, si escribimos

b = ++a;

y "a" valía 2, primero aumentamos "a" y luego los asignamos a "b" (preincremento), de modo que a=3 y b=3.

Por supuesto, también tenemos postdecremento (a--) y predecremento (--a).

Y ya que estamos embalados con las asignaciones, hay que comentar que en C es posible hacer asignaciones múltiples:

a = b = c = 1;

Pero aún hay más. Tenemos incluso formas reducidas de escribir cosas como "a = a+5". Allá van

a += b ; es lo mismo que a = a+b;
a -= b ; es lo mismo que a = a-b;

a *= b ; es lo mismo que a = a*b;
a /= b ; es lo mismo que a = a/b;
a %= b ; es lo mismo que a = a%b;
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Vie Oct 24, 2008 11:36 pm

CURSO DE C. TEMA 5.2 (de 3). Operadores lógicos

En la próxima lección veremos cómo hacer comparaciones del estilo de "si A es mayor que B y B es mayor que C". Así que vamos a anticipar cuales son los operadores de comparación en C.


Operador Operación

== Igual a
!= No igual a (distinto de)
< Menor que
> Mayor que
<= Menor o igual que
>= Mayor o igual que

Cuidado con el operador de igualdad: el formato será if (a==b) ... Si no nos damos cuenta y escribimos if (a=b) estamos asignando a "a" el valor de "b" (lo veremos con más detalle en la próxima lección).

Afortunadamente, la mayoría de los compiladores nos avisan con un mensaje parecido a "Possibly incorrect assignment" (que podríamos traducir por "posiblemente esta asignación es incorrecta") o "Possibly unintended assignment" (algo así como "es posible que no se pretendiese hacer esta asignación").

Estas condiciones se puede encadenar con "y", "o", etc., que se indican de la siguiente forma (también lo aplicaremos en la próxima lección)


Operador Significado

&& Y
|| O
! No

Así, una orden que sea mezcla de C y español (porque todavía no sabemos bien cómo comprobar condiciones) y que compruebe si una variable "x" vale 2 y si otra variable "z" no es mayor de 5, sería

Si (x==2) && !(z>5) entonces ...
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Vie Oct 24, 2008 11:36 pm

CURSO DE C. TEMA 5.3 (de 3). Operadores entre bits

Al igual que en Pascal, podemos hacer operaciones entre bits de dos números (producto, suma, suma exclusiva, etc.), que se indican:


Operador Operación

~ Complemento (cambiar 0 por 1 y viceversa)
& Producto lógico (and)
| Suma lógica (or)
^ Suma exclusiva (xor)
<< Desplazamiento hacia la izquierda
>> Desplazamiento a la derecha

Explicar para qué sirven estos operadores implica conocer qué es eso de los bits, cómo se pasa un número decimal a binario, etc. Supondré que se tienen las nociones básicas, y pondré un ejemplo, cuyo resultado comentaré después:

/*-------------------------*/
/* Ejemplo en C nº 14b: */
/* EJ14B.C */
/* */
/* Operaciones de bits */
/* en números enteros */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int a = 67;
int b = 33;

main()
{
printf("La variable a vale %d\n", a);
printf("y b vale %d\n", b);
printf(" El complemento de a es: %d\n", ~a);
printf(" El producto lógico de a y b es: %d\n", a&b);
printf(" Su suma lógica es: %d\n", a|b);
printf(" Su suma lógica exclusiva es: %d\n", a^b);
printf(" Desplacemos a a la izquierda: %d\n", a << 1);
printf(" Desplacemos a a la derecha: %d\n", a >> 1);
}

/*-------------------------*/


Veamos qué ha ocurrido. La respuesta que nos da Turbo C++ 1.01 (y que coincide con Symantec C++ 6.0) es la siguiente:

- - - - - - - - - - - - - - - - - - - - - - - - - - -
La variable a vale 67
y b vale 33
El complemento de a es: -68
El producto lógico de a y b es: 1
Su suma lógica es: 99
Su suma lógica exclusiva es: 98
Desplacemos a a la izquierda: 134
Desplacemos a a la derecha: 33
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Para entender esto, deberemos convertir al sistema binario esos dos números:

67 = 0100 0011
33 = 0010 0001

- En primer lugar complementamos "a", cambiando los ceros por unos:

1011 1100 = -68

- Después hacemos el producto lógico de A y B, multiplicando cada bit,

de modo que 1*1 = 1, 1*0 = 0, 0*0 = 0

0000 0001 = 1

- Después hacemos su suma lógica, sumando cada bit, de modo que
1+1 = 1, 1+0 = 1, 0+0 = 0

0110 0011 = 99

- La suma lógica exclusiva devuelve un 1 cuando los dos bits son distintos:
1^1 = 0, 1^0 = 1, 0^0 = 0

0110 0010 = 98

- Desplazar los bits una posición a la izquierda es como multiplicar por dos:

1000 0110 = 134

- Desplazar los bits una posición a la derecha es como dividir entre dos:

0010 0001 = 33

¿Y qué utilidades puede tener todo esto? Posiblemente, más de las que parece a primera vista. Por ejemplo: desplazar a la izquierda es una forma muy rápida de multiplicar por potencias de dos; desplazar a la derecha es dividir por potencias de dos; la suma lógica exclusiva (xor) es un método rápido y sencillo de cifrar mensajes; el producto lógico nos permite obligar a que ciertos bits sean 0; la suma lógica, por el contrario, puede servir para obligar a que ciertos bits sean 1...

Un último comentario: igual que hacíamos operaciones abreviadas como

x += 2;

también podremos hacer cosas como

x <<= 2;
x &= 2;
x |= 2;
...

Pasemos ya al tema siguiente, para ver cómo se comprueban condiciones...
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Sáb Oct 25, 2008 9:03 pm

CURSO DE C. TEMA 6. Condiciones.

Vamos a ver cómo podemos evaluar condiciones. Supongo que está memorizado del tema anterior cómo se expresa "mayor o igual", "distinto de", y todas esas cosas.

La primera construcción sería el "si ... entonces ..." (if..then en Pascal y otros lenguajes). El formato en C es

if (condición) sentencia;

Vamos a verlo con un ejemplo:

/*-------------------------*/
/* Ejemplo en C nº 15: */
/* EJ15.C */
/* */
/* "if" elemental */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int numero;

main()
{
printf("Escriba un número: ");
scanf("%d", &numero);
if (numero>0) printf("El número es positivo.\n");
}

/*-------------------------*/

Todo claro, verdad? Pero (como suele ocurrir en C) esto tiene más miga de la que parece: recordemos que en C no existen los números booleanos, luego la condición no puede valer "verdadero" o "falso". Dijimos que "falso" iba a corresponder a un 0, y "verdadero" a un número distinto de cero (normalmente uno).

Por tanto, si escribimos el número 12 y le pedimos que escriba el valor de la comparación (numero>0), un compilador de Pascal escribiría TRUE, mientras que uno de C escribiría 1.
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Sáb Oct 25, 2008 9:03 pm

CURSO DE C. TEMA 6.3 (de 9).



La "sentencia" que se ejecuta si se cumple la condición puede ser una sentencia simple o una compuesta. Las compuestas se forman agrupando varias simples entre un llaves ( { y ):

/*-------------------------*/
/* Ejemplo en C nº 17: */
/* EJ17.C */
/* */
/* "if" y sentencias */
/* compuestas */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int numero;

main()
{
printf("Escriba un número: ");
scanf("%d", &numero);
if (numero<0)
{
printf("El número es ");
printf("negativo.\n");
}
}

/*-------------------------*/

En este caso, si el número es negativo, se hacen dos cosas: escribir un un texto y luego... escribir otro! Claramente, esos dos "printf" podrían ser uno solo, pero es que entonces me quedaría sin ejemplo.
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Sáb Oct 25, 2008 9:03 pm

CURSO DE C. TEMA 6.4 (de 9).



Sigamos... También podemos indicar lo que queremos que se haga si no se cumple la condición. Para ello tenemos la construcción "if (condición) sentencia1; else sentencia2;":

/*-------------------------*/
/* Ejemplo en C nº 18: */
/* EJ18.C */
/* */
/* "if" y "else" */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int numero;

main()
{
printf("Escriba un número: ");
scanf("%d", &numero);
if (numero<0)
printf("El número es negativo.\n");
else
printf("El número es positivo o cero.\n");
}

/*-------------------------*/

De nuevo, aquí debe llevar cuidado quien venga de Pascal, porque en C sí se debe poner un punto y coma antes de "else".
Volver arriba Ir abajo
Ver perfil de usuario
duirk
Co-Administrador
Co-Administrador


Mensajes : 88
Fecha de inscripción : 28/09/2008

MensajeTema: Re: Curso programación en C   Sáb Oct 25, 2008 9:04 pm

CURSO DE C. TEMA 6.5 (de 9).

Las sentencias "if (condición) s1; else s2;" se pueden encadenar:

/*-------------------------*/
/* Ejemplo en C nº 19: */
/* EJ19.C */
/* */
/* "if..else" encadenados */
/* */
/* Comprobado con: */
/* - Turbo C++ 1.01 */
/* - Djgpp 2.01 */
/* - Symantec C++ 6.0 */
/* - GCC 2.6.3 */
/* - PCC 2.1c */
/*-------------------------*/

#include <stdio.h>

int numero;

main()
{
printf("Escriba un número: ");
scanf("%d", &numero);
if (numero < 0)
printf("El número es negativo.\n");
else if (numero == 0)
printf("El número es cero.\n");
else
printf("El número es positivo.\n");
}

/*-------------------------*/

Atención en el ejemplo anterior al operador de comparación == para ver si dos valores son iguales. Insisto en que "if (numero = 0)" daría a número el valor 0. Ahora que sabemos más, nos damos cuenta de que además esto haría que tomase la condición como falsa. Para que se vea mejor, no hay más que teclear 0 como entrada a este programa:
Volver arriba Ir abajo
Ver perfil de usuario
Contenido patrocinado




MensajeTema: Re: Curso programación en C   Hoy a las 3:01 pm

Volver arriba Ir abajo
 
Curso programación en C
Ver el tema anterior Ver el tema siguiente Volver arriba 
Página 1 de 3.Ir a la página : 1, 2, 3  Siguiente
 Temas similares
-
» Como poner iconos de resyelto, en curso, etc.
» Resuelto, En curso, etc.
» imagen que siga el curso y que diga registrarse
» Manual Android
» Abuso en curso porque no quieren recibir correos... ¿como lo elimino?

Permisos de este foro:No puedes responder a temas en este foro.
-^Blue Hacking^- :: Hacktivismo :: Programación En General-
Cambiar a: