Introducción

EL lenguaje C es el resultado de un proceso de desarrollo que inició con un lenguaje denominado BCPL. Este influenció a otro llamado B (inventado por Ken Thompson). En los años 70; este lenguaje llevó a la aparición del C. Con la popularidad de las micro computadoras muchas compañías comenzaron a implementar su propio C por lo cual surgieron discrepancias entre si. Por esta razón ANSI (American National Standars Institute, por sus siglas en inglés), estableció un comité en 1983 para crear una definición no ambigua del lenguaje C e independiente de la máquina que pudiera utilizarse en todos los tipos de C. Algunos de las C existentes son: Quick C , C++ , Turbo C, Turbo C ++ , Borland C Borland C++, Microsoft C

 

C es un lenguaje de programación de nivel medio ya que combina los elementos del lenguaje de alto nivel con la funcionalidad del ensamblador. Su característica principal es ser portátil, es decir, es posible adaptar los programas escritos para un tipo de computadora en otra. Otra de sus características principales es el ser estructurado, es decir, el programa se divide en módulos (funciones) independientes entre sí.

 

El lenguaje C inicialmente fue creado para la programación de: Sistemas operativos, Intérpretes, Editores, Ensambladores, Compiladores, Administradores de bases de datos. Actualmente, debido a sus características, puede ser utilizado para todo tipo de programas.

 

ELEMENTOS GENERALES DE UN PROGRAMA EN C

Aunque cada uno de los programas son distintos, todos tienen características comunes. Los elementos de un programa en C son los siguientes:

Comentarios

Inclusión de archivos

main()

{

variables locales

flujo de sentencias

}

Definición de funciones creadas por el programador utilizadas en main()

 

Comentarios: Se identifican porque van entre diagonales y asterisco. Nos sirve para escribir información del programa pero que no forme parte de él. Por ejemplo especificar que hace el programa, quien lo elaboró, en que fecha, que versión es, etc.

 

Inclusión de archivos: Consiste en mandar llama-      r a la o las bibliotecas donde se encuentran definidas las funciones de C (instrucciones) que estamos utilizando en el programa. En realidad, la inclusión de archivos no forma parte de la estructura propia de un programa sino que pertenece al desarrollo integrado de C. Se incluye aquí para que no se olvide que debe mandar llamar a los archivos donde se encuentran definidas las funciones estándar que va a utilizar.

 

main(): En C todo esta constituido a base de funciones. El programa principal no es la excepción. main() indica el comienzo de la función principal del programa la cual se delimita con llaves.

 

Variables locales: Antes de realizar alguna operación en el programa, se deben declarar la(s) variable(s) que se utilizarán en el programa.

 

Flujo de sentencias: Es la declaración de todas las instrucciones que conforman el programa.

 

Definición de funciones creadas por el programador utilizadas en main(): Finalmente, se procede a definir el contenido de las funciones utilizadas dentro de main(). Estas contienen los mismos elementos que la función principal.

 

Después de cada asignación o función es imprescindible colocar un punto y coma (;) ya que éste termina las proposiciones.

 

En C, los comandos deben ser escritos con letras minúsculas. En el caso de las variables o la funciones definidas por el usuario la situación es similar: no es lo mismo  Apellido  que  apellido  que  APELLIDO, el compilador de C, los toma como tres nombres distintos. Por tanto, asegúrese de mandar llamar las variables o funciones exactamente de la misma forma en que las declaró.

 

Los tipos de datos son identificadores que usa cada lenguaje para saber la clase de información que va a tomar una variable. Por ejemplo: si quiero utilizar la variable "cantidad" para almacenar un número entero, declararé "cantidad" como una variable de tipo int lo que significa sólo aceptará valores de tipo entero.

 

Los tipos de datos básicos que maneja C son:

·       char identifica el contenido de la variable que se declare como caracter. Su longitud es de 1 byte.

·       int se refiere a valores de tipo entero. Ocupa 2 bytes.

·       float indica que la variable recibe datos de tipo real con aproximadamente 6 digitos de precisión. Su longitud en bytes es de 4.

·       double define variables que aceptan datos de tipo real con 12dígitos de precisión. Cada variable ocupa 8 bytes de memoria.

·       void Este tipo de dato sirve para declarar funciones que no devuelven valores. Su cantidad de bytes es cero.

 

Además de los anteriores, podemos crear otros tipos de datos al combinarlos con modificadores de tipo como signed, unsigned, long y short.

 

También existen los modificadores de acceso que sirven para controlar las formas en que se acceden o se modifican las variables. Estos modificadores son const y volatile.

Una variable de tipo const trabaja como una constante, ya que recibe sus valores por una inicialización explícita, o bien por algún medio dependiente del hardware. Por ejemplo: const int x; crea la variable entera x que no puede ser modificada por el programa pero si inicializada.

El modificador volatile se usa para indicar al compilador que el valor de una variable se puede cambiar por medios externos (no especificados) al programa. Por ejemplo la dirección de una variable global puede ser pasada a la rutina del reloj del sistema operativo y usada para mantener el tiempo real del sistema. En este caso, el contenido de la variable es cambiado sin que haya una sentencia que así lo indique.

Es importante que respetemos estos tipos de modificadores ya que ayudan a la optimización de las funciones del compilador. Se pueden usar ambos modificadores juntos.

 

DECLARACION DE VARIABLES

 

Forma general:

Tipo_de_dato Variable;

Donde tipo_de_dato puede ser cualquiera que esté permitido en C y Variable una palabra que designemos para recibir datos.

 

No hay cantidad máxima de caracteres (letras o palabras) que podamos utilizar para crear variables pero si hay dos que tengan los primeros 6 caracteres significativos iguales, C las tomará como si fuesen la misma.

 

Tampoco podemos utilizar como variables aquellos términos que ya han sido definidos previamente por el propio C o por el usuario como variables de otro tipo.

 

Las variables de tipo cadena se declaran como un conjunto de caracteres. Por ejemplo:

char nombre[30];

Donde 30 es el número de caracteres máximo que puede tener la cadena.

De acuerdo al lugar donde se declaran, las variables pueden ser globales, formales o locales.

Variables locales: Son aquellas que se declaran dentro de un conjunto de código relacionado lógicamente entre si (sentencias de control o funciones) Por ejemplo:

 

funcion_A()

{

int x;

.

.

. 

}

funcion_b()

{

int x;

.

.

.

}

 

En las funciones anteriores, declaramos dos variables llamadas "x" con el mismo tipo. Si se trata de utilizar alguna de las variables fuera de las funciones a las que pertenecen, se marcará un error porque el tipo sólo ha sido definido para utilizarse dentro de las llaves donde fue declarada. El que ambas variables se llamen "x" no quiere decir que sean la misma o que ocupen el mismo lugar en la memoria dado que las variables locales se crean y se destruyen cada vez que se sale del bloque en el que son declaradas por tanto, también su contenido se pierde al salir del él.

 

Parámetros formales: Muchas de las funciones necesitan argumentos. Los argumentos son datos que recibe la función desde el exterior. A las variables en que sirven para transmitir estos datos se les llama parámetros formales de la función. Su comportamiento es el mismo al de cualquier otra variable local. Veamos el siguiente ejemplo:

 

/*Devuelve la suma de dos números dados  */

suma(int a, int b)

{

 a+=b; /* a toma el valor de a+b */

  return(a);

}

Esta función realiza la suma de dos números. Utiliza dos parámetros formales: a y b los cuales deben ser declarados en la llamada a suma() para luego poder utilizarlas dentro de la función como variables locales. También se destruyen al salir de la función.

Se debe tener mucho cuidado de que los parámetros formales que se declaran sean del mismo tipo que los valores que se introducen cuando se manda llamar la función porque podría obtener resultados inesperados.

 

Variables globales: Este tipo de variables se conocen a través de todo el programa por lo cual se pueden usar en cualquier parte de la ejecución de éste. Se declararan antes de utilizar la variable por primera vez. Se recomienda que sea al principio del programa para mantener un orden.

 

Sentencias de asignación

La forma general de asignar valores a una variable es:

  nombre_variable=expresión

Expresión puede ser desde una constante hasta una combinación de variables, operadores y constantes.

Si se mezclaran variables de un tipo con las de otro, se aplica la regla de conversión de tipos que consiste en que el valor del lado derecho de la asignación se convierte al tipo de dato de la variable del lado izquierdo (que es la que va a recibir  el dato) siempre y cuando ésta última tenga mayor longitud en bytes. Por ejemplo, una variable int podemos asignarla a otra variable de tipo float pero no viceversa.

 


Arreglos

 

Un arreglo es un conjunto de elementos del mismo tipo agrupados en una sola variable. También se les conoce con el nombre de arreglos.

 

Para ingresar a un elemento en particular, utilizamos un índice. Existen arreglos unidimensionales, bidimensionales y multidimensionales.

 

Su uso más común es en la implementación de cadenas de caracteres. en C no existen variables de tipo cadena por lo cual se utiliza un arreglo de caracteres.

 

Físicamente, un arreglo es un conjunto de localidades de memoria contiguas donde la dirección más baja corresponde al primer elemento y la dirección más alta al último.

En un arreglo de n elementos, éstos ocuparan desde la casilla 0 hasta la n-1.

Por si mismo, el nombre del arreglo apunta a la dirección del primer elemento del arreglo.

 

La forma general para definir un arreglo unidimensional es la siguiente:

tipo_de_dato nombre_variable[tamaño]

 

 tipo_de_dato se refiere al tipo de dato de cada elemento del arreglo y tamaño es la cantidad de elementos agrupados en la misma variable.

 

Para acceder a uno de los elementos del arreglo en particular, basta con invocar el nombre del arreglo y especificar entre corchetes el número de casilla que ocupa el elemento en el arreglo. Por ejemplo, si queremos acceder al cuarto elemento de un arreglo de 10, se invocaría de la siguiente manera:

nombre_variable[3]

 

La forma de pasar un arreglo a una función consiste en llamar a la función y en el argumento, especificar el nombre del arreglo sin ninguna indexación. Esto hace que se pase a la función la dirección del primer elemento del arreglo ya que en C no es posible pasar el arreglo completo como argumento. Por ejemplo:

 

main()

{

  int conjunto[20];

  clrscr();

    .

    .

funcion(conjunto);

    .

    .

}

 

Aquí, al pasar el arreglo conjunto a función, estamos pasando la dirección en memoria del primer elemento de conjunto. En caso de que dentro de la función tuviésemos que acceder a algún elemento del arreglo, se pasa de la misma manera sólo que dentro de la función utilizaremos los corchetes para acceder al elemento deseado.

 

Hay tres formas de declarar un arreglo como parámetro formal: como un arreglo delimi-tado, como un arreglo no delimitado y como un puntero.

 

Por ejemplo:

 

funcion1(int conjunto[20]) /*Delimitando el array*/

{

   .

   .

   .

 }

o como

funcion1(int conjunto[]) /*arreglo no delimitado*/

{

   .

   .

   .

}

o se puede declara como

funcion1(int *conjunto) /*como un puntero*/

{

   .

   .

   .

}

El resultado de los tres métodos de declaración es idéntico.

 

Definimos una cadena en C como un arreglo de caracteres que al final tiene un caracter nulo ('\0'). Por esta razón es necesario que al declarar los arreglos estos sean de un caracter más que la cadena más larga que pueda contener.

 

Por ejemplo si se desea crear un cadena que contenga 5 caracteres la declaración debe hacerse como sigue:

char cadena[6];

 

Esto es con el fin de dejar el último espacio para el caracter nulo.

 

No es necesario añadir explícitamente el caracter nulo de las constantes de cadena porque el compilador de C lo hace automáticamente.

 

Un arreglo bidimensional es un arreglo de arreglos unidimensionales. Constituyen la forma m s simple de los arreglos multidimensionales.

 

Su forma general de declaración es

tipo_dato   variable[primer índice][segundo índice];

 

El primer índice corresponde a la filas y el segundo a las columnas.

 

Cuando se utiliza un arreglo bidimensional como argumento de una función, realmente se pasa sólo la dirección del primer elemento (el[0][0]). Sin embargo, la función que recibe un arreglo bidimensional como parámetro tiene que definir al menos la longitud de la segunda dimensión. Esto es necesario debido a que el compilador de C necesita "conocer" la longitud de cada fila para ordenar el arreglo correctamente. Por ejemplo, una función que recibe un arreglo bidimensional de 5,9 se declara así:

 

 

funcion(int matriz[][9])

{

   .

   .

   .

}

 

No es necesario especificar la primera dimensión pero la segunda si ya que el compilador de C la necesita para saber donde empieza la segunda fila.

 

También podemos utilizar arreglos bidimensionales para crear arreglos de cadenas. El primer índice indicaría el número de cadenas y el segundo la longitud máxima de las cadenas.

char mensajes[5][20];

 

En la declaración anterior se especifica que tenemos un arreglo llamado mensajes el cual contiene 5 cadenas de 20 caracteres cada una.

 

Para acceder a una cadena en especial, sólo especificamos el número de cadena (de 0 al número de cadenas menos 1). Ejemplo:

printf("%s",mensajes[3]);

 

Aquí mandamos imprimir la cadena número 3 de la variable mensajes. Esto sera equivalente a

printf("%s",mensajes[3][0]);

 

aunque es más común utilizar la primera forma.

 

En C, podemos también se puede crear arreglos más de dos dimensiones el límite de dimensiones, viene dado por el compilador. Su forma general de declaración es

tipo_dato   variable [longind1][longindice2] ...[longindiceN]

donde tipo_dato es el tipo de dato de los elementos del arreglo y longind1, longind2...longindN es la longitud de cada dimensión del arreglo. Este tipo de arreglos no se utiliza muy frecuentemente debido a el gran espacio en memoria que ocupan. Otra desventaja es que el acceso a un arreglo multidimensional dura más tiempo que el requerido por uno del tipo unidimensional.

 

Cuando se pasan arreglos multidimensionales a funciones, se tiene que declarar todo excepto la primera dimensión. Por ejemplo:

 

 

funcion1(int multiarreglo[][3][[4][5])

{

  .

  .

  .

}

 

main()

{

 int m[2][3][4][5];

 

  funcion(m[][3][4][5]);

  .

  .

  .

}

 

Claro que si se desea, se puede especificar también la longitud de la primera dimensión.

 

En C, podemos inicializar arreglos globales y arreglos estáticos locales en el momento de declararlos. No es posible inicializar arreglos globales no estáticos.

 

Su forma general de inicialización es

tipo_dato variable  [tamaño 1] [tamaño2] ... [tamaño] = {lista de valores};

 

Lista de valores es un conjunto de constantes, separadas comas, cuyo tipo es compatible con tipo_dato. La primera constante se coloca en la primera posición del arreglo, la segunda constante en la segunda posición, y asi sucesivamente.

 

int digitos[5]={'0','1','2','3','4',};

 

En el caso de los arreglos unidimensionales de caracteres podemos inicializarlos abreviadamente con la forma:

char  variable [tamaño]="cadena";

 

Por ejemplo:

char nombre[6]="clase";

 

Lo anterior es lo mismo que si inicializaramos nombre caracter a caracter como en el ejemplo de dígitos.

char nombre[6]={'c','l','a','s','e','\0'};


PUNTEROS

 

Un puntero es una zona de la memoria que contiene la dirección de otra zona de memoria.

 

En C, es muy importante el manejo de los punteros para una fructífera programación. Sus principales ventajas son:

·       Los punteros proporcionan los medios por los cuales las funciones pueden modificar sus argumentos de llamada.

·       Los punteros se utilizan para soportar las rutinas de asignación dinámica de C.

·       El uso de punteros puede mejorar la eficiencia de ciertas rutinas.

 

Aunque también cuenta con desventajas como

·       Son un recurso peligroso ya que los no inicializados o punteros descontrolados pueden provocar el fallo del sistema.

·       Es fácil utilizar punteros de forma incorrecta y ésto causa fallas muy difíciles de encontrar.

 

Los punteros pueden ser de cualquier tipo de datos. Esto quiere decir que puede haber punteros que contengan la dirección de variables de cualquier tipo.

 

La forma general de declarar una variable de este tipo es:

tipo_dato *nombre_variable;

 

tipo_dato es cualquier tipo de dato que soporte el C y nombre_variable es el nombre de la variable puntero. El * es el indicador de que nos estamos refiriendo a un puntero.

 

Existen dos operadores monarios (sólo necesitan un operando) utilizados para la manipulación de punteros. Ellos son el "&" y el asterisco "*".

 

Cuando una variable puntero va precedida del &, nos referimos a su dirección en memoria.

Por ejemplo:

Suponga que la variable dato ocupa la celda de memoria número 1000 y contiene una 'A'. s=&dato; la dirección de dato que es 1000.

La dirección no tiene nada que ver con el valor de dato. el operador "&" devuelve la dirección de la variable que le sigue.

El otro operador es el "*". Cuando éste precede a una variable puntero indica el valor de la variable puntero.

Por ejemplo:

s=*dato; Aquí s contendrá 'A' porque es el valor que se encuentra almacenado en dato.

 

Debe asegurarse de que las variables puntero apunten siempre al tipo de dato correcto es decir, que una variable puntero tipo int sea asignada a otra variable puntero del mismo tipo y así respectivamente. De lo contrario, aunque no se produzcan errores al compilarlo (sólo advertencias) los resultados no serán los deseados.

 

Existe una estrecha relación entre los punteros y los arrays ya que un array por si mismo es un puntero a la dirección de su primer elemento (Un nombre de array sin índice devuelve la dirección de comienzo del array que es el primer elemento). Por tanto, podemos intercambiar información entre punteros y arrays del mismo tipo de dato. ejemplo:

 

   char cad[30], punt;

   char *punt;

   punt=cad;

 

Arriba, tenemos un array de 30 caracteres y un puntero a caracter así que al asignar cad a punt, almacenamos en punt la dirección del primer elemento de cad.

Para acceder al quinto elemento de cad lo podemos hacer de dos formas:

cad[4] ó *(punt+4)

Ambas formas nos dan el mismo resultado.

Utilizamos el 4 para acceder al quinto elemento porque los arrays comienzan en el elemento número 0.

 

C proporciona dos métodos para acceder a los elementos de un array: la aritmética de punteros y la ordenación de arrays. La elección de cual utilizar es importante ya que la aritmética de punteros puede ser más rpápida que la indexación de arrays. En la práctica es frecuente el uso de punteros para acceder a elementos de un array en programas en C debido a que la velocidad es un factor importante en la programación.

 

También podemos agrupar punteros en arrays. Su formato de declaración sería el siguiente:

tipo_dato *nombre_variable[tamaño];

Por ejemplo:

int *[20];

 

declara un array de 20 elementos de tipo puntero a entero.

Este tipo de arrays poseen las mismas propiedades que los arrays comunes(en cuanto a la forma de acceder a sus elementos) y se manejan de la misma forma que las variables puntero simples (en cuanto a dirección y contenido). Por ejemplo, para asignar la dirección de una variable entera llamada elem al octavo elemento del array de punteros (que es una dirección), se indica

 

x[7]=&elem;

&elem significa "la dirección de elem".

Para encontrar el valor de elem desde el array se escribe

*x[7]

 

Para pasar un array de punteros a una función podemos llamarla con el nombre del array sin índices. Por ejemplo, la siguiente función utiliza un array de este tipo como parámetro:

 

despliega_elem(int *a[])

   {

     int i;

 

     for(i=0;i10;i++)

     printf("%d",*a[i]);

   }

despliega_elem imprime en pantalla el contenido de los elementos de a

 

Inicialización de punteros

Después de declarar una variable pero antes de asignarle un valor, contiene un valor desconocido. Si se intenta utilizar el puntero antes dedar le un valor, probablemente fallará no solo el programa, sino también el sistema operativo de la computadora.

 

Es por esto que las variables puntero también deben ser inicializadas.

 

Inicializar una variable es darle un valor específico; ésto se realiza indirectamente, al asignar la dirección de una variable a un puntero, o directamente, al declarar un puntero nulo es decir, que no apunte a dirección alguna.

ejemplo:

main()

       {

        char car;

       char*punt1,*punt2;

       punt1=&car;

       punt2=NULL;

           .

           .

           .

       }

Tenemos una variable llamada car que es de tipo caracter, además punt1 y punt2 que son punteros a caracter.

 

Al asignar la dirección de car a punt1 (punt1=&car) estamos inicializando indi-rectamente a punt1 porque su nuevo contenido depende de la dirección que car ocupe en memoria mientras que punt2 esta inicializado directamente ya que NULL es un valor constante que le dimos. En este caso, NULL indica que ese puntero no apunta a ninguna dirección (es como inicializar una variable entera en 0).

 

Se puede utilizar el puntero nulo para hacer muchas de las rutinas de punteros más fáciles de codificar y más eficientes. Por ejemplo, en la siguiente función, se leen los elementos de un array hasta que se encuentre un puntero nulo.

 

lee( char *lista)

{

int n;

n=0;

while (lista!=NULL)

printf("%s",*lista[n]);

}

 

En este caso, NULL nos sirve para determinar el fin de una lista de elementos.


ESTRUCTURAS

 

Las estructura es un tipo de datos compuesto que permite el C. Se define como un conjunto de variables relacionadas lógicamente entre sí que se referencian bajo un mismo nombre.

Su forma general de definición es

 

 struct nombre_de_la_estructura{

  tipo nombre_variable;

  tipo nombre_variable;

  tipo nombre_variable;

  .

  .

  }variables_tipo_nombre_de_la_estructura;

 

donde nombre_de_la_estructura o bien variables_tipo_nombre_de_la_variables_estructura pueden omitirse pero no ambos.

Ejemplo:

 

   struct agenda{

    char nombre[30];

    char direccion[20];

    char ciudad[15];

    int edad;

    } actor;

 

agenda es el nombre de la estructura. nombre, dirección, ciudad y edad son los campos o elementos de la estructura y actor es la variable declarada de ese tipo.

 

Los elementos individuales de la estructura se referencian utilizando el operador punto. Por

ejemplo: actor.nombre="Harrison Ford";

Aquí se está asignando la cadena "Harrison Ford" al campo nombre de la variable actor.

 

El nombre de la variable tipo estructura seguido del punto y del nombre del campo, referencia ese campo individual de la estructura. a todos los elementos de la estructura se accede del mismo modo. La forma general es: variable_estructura.nombre_elemento

 

Así, para imprimir en pantalla el campo edad de la variable actor, escribimos:

      printf("%d",actor.edad);

 

De la misma forma podemos utilizar gets (función que lee una cadena desde el teclado) para obtener un valor para actor, domicilio como se muestra aquí.

      gets(actor.domicilio);

 

Las variables tipo estructura son útiles para crear unidades de información de diferentes tipos lógicamente relacionada entre si. Tal es el ejemplo de los datos de una agenda (en una variable guardas su nombre, dirección, número telefónico, etc.) o de los datos de un elemento de la tabla periódica (en cada variable guardas su nombre, símbolo, número atómico, etc.).

 

INICIALIZACIÓN DE VARIABLES

 

Inicializar una variable es darle un valor después que se ha declarado pero antes de que se ejecuten las sentencias en las que se emplea.

En C, se les puede dar un valor a la vez que se declaran. Unicamente se coloca el signo igual y una constante después del nombre de la variable. La forma general de inicialización es:

tipo nombre_variable = constante;

 

   int uno=1;

   float pi=3.1416;

   char respuesta='s';

 

Regularmente, las variables locales se inicializan cada vez que se entra en el bloque en el que están definidas mientras que las globales son inicializadas al principio del programa.

 

Constantes

Constantes son los valores que no pueden ser modificados. En C, pueden ser de cualquier tipo de datos.

Además podemos crear constantes de caracteres con barra invertida. Estos corresponden a los caracteres que son imposibles introducir desde el teclado.

Se usan de la misma forma que los caracteres normales por ejemplo:

printf('Esta es una prueba\n");

ch='\0';

 

 

 

 

OPERADORES

Un operador es un símbolo que indica al compilador que realice manipulaciones lógicas o matemáticas específicas.

 

 

Cuando se aplica el símbolo / a un entero o a un caracter, cualquier residuo se trunca. Por ejemplo 5/3 será 1 en división entera.

El menos monario hace el efecto de multiplicar su único operando por -1 es decir, cualquier número precedido por un signo menos cambia de signo.

 

Incremento y decremento Dos operadores característicos de C son el incremento y el decremento.++ aumenta en uno a su operando y -- le resta 1. Es decir,

  x=x+1 es equivalente a ++x;

  x=x-1 es equivalente a –x;

 

Los operandos de incremento y decremento pueden ir antes o después del operador sin embargo existe una diferencia. Veamos el siguiente ejemplo: si x=10;

y=x++;  Aquí y tomará el valor de 10. y en

y=++x;  y tomará el valor de 11.

 

Los operadores relacionales son los que determinan la forma de vinculación entre dos valores. A su vez, los operadores lógicos evalúan la forma de relacionarse los dos valores.

 

El lenguaje C admite abreviaturas que simplifican la escritura de ciertos tipos de sentencias de asignación. Por ejemplo:

    x=x+10; es igual a x+=10;

 

 


SENTENCIAS DE CONTROL

Son herramientas básicas en la implementación de programas.

una sentencia puede ser una proposición o un conjunto de proposiciones (cuando se encuentran agrupadasentre llaves)

 

SENTENCIAS CONDICIONALES

Las sentencias IF

La sentencia de control if nos sirve para verificar que se cumpla una condición en el programa. Su forma general es

 

if(expresión) sentencia;

else sentencia;

 

Ejemplo: 1

if (divisor!=0)

divisior=dividendo/divisor;

else

printf("Error en el divisor");

 

Ifs anidados

La expresión "ifs anidados" se refiere a que podemos utilizar una sentencia if dentro de otra sentencia if. Esto se emplea cuando se tienen que cumplir varias condiciones para poder ejecutar una acción.

 

Ejemplo: 2

 

menu()

{

char opcion;

printf("A) Español \n");

printf("B) Matemáticas \n");

scan("%c",&opcion);

printf("Escogió ");

if (opcion=='A')

   printf("español");

else if (opcion=='B')

        printf("matamáticas");x

     else printf("una asignatura inexisten-
                 te" );

}

La sentencia Switch

Cuando se anidan muchos ifs, el código puede volverse difícil de entender. Para darle mayor transparencia, en C se utiliza la sentencia de decisión múltiple switch.

Switch es utilizada cuando una variable es sucesivamente comparada con una lista de enteros o de caracteres. Cuando se encuentra la correspondencia, se ejecuta una sentencia o el bloque de sentencias.

La forma general de una sentencia switch es

switch(expresión) 

{

case constante1:

secuencia de sentencias;

break;

case constante2:

secuencia de sentencias;

break;

case constente3:

secuencia de sentencias;

break;

.

.

.

default:

secuencia de sentencias;

}

 

donde switch es el indicador del tipo de sentencia de control. { } delimitan lo que abarca la sentencia switch. case especifica donde comienza la evaluación de la variable con la constante que sucede al case

En caso de que encontremos el valor de la variable en un case se ejecutarán la secuencia de sentencias relacionadas con este hasta encontrar un break.

Las sentencias asociadas a Default serán ejecutadas si no se encuentra ninguna correspondencia con el valor de la variable que estamos evaluando en alguno de los case. esta sentencia es opcional.

 

La diferencia entre switch e if es que la primera sólo puede comprobar la igualdad, mientras que if puede evaluar expresiones relacionales o lógicas.

 

No puede haber dos constantes case que tengan los mismos valores sólo en el caso de que la sentencia switch este anidada (que haya una dentro de otra).

Ejemplo 3

menu()

{

char opcion;

printf("A) Español\n");

printf("B) Matemáticas\n");

printf("Opción: ");

scan("%c",&opcion);

printf("Escogió ");

switch(opcion)

  {

   case'A':printf("español");

           break;

   case 'B':printf("matemáticas");

           break;

   default: printf("escogiste una asignatura
                   inexistente");

  }

}

 

Bucles

Se denomina bucles a las proposiciones de control que nos permiten ejecutar una sentencia hasta que se cumpla cierta condición. Es decir, si tenemos que realizar una tarea varias veces, basta con escribirla una sola vez dentro de un bucle, para que pueda efectuarse las veces que deseamos. Los bucles soportados por C son el for, el while y el do-while.

 

For

 

for(inicialización;condición;incremento) sentencia;

 

donde Inicialización es una sentencia de asignación que nos sirve como variable de control del bucle. Condición es una expresión que nos indica la condición que debe cumplirse para que continue el bucle e incremento define como va cambiando el valor de la variable de control cada vez que se repite el bucle. Sentencia es el conjunto de proposiciones que se van a realizar en cada repetición.

 

 

 

Ejemplo 4

main()

{

 for(x=1;x<80;x++)

    {

     gotoxy(x,1);

     printf("¾");

     gotoxy(x,24);

     printf("¾");

    }

 gotoxy(1,1);

 printf("é");

 gotoxy(80,1);

 Printf("ù");

 gotoxy(1,24);

 printf("ë");

 gotoxy(80,24);

 printf("û");

 for(x=0;x<24;x++)

    {

     gotoxy(1,x);

     printf("ï");

     gotoxy(80,x);

     printf("ï");

    }

}

Una de las principales características del for es que la condición (para determinar si se ejecutan o no las sentencias que contiene) se evalúa al principio del ciclo. Por esto, el código dentro del bucle no será ejecutado si la condición es false al comienzo.

Debido a la flexibilidad del lenguaje C, se pueden utilizar dos o más variables de control Por ejemplo:

for (i=0,j=4;i*j<4;i++,j--)

{

.

.

.

}

En este caso, estamos inicializando a i y a j dentro del bucle. Al mismo tiempo, en la sección de incremento, aumentamos a i y disminuimos el valor de j. Esto es completamente válido.

 

Bucle Infinito

Es aquel que no tiene fin. En este tipo de ciclos, no necesitamos especificar ninguna de las tres proposiciones que lo constituyen

for (;;) printf("Bucle infinito");

o basta dejar la de la condición vacía como se muestra a continuación:

for(x=0;;x++) printf("Bucle infinito");

La forma de romper un bucle infinito es mediante la sentencia break. Cuando se encuentra esta proposición dentro de un ciclo, trunca el bucle y se procede a ejecutar el código que se encuentra inmediatamente después de él.

 

Ejemplo 5

main()

}

 for(;;)

    {

      printf("Número: ");

      scanf("%d",&x);

      if(x==9) break;

     }

 printf("Digitaste %d números antes de rom-
         per el ciclo",x);

}

 

Bucle sin cuerpo

Según la sintaxis de C, existen las sentencias vacías por tanto, podemos tener un bucle for o cualquier otro, que no tenga cuerpo. Este tipo de ciclos se usan regularmente para retardar la ejecución del programa. Veamos como crear uno:

 

Ejemplo 6

main()

{

  int num;

  printf("Piensa un número del 1 al 10.");

  lapso();

  printf("Que número pensaste: ");

  scanf("%d",&num);

  .

  .

  . 

}

 

lapso()

{

  int tiempo

  int valor=100;

  for (tiempo=0;tiempo<valor;tiempo++);

}

 

En el programa anterior, se dá cierto tiempo para que pienses un número y luego lo escribas.

 

 

While

Este es otro de los bucles disponibles en C.

 

while(condición)sentencia;

donde sentencia es una sentencia vacía, una única o un bloque de sentencias. El bucle itera mientras se cumpla la condición (puede ser cualquier expresión). Cuando ya no se cumple, el control del programa pasa a la línea siguiente al código del bucle.

 

Ejemplo: 1

#include <ctype.h>

#include<conio.h>

 

#include <math.h>

 

main()

{

  char respuesta;

  clrscr();

  respuesta='\0';

  while (respuesta!='N')

  {

     float x;

     printf("Dame un número: ");

     scanf("%f",&x);

     x=fabs(x);

     printf("Su valor absoluto es: %f\n",x);

     printf("Presione 'N' para salir...\n");

     respuesta=toupper(getch());

  }

}

 

Inicializamos la variable respuesta con caracter nulo ('\0') para asegurarnos de que al menos se entre una vez al ciclo. Al final del bucle, preguntamos si quiere continuar o no. Con getch()leemos el caracter. toupper() nos sirve para convertir el caracter recibido por getch() a mayúsculas; de esta manera logramos que se acepte 'n' o 'N' para terminar el ciclo.

 

Como en el caso del for, podemos utilizar bucles while sin cuerpo. Por ejemplo:

while((letra=getch())!='M');

En letra se guardará el valor que se lea con getch() y estos se repetirá hasta que letra sea igual a 'M'.

 

 

DO-WHILE

La característica principal del Do-while es que analiza la condición del bucle al final del ciclo, lo que garantiza que el bloque de sentencias se ejecute al menos una vez. Su forma general es

 

do{

sentencia

}while(condición);

 

Las llaves no son necesarias cuando sentencia corresponde a una sola propo-sición, pero se recomienda que utilizarlas para mejorar la legibilidad del programa.

Como ejemplo, modifiquemos el programa anterior utilizando do-while:

 

Ejemplo: 2

#include <ctype.h>

#include<conio.h>

 

#include <math.h>

 

main()

{

  char respuesta;

  clrscr();

  do{

     float x;

     printf("Dame un número: ");

     scanf("%f",&x);

     x=fabs(x);

     printf("Su valor absoluto es: %f\n",x);

     printf("Continuar...\n");

     respuesta=toupper(getch());

    }while(respuesta!='N');

}

 

En esta ocasión, no necesitamos inicializar respuesta ya que por las características de do-while de todos modos se ejecutaría la primera vez. La única diferencia es que ahora la condición se comprueba al final del bucle y no al principio como lo hace for ywhile.

 

 

Break

La sentencia break tiene dos usos:

1.   Para determinar el final de un case en una sentencia switch (visto anterior-mente) y

2.   Terminar la ejecución de un bucle y saltar a la evaluación condicional del ciclo.

 

Cuando utilizamos una sentencia break dentro de un bucle, éste se termina inmediatamente y el control del programa pasa a la línea que está inmediatamente después del ciclo.

 

ejemplo: 3

 

main()

{

  int x;

  for(x=0;;)

  {

     if(x==250) break;

     x++;

  }

  printf("%d",x);

}

El programa anterior hay un ciclo infinito que es truncado cuando x es igual a 250.

 

 

Exit()

Esta sentencia da lugar a la terminación del programa.

Los programadores la utilizan cuando no se satisface una condición obligatoria en la ejecución de un programa ya que detiene su ejecución y fuerza la vuelta al sistema operativo.

La función exit() requiere de un argumento entero ya que se supone que un proceso de alto nivel sería capaz de acceder al valor contenido en el argumento . Normalmente se utiliza un argumento 0 (exit(0)) para indicar que se trata de una terminación normal y otros argumentos para indicar algún tipo de error.

Por ejemplo, imagine un programa al que se tenga que dar una clave de acceso para iniciar. La función main() de este programa sería como esta:

 

ejemplo 4

main()

{

  char clave[]="clave";

  char password[5];

  printf("Proporcione clave de acceso: ");

  scanf("%s",password);

  if(password!=clave)exit(1);

  .

  .

  .

}

 

Al iniciar el programa, se pide la clave de acceso. En caso de que no sea la especificada, el programa termina sin esperar nada más.


Continue

Es una sentencia de significado opuesto al break. En vez de forzar la terminación del bucle, continue obliga una nueva iteración del ciclo y salta cualquier código que exista entre este.

 

ejemplo 5

do{

   int years,tope=12;

   gotoxy(5,5);

   clreol();

   printf("Años: ");

   scanf("%d",&years);

   if (years<=0) continue;

   if (years<=tope)

   printf("Lo siento, este programa no es
          para niños");

  }while(tope!=18);

 

En el ciclo anterior, utilizamos el continue para verificar que la edad se mayor que cero. En caso de que ésta sea cero o menos vuelve a comenzarlo sin llegar a ejecutar las instrucciones del bucle restantes. Al no comparar la condición que puede terminar el ciclo, éste se repite.

 

FUNCIONES

En C, una función es un bloque de instrucciones que realizan una tarea específica la cual se maneja como una unidad lógica. Esta unidad, regresa un valor de acuerdo al resultado del proceso que realice.

C es un programa de funciones, todo se hace a partir de ellas. La principal es main() la cual, utiliza a otras que se encuentran definidas en las bibliotecas (todas las instrucciones que maneja C).

Además de éstas, nosotros podemos definir nuestras propias funciones. De esta manera dividimos tareas grandes de computación en varias más pequeñas lo que nos da como resultado que el programa sea más fácil de entender y se pueda manejar más eficientemente.

Además, al subdividir los programas en funciones, éstas pueden ser reutilizadas en otros programas.

 

La forma general para definir una función es:

especificador_tipo nombre_de_la_función (declaración deparámetros)

{

 cuerpo de la función

}

 

El especificador_de_tipo de la función define la clase de valor que regresa la función. El valor puede ser cualquier que maneje el C. En caso de que no se especifique ninguno, la función devuelve por omisión un entero.

Nombre_de_la_función es la palabra con la que vamos a identificara la función.

La declaración de parámetros es un conjunto de variables separados por comas y con un tipo de dato específico que reciben los valores de los argumentos cuando se llama a la función.

Una función puede carecer de parámetros en cuyo caso los paréntesis estarán vacíos tanto al declarar como al mandar llamar a la función.

 

Por ejemplo:

float multiplicación (float multiplicando,float multiplicador)

{

multiplicando=multiplicando*multiplicador;

return(multiplicando);

}

La función está declarada de tipo float porque es la clase de valor que va a regresar.

Multiplicando y multiplicador es el nombre que le vamos a darlos valores que recibirá la función para trabajar con ellos los cuales, son declarados dentro de los paréntesis.

Por último se define el cuerpo de la función (delimitándose con llaves) .

En este caso, asignamos el resultado de la multiplicación a multiplicando para ahorrar memoria (se declara una variable menos) y regresamos el valor obtenido por medio de la sentencia return.

 

Return

Esta sentencia se utiliza para devolver valores generados en una función al programa principal. También sirven para salir de la función donde se encuentra y continuar con la instrucción posterior a la función que lo llamó.

En la función anterior return(multiplicando)devuelve el contenido de multiplicando al programa principal. En caso de que sólo se quiera salir de la función, no es necesario indicarle parámetros, basta con return();.

Todas la funciones, excepto las de tipo void (Es el tipo de datos que no tiene valor) generan valores que se transmiten al programa principal. Estos valores son de tipo int (entero) por omisión, pero puede regresar los de todo tipo si así se declara; por ejemplo, en la función de multiplicación, la función regresa un valor de tipo float (flotante).

Cuando queremos utilizar el valor que devuelve la función en el programa principal, es necesario asignar la función a una variable del tipo de dato que va a regresar la función.

 

Reglas de las funciones

·       No se puede declarar funciones dentro de funciones ya que todas están al mismo nivel,.

·       Tampoco se puede ingresar al código de una función si estamos fuera de la misma.

·       Las variables que se declaran en las funciones, son locales y no pueden ser utilizadas fuera de esa función.

·       Además, si utilizamos una función dos o más veces, la segunda vez las variables locales no contendrán el valor que obtuvieron al ejecutar la primera vez la función y así sucesivamente ya que se crean al entrar a la función y se destruyen al salir.

 

Argumentos de las funciones:...

Es muy común que las funciones utilicen argumentos es decir, que necesiten de algún valor o valores externos dentro de su propio código. Estos valores se pasan mediante variables llamadas parámetros formales de la función las cuales se declaran dentro de los paréntesis que suceden a el nombre de la función o bien, después de estos y antes de la llave de comienzo.

Asegúrese de que de que los argumentos utilizados al declarar la función sean del mismo tipo que los usados para llamar la función. Si hay algún error en los tipos, el compilador no mandará mensaje de error pero se obtendrán resultados inesperados.

Se puede utilizar a las variables que son parámetros formales como cualquier otra variable local es decir, se les puede hacer asignaciones o usarlos en cualquier expresión permitida por C.

 

Existen dos formas de pasar argumentos a una función:

Llamadas por valor

consiste en sólo pasar el contenido de la variable utilizada como argumento a la subrutina. De esta manera, los cambios efectuados en los parámetros de la función no afectan a las variables (globales) que se utilizaron para hacer la llamada a la función.

Llamadas por referencia

En la cual, lo que se pasa a la subrutina es la dirección de la variable que se está mandando como parámetro. De esta manera, los cambios que sufra el parámetro dentro de la subrutina, se efectuarán también en la variable que se introdujo como parámetro.

La forma de pasar una llamada por referencia es pasando un puntero al argumento, de esta manera, lo que pasará es la dirección de la variable en vez de su contenido. Para esto, los parámetros se declaran de tipo puntero.

 

/* Ejemplo de funciones por valor y por referencia */

/* Calcula dos veces el porcentaje de gastos, la primera vez utilizando una función por valor y la segunda por referencia */

 

main()

{

  float entrada, salida;

  clrscr();

  printf("Entradas: ");

  scanf("%f",&entrada);

  printf("Salidad: ");

  scanf("%f",&salida);

  porcentaje_xvalor(entrada,salida); /*Llamada a la función porcentaje utilizando paso de
                                       parámetros por valor */

  printf("\n\n");

  porcentaje_xref(&entrada,&salida); /*Utilización de la función porcentaje con paso de
                                       parámetros por referencia */

  getch();

}

porcentaje_xvalor(float ingreso, float egreso)

{

  egreso=((egreso/ingreso)*100)

  printf("Usted gasta el %.2f por ciento de lo que gana", egreso);

}

porcentaje_xref(float *ingreso, float *egreso)

{

  *egreso=(((*egreso)/(*ingreso))*100);

  printf("Usted gasta el %.2f por ciento de lo que gana", egreso);

}

En el programa anterior, realizamos la misma tarea dos veces pero de diferente manera.

 

En porcentaje_xvalor(entrada,salida) mandamos el contenido de entrada y salida a la función donde son recibidos por ingreso y egreso respectivamente. De esta manera, el cálculo del porcentaje se hace internamente es decir, utilizando las variables definidas en la función. Tanto entrada como salida, no se modifican.

 

La función porcentaje_xref(&entrada,&salida) también obtiene el mismo resultado, pero en este caso, en vez de pasar los valores existentes en las variables, pasamos su dirección; por lo que trabajamos directamente con ellas dentro de la función aún cuando las llamemos de diferente manera( ingresos y egresos). En esta ocasión, las variables globales si se modifican.

 

Creación de Bibliotecas propias.

Si quiere utilizar funciones definidas por Ud. en varios programas, puede hacerlo, creando su propia biblioteca. Esto se logra de la siguiente manera:

 

·       Defina sus funciones en un nuevo archivo. Mande llamar las librerías estándar de C, que necesite.

·       No utilice la función main().

·       Compilalo

·       Cuando la compilación sea exitosa, se generará un archivo con el mismo nombre que el suyo pero con la terminación Obj. Este archivo deberá ser incluido preferentemente en el mismo directorio que se encuentre la biblioteca . En caso contrario, se debe dar la ruta en la sección Directories del menú Options.

·       En el programa donde quiera utilizar esta unidad sólo tendrá que mandarla llamar al principio del programa de la siguiente manera:

 

 

#include "nombre_archivo"

Después de esto, puede llamar a las funciones que tengas definidas en esta librería normalmente sin tener que declararlas al principio del programa.

Además de funciones, en la biblioteca también puede definir constantes, macros, etc.

 

 

 

Programa ejemplo:

/*Programa que convierte un número en hexadecimal a decimal*/

 

#include<math.h>

#include<string.h>

#include<conio.h>

void main()

{

char hexa[10];

float numero;

clrscr();

printf("Numero hexadecimal (mayúsculas): ");

gets(hexa);

numero=hex_dec(hexa);

printf("\n En decimal es : %.0f",numero);

}

float hex_dec(char cadena[])

{

int i,j;

char letra;

float decimal=0;

float temp=0;

 

i=strlen(cadena);

for (j=0;i>0;j++,i--)

{

letra=cadena[i--];

switch(letra){

case 1:temp=(1*pow(16,j));

       break;

case 2:temp=(2*pow(16,j));

       break;

case 3:temp=(3*pow(16,j));

       break;

case 4:temp=(4*pow(16,j));

       break;

case 5:temp=(5*pow(16,j));

       break;

case 6:temp=(6*pow(16,j));

       break;

case 7:temp=(7*pow(16,j));

       break;

case 8:temp=(8*pow(16,j));

       break;

case 9:temp=(9*pow(16,j));

       break;

case 0:temp=(0*pow(16,j));

       break;

case 'A':temp=(10*pow(16,j));

       break;

case 'B':temp=(11*pow(16,j));

       break;

case 'C':temp=(12*pow(16,j));

       break;

case 'D':temp=(13*pow(16,j));

       break;

case 'E':temp=(14*pow(16,j));

       break;

case 'F':temp=(15*pow(16,j));

       break;

}

decimal+=temp;

}

return(decimal);

}


FUNCIONES DE ENTRADA Y SALIDA  (  )

 

int getchar() Esta función leé un caracter desde el teclado hasta que se pulse <ENTER>.En caso de que se digite máss de un caracter antes de pulsar <ENTER>, la variable sólo almacenará el primer caracter que se tecleó.

 

char *gets(char *cad) Esta función leé una cadena de caracteres desde el teclado y la coloca en la cadena cad. Se leen caracteres hasta que se recibe la pulsación de <ENTER>. Esto no quiere decir que en la cadena se almacenará este caracter sino que añadirá un carácter nulo (\0) para identificar el final de la cadena. En caso de error, gets() retorna un puntero nulo y el contenido de cad será indeterminado. Con gets() puedes leer todos los caracteres que desees. Por tanto, corresponde al programador asegurarse que la cantidad de caracteres leídos no superen la capacidad del array.

 

int putchar(ch) putchar() escribe un caracter en pantalla donde ch puede ser una variable de tipo caracter o un caracter ASCII entre comillas simples('') y posiciona el cursor en la siguiente línea.

 

int puts( char *cad) La función puts() escribe en pantalla el contenido de una cadena apuntada por cad (un conjunto de caracteres) y posiciona el cursor en la siguiente línea.

 

int kbhit() Esta función no está definida por el ANSI propuesto. Sin embargo, la incluimos aquí porque aunque con nombre diferente, se encuentra definida en todas las implementaciones de C. Su uso principal es permitir que el usuario pueda interrumpir alguna rutina desde el teclado. Regresa un valor distinto de cero, si se ha pulsado una tecla y en caso contrario, el valor retornado es cero.

 

int printf(char *formato, lista_arg) La función printf() despliega en pantalla tanto cadenas constantes(mensajes) como variables de acuerdo al contenido de formato. Con formato, se especifica la cadena constante y/o el tipo de variables que desplegará en pantalla. Todo esto siempre va entre comillas("") . Por ejemplo:

con printf("Hola, como estas?"); mandamos un mensaje a pantalla. En este caso, no es necesario especificar algún formato ya que sólo se despliega el mensaje.

en printf("%s",nombre); utilizamos formato para determinar el tipo de varaible(s) que van a ser desplegadas. determinamos que se va a escribir el contenido de nombre que es una variable de tipo cadena.

para definir el contenido de cualquier varibale:

 

Código   Formato

 %c  Un sólo caracter

 %d  Decimal

 %i   Decimal

 %e  Notación científica

 %f   Coma flotante

 %g  utiliza el más corto de %e o %f.

 %o  Octal

 %s  Cadena de caracteres

 %u  Decimal sin signo

 %x  Hexadecimal

 %% Imprimir el símbolo %

 %p  Presentar un puntero

 %n  El argumento asociado será un puntero entero en el que se sitúa el número de caracteres escritos hasta entonces.

 

También podemos desplegar en el monitor mensajes como el contenido de variables con el mismo comando printf() como en el ejemplo siguiente:

printf("Hola %s soy %s, tengo %i años." huesped, nombre, edad);

Si huesped="visitante", nombre="el supervisor" edad=35

el resultado será el siguiente mensaje en pantalla:

<Hola visitante soy el supervisor, tengo 35 años>.

 

Recuerde que se deben especificar en el mismo orden tanto el contenido de las variables a imprimir dentro de formato como las variables en sí.

 

La función printf() devuelve el número de caracteres realmente presentados en pantalla. Un valor negativo significa que se ha producido un error.

 

Se pueden escribir enteros entre el signo de porcentaje y el caracter que especifica el tipo de dato a presentar. Esto sirve para determinar la longitud del campo, el número de decimales y un indicador de justificación a la izquierda.

 

Para especificar la longitud del campo, basta con escribir el número después del signo de porcentaje; después se agrega un punto y el número de posiciones decimales que se desea presentar en el caso de los números en coma flotante. Si la cadena es mayor que la anchura del campo, se truncan los caracteres por el final.

Por ejemplo, %12.4f determina a un número de como máximo doce caracteres de longitud con cuatro posiciones para la parte decimal.

 

Cuando se aplica a cadenas de caracteres o enteros, el número después del punto determina la máxima longitud del campo. Por ejemplo %3.5s presenta una cadena que tiene al menos tres caracteres y que no excede de cinco. Si la cadena es mayor que el campo, se truncan los caracteres por el final.

 

Por defecto, toda salida está justificada por la derecha. En otras palabras, si la anchura del campo es mayor que la de los datos presentados, eston son situados en la parte derecha del campo. Puede forzar que la información quede justificada a la izquierda situando un signo menos inmediatamente después del signo de porcentaje. Por ejemplo %-6.3f justifica un número en coma flotante por la izquierda con tres posiciones decimales en un campo de seis caracteres.

Ejemplo: Si saludo="hola"  printf("%-10s",saludo); presentará: <hola >

 

int scanf(char *formato,lista_arg) Esta función realiza la operación contraria a printf()es decir, leé datos de cualquier tipo desde el teclado hasta que se pulse un retorno de carro(<ENTER>).

 

Sus parámetros también son similares a printf() ya que en formato se especifica el o los tipos de variables que se van a leer miemtrasq ue en lista_arg se escriben las variables. Por ejemplo:

scanf("%d",&edad);

scanf("%i%c",&edad,&sexo);

 

La sección de formato corresponde a "%d" donde se indica que se va a leer un entero decimal; &edad corresponde a lista_arg e indica que los caracteres leídos serán almacenados en la dirección que ocupa la variable edad.

 

La diferencia entre la sintaxis de scanf() y printf() consiste en que en la lista de argumentos, scanf() necesita que se le especifique que el lugar donde va a almacenar los datos es en la dirección de la variable( &edad). La única excepción es cuandose va a leer una cadena de caracteres ya que este tipo de variables indican una dirección por si mismas. Ejemplo:

char nombre[10];

scanf("%s", nombre);

 

A continuación se presentan los códigos de formato descanf().

Código   Interpretación

 %c  Leer un único caracter

 %d  Leer un entero decimal

 %i   Leer un entero decimal

 %e  Leer un número en punto flotante

 %f   Leer un número en punto flotante

 %h  Leer un entero corto

 %o  Leer un número octal

 %s  Leer una cadena de caracteres

 %x  Leer un número hexadecimal

 %p  Leer un puntero

 %n  Recibir un valor entero igual al número de caracteres leídos hasta entonces.

 

Un espacio en blanco en la cadena de control da lugar a que scanf() salte uno o más espacios en blanco en el flujo de entrada. Un caracter blanco es un espacio, un tabulador o caracter de nueva línea. Esencialmente, un caracter espacio en blanco en una cadena de control da lugar a que scanf() lea, pero no guarde cualquier número (incluido 0) de espacios en blanco hasta el primer caracter no blanco.

 

Un caracter que no sea espacio en blanco hace que scanf() lea y elimine el caracter asociado. Por ejemplo, %d,%d da lugar a que scanf() lea primero un entero, entonces lea y descarte la coma, y finalmente lea otro número. Si el caracter especificado no se encuentra, scanf() termina.

 

Un * situado después del % y antes del código de formato leé los datos de tipo especificado pero elimina su asignación. Asi, dada la entrada 10/20, el código

scanf("%d*%d",&x,&y); asigna el valor 10 a x, decarta el signo de división, y da a y el valor 20.

 

Las órdenes de formato pueden especificar un modificador de máxima longitud de campo. Situado entre el % y el código de orden de formato, es un entero que limita la cantidad de caracteres a leer para cualquier campo. Por ejemplo, si se quieren leer sólo 15 caracteres en nombre se escribiría asi:

scanf("%15s",direccion);

Si el flujo de entrada fuera mayor de 15 caracteres, entonces una posterior llamada de entrada debería comenzar donde esta llamada la dejó.P or ejemplo, si

Av._Corregidora_#_500 se ha introducido como respuesta al scanf() anterior, únicamente los primeros 15 caracteres (hasta la a de corregidora) serían situados en dirección debido al especificador de tamaño máximo. Cuando se hiciera otra llamada a scanf() tal como scanf("%s",cadena); _#_500 se asignará a cadena.

 

Cuando una cadena está siendo leída, los espacios, los tabuladores y los saltos de línea son utilizados como separadores de campos; sin embargo, cuando se leé un único caracter, estos son leídos como cualquier otro caracter.


FUNCIONES DE PANTALLA   ( #include<conio.h> )

 

clreol() borra desde la posición del cursor hasta que se alcanza el final de la línea en el extremo derecho de la pantalla. Esta operación sólo es válida en modo texto.

 

clreos() borra la pantalla desde la posición actual del curso hasta abajo. Sólo se aplica en pantallas en modo texto.

 

clrscr() borra toda la pantalla. En general, esta operación sólo se aplica cuando la pantalla está en modo texto.

 

gotoxy(int x, int y) Esta función, sitúa el cursor en la fila y columna definidas por x, y. Esta operación sólo se utiliza en pantallas de modo texto.

 

home() Coloca el cursor en la posición 0,0 (el extremo superior izquierdo de la pantalla). No borra la pantalla. Sólo funciona en modo texto.

 

int gettext(int izq, int top, int der, int centro, void *destino); Copia texto de la pantalla en modo texto a la memoria. Las coordenadas utilizadas son absolutas, no relativas a la ventana en la que se está trabajando. La coordenada del extremo superior izquierdo es (1,1). Regresa un valor diferente de cero si la operación fue exitosa.

 

int movetext(int izq,int top, int der, int centro, int detizq, int desttop); Copia texto en una pantalla de modo texto de una ventana a otra. Las coordenadas son relativas al extremo izquierdo de la pantalla (1,1). Regresa un valor diferente de cero si la operación se efectuó correctamente.

 

int puttext(int izq,int top, int der, int centro,void *source); Copia texto de la memoria a la pantalla. Las coordenadas utilizadas son absolutas, no relativas a la ventana en la que se esté trabajando. La coordenada del extremo superior izquierdo es (1,1). Regresa un valor diferente de cero si la operación fué exitosa.

 

insline(); Inserta una línea en blanco en una ventana de texto en la posición del cursor. Las líneas que se encuentran debajo de la posición del cursor se recorren una línea hacia abajo y se pierde la última línea.

 

lowvideo(void); Disminuye la intensidad de la luminosidad de los caracteres. Afecta a todos los caracteres que se imprimen posteriormente en pantalla dentro de esa ventana.

 

highvideo(void); Aumenta la intensidad de la luminosidad de los caracteres. Afecta a todos los caracteres que se imprimen posteriormente en pantalla dentro de esa ventana.

 

normvideo(void); Anula a highvideo() y/o normvideo(). Es decir, la luminosidad de los caracteres que se escriban a continuación, será normal dentro de esa ventana.

 

textcolor(int color); Selecciona un nuevo color de los caracteres que se escribirán a continuación.

 

texbackground(int color); Selecciona un nuevo color de la pantalla.

 

window(int iniciox,int inicioy, int finx, int finy); Crea una ventana activa en pantalla.

 


FUNCIONES MATEMATICAS ( #include<math.h> )

 

La mayoría de las funciones matemáticas están definidas con tipo de datos dobles pero podemos utilizar esas funciones con tipos de datos de menor rango, excepto caracteres.

 

double acos(double arg) La función acos() obtiene el arco coseno de arg. EL argumento de acos() debe estar en el rango de -1 a 1; en cualquier otro caso se produce un error de dominio.

 

double asin(double arg) Esta función devuelve el arco seno de arg. EL parámetro con el que se mande llamar a asin() debe estar en el rango de -1 a1 para que no produzca un error de dominio.

 

double atan(double arg) Devuelve el arco tangente de arg .

 

double atan2(double y, double x) atan2() devuelve el arco tangente de y/x. Utiliza el signo desus argumentos para obtener el cuadrante del valor devuelto.

 

double ceil(double num) Esta función da como resultado un valor double que representa el entero más pequeño que es mayor o igual a num. Por ejemplo, dado 1.02, ceil() devuelve 2.0; dado -1.02, devuelve-1.

 

double cos(double arg) Esta función devuelve el coseno de arg. El valor de arg debe darse en radianes.

 

double cosh(double arg) cosh() devuelve el coseno hiperbólico de arg. El valor de arg debe darse en radianes.

 

double exp(double arg) La función exp() devuelve un número e elevado a la potencia arg.

 

double fabs(double num) Devuelve el valor absoluto de num.

 

double floor(double num) La función floor() el mayor entero (representado en double) que no es mayor que num. Por ejemplo, dado 1.02, floor() devuelve 1.0; dado -1.02,floor() devuelve -2.0

 

double fmod(double x, double y) Esta función retorna el residuo de la división entera x/y.

 

double frexp(double num, int *exp) La función frexp() descompone el número num en una mantisa de rango entre 0.5 y 1 y en un exponente entero tal quenum=mantisa*2exp. Se devuelve la mantisa, y el exponente se guarda en la variable apuntada por exp.

 

double idexp(double num, int exp) Esta función regresa el valor de num*2exp. Si se produce desbordamiento, se devuelve HUGH-VAL (constante definida por C).

 

double log(double num) La función log() devuelve el logaritmo neperiano de num. Se produce un error cuando num es negativo y error de rango si el argumento es cero.

 

double log10(double arg) Esta función, regresa el logaritmo en base 10 de num. Se produce un error de dominio si el argumento es negativo, y un error de rango en caso de ser cero.

 

double modf(double num, int i) Esta función descompone num en su parte entera y fraccionaria, y sitúa la parte entera en la variable apuntada por i.

 

double pow(double base, double exp) retorna base elevada a exp, esto es base exp. Se produce un error de dominio si base es cero y exp es menor o igual a cero. También ocurre si base es negativo y expno es entero. Un desbordamiento produce un error de rango.

 

double sin (double arg) Devuelve el seno de arg. El valor de arg, debe darse en radianes.

 

double sinh(double arg) devuelve el seno hiperbólico de arg. El valor de arg debe darse en radianes.

 

double sqrt(double num) devuelve la raíz cuadrada de num. Si se llama con un número negativo, se produce un error de dominio.

 

double tan(double arg) Esta función, devuelve la tangente de arg. El valor de arg debe darse en radianes.

 

double tanh(double arg) retorna la tangente hiperbólica de arg. El valor devuelto debe darse en radianes.


FUNCIONES DE HORA, FECHA Y OTRAS RELACIONES CON EL SISTEMA. ( #include <time.h> )

 

char *asctime(punt)

struct tm *punt

Esta función regresa un puntero a una cadena que convierte la información almacenada en la estructura apuntada por punt de la forma siguiente:

dia mes horas:minutos:segundos año\n\0

Por ejemplo:

Miercoles Jun 19 12:05:34 1999

El puntero a estructura pasado a asctime() se obtiene generalmente de localtime() o gmtime().

El buffer utilizado por asctime() para mantener la cadena de salida con formato se situa estáticamente en un array de caracteres y se sobre escribe cada vez que se llama a la función. Si se desea salvar el contenido de la cadena, es necesario copiarlo en otro lugar.

 

clock_t_clock()Indica el tiempo empleado en la ejecución de un proceso. Para transformar este valor en segundos, se divide entre el valor de la macro CLK_TCK. Se devuelve el valor -1 si el tiempo no está disponible.<

 

char *ctime(long *hora)

long *ctime(long *hora)

Dado un puntero a la hora de calendario, la función ctime()convierte un tiempo almacenado como un valor de tipo time_t a una   cadena de caracteres de la forma:

dia mes fecha horas:minutos:segundos año\n\0

La hora de calendario se obtiene normalmente durante una llamada atime().

La función ctime() es equivalente a:

asctime(localtime(hora)) El buffer utilizado por ctime() para guardar la cadena de salida conformato se sitúa de forma estática en un array de caracteres y se sobreescribe cada vez que se llama a la función. Si se desea guardar el contenido de la cadena  es necesario guardarla en otro lugar.

 

double difftime( time_t hora1, tiem_t hora2) Esta función devuelve la diferencia en segundos que tarda en finalizar el bucle for desde 0 hasta 500000.

 

struct tm *gmtime(time_t hora) regresa un puntero a la forma separada de hora en una estructura tm. Esta, está representada en hora de Greenwich. El valor de hora se obtiene normalmente a través de una llamada a time().

La estructura utilizada por gmtime() mantiene la hora separada en una posición estática y se sobre escribe en ella cada vez que se llama a la función. Si se desea guardar el contenido de la estructura es necesario copiarlo en otro lugar.

 

struct tm *localtime(time_t *hora) devuelve un puntero a la forma separada de hora en la estructura tm. La hora se representa con la hora local. Esta se obtiene normalmente a través de una llamada a time().

La estructura utilizada por localtime() para mantener la hora separada, se situada de forma estática y se reescribe cada vez que se llama a la función. Si se desea guardar el contenido de la estructura, es necesario copiarla en otra variable.

 

time_t mktime(struct tm *hora) se utiliza principalmente para inicializar la hora del sistema. Los elementos tm_wday y tm_yday son activados por la función, de modo que no necesitan ser definidos en el momento de la llamada.

Si mktime() no puede representar la información como una horade calendario válida, se devuelve -1.

 

char *setlocale(int categoria, char lugar) permite al usuario pedir o activar ciertos parámetros que son sensibles al lugar donde se utiliza el programa. Por ejemplo, en Europa, la coma se utiliza en lugar del punto decimal; del mismo modo los formatos de la hora y la fecha difieren.

Si lugar es nulo, setlocale() devuelve un puntero a la actual cadenade localización especificada para poner los par metros de lugarsegún se especifica en categoría.

En el momento de la llamada, categoría debe ser una de las siguientes macros:

 

LC_ALL

LC_COLLATE

LC_CTYPE

LC_NUMERIC

LC_TIME

 

LC_ALL hace referencia a todas las categorías de localización. LC_COLLATE afecta a la operación de la función strcoll(). LC_CTYPE modifica la forma de trabajo de las funciones de caracteres. LC_NUMERIC cambia el caracter del mundo decimal para las funciones de entrada/salida con formato, Finalmente, LC_TIME determina el comportamiento de la función strftime(). El estándar define dos posibles cadenas para lugar. La primera es "C", que especifica el mínimo entorno para la compilación de C. El segundo es " ", la cadena vacía, que especifica el entorno de implementación definido por defecto. El resto de los valores definidos para locale() están definidos por la implementación y afectan a la portabilidad.

 

time_t time(time_t hora) devuelve la hora actual del calendario del sistema. Si el sistema no tiene hora, devuelve -1.

Puede llamarse con un puntero nulo o con un puntero a una variable de tipotime_t. Si se utiliza este último, el argumento también es asignado a la hora de calendario.

 
FUNCIONES CON CADENAS

   ( #include <ctype.h> )

int isalnum(int ch) devuelve un valor distinto de cero en caso de que ch sea una letra del alfabeto o un dígito; si no, devuelve cero.

int isalpha(int ch) si ch es una letra del alfabeto, regresa un valor diferente de cero, en cualquier otro caso, devuelve cero.

int iscntrl(int ch) determina si ch es un caracter de control - entre 0 y 0x1F (0 a 31 en decimal) o si ch es igual a 0x7F(la tecla DEL)- en cualquier todo caso, devuelve cero.

int isdigit(int ch) devuelve un valor distinto de cero si ch es un número dígito (desde 0 a 9). De lo contrario, devuelve cero.

int isgraph(int ch) comprueba si ch es un carácter imprimible distinto del espacio en blanco; si no es así, devuelve cero como resultado de la ejecución.

int islower(int ch) devuelve un valor distinto de cero cuando ch es un caracter en minúscula es decir, una letra desde a hasta z; en cualquier otro caso devuelve cero.

int isprint(int ch) verifica que ch sea un carácter imprimible, incluyendo el espacio en blanco; en cualquier otro caso, se devuelve cero.

int ispunct(int ch) comprueba que ch sea un caracter de puntuación, excluyendo el espacio en blanco; en cualquier otro caso devuelve cero. En puntuación se incluye a todos los caracteres que no son alfanuméricos ni el espacio en blanco

int isspace(int ch) Esta función, devuelve un valor diferente de cero en caso de que ch sea el espacio en blanco, el tabulador o un caracter de salto de línea; en cualquier otro caso, devuelve cero.

int isupper(int ch); comprueba que ch sea una letra mayúscula(cualquier letra entre A y Z); en caso contrario devuelve cero.

int isxdigit(int ch) devuelve un valor distinto de cero si ch es un dígito hexadecimal; en caso contrario, devuelve cero.

void *memchr(void *buffer,int ch, unsigned int cuenta) busca en buffer la primera ocurrencia de ch en los primeros cuenta caracteres. La función regresa un puntero a la primera ocurrencia del caracter ch en buffer. Si no se encuentra ch se devuelve un puntero nulo.

int memcmp(void *buf1,void *buf2,unsigned int cuenta) Esta función compara lexicográficamente los primeros cuenta caracteres de los arreglos buf1 y buf2. memcmp() devuelve un entero que se interpreta acorde a lo siguiente:

Valor               Interpretación

Menor que 0    buf1 es menor que buf2

0                     buf1 es iguala buf2

Mayor que cero       buf1 es mayor que buf2.

void memcpy(void *hacia, void *desde, unsigned int cuenta) Esta función sirve para copiar cuenta caracteres del arreglo desde en el arreglo hacia. Si los arreglos se superponen, el comportamiento de memcpy()queda indefinido. Como resultado, devuelve un puntero a hacia.

void *memset(void *buf, int ch, unsigned int cuenta) copia el byte menos significativo de ch en los primeros cuenta caracteres del arreglo apuntado por buf. Devuelve buf. El uso más común de memset() es dar valor inicial una región de memoria con algún valor conocido. En caso de que el compilador no soporte el tipo void.

char *strcat(char *cad1, char *cad2) Esta función concatena una copia de cad2 en cad1 y añade al final de cad1 un caracter nulo. El caracter nulo determinación que originalmente tenía cad1 es sustituido por el primer caracter de cad2. La cadena cad2 no se toca en esta operación. La función devuelve cad1. Es necesario que cad1 sea lo suficientemente grande como para mantener su contenido original y el de cad2.

char *strchr(char *cad, int ch) devuelve un puntero a la primera ocurrencia de ch en la cadena apuntada por cad. Si no se encuentra, devuelve un puntero nulo.

unsigned int strcoll(char *hacia, unsigned int cuenta, char *desde) se utiliza para ajustar la cadena apuntada por desde de modo que pueda ser utilizada por memcmp() ostrcmp() según se requiera. El resultado de tal ajuste se sitúa en la cadena apuntada por hacia hasta la longitud que cuenta especifica. En ningún caso, sin embargo, la longitud de la cadena apuntada por hacia debe superar el doble de la longitud de la cadena apuntada por desde. La función devuelve la longitud de hacia si se ejecuta correctamente, si no la función devuelve cero.

int strcmp(char *cad1, char *cad2) Por medio de esta función se comparan lexicográ-ficamente dos cadenas que finalizan con el caracter nulo y devuelve un entero que se interpreta de la siguiente forma:

Valor             Interpretación

Menor que 0    cad1 es menor que cad2

0                   cad1 es iguala cad2

Mayor que 0 cad1 es mayor que cad2

char *strcpy(char *cad1, char *cad2) se utiliza para copiar el contenido de cad2 encad1. La variable cad2 debe ser un puntero a una cadena que finalice con un caracter nulo; strcpy() devuelve un puntero acad1. Si cad1 y cad2 se solapan, el com-portamiento de strcpy() es indefinido.

int strcspn(char *cad1, char *cad2)11 devuelve el índice (la dirección)del primer caracter en la cadena apuntada por cad1 que está como caracter de la cadena apuntada por cad2.

char *strerror(int num_error) Esta función convierte el número de error especificado por num_error en una cadena de mensaje de error. Regresa un puntero a la cadena. El mensaje a cada num_error está definido en la aplicación. Bajo ninguna circunstancia se debe modificar la cadena.

unsigned int strlen(char *cad) nos sirve para determinar el número de caracteres que continúe una cadena que finaliza con el caracter nulo. El caracter nulo no se contabiliza.

char *strncat(char *cad1,char *cad2, unsigned int cuenta) concatena cuenta caracteres de la cadena apuntada por cad2 en la cadena apuntada por cad1 y pone al final de cad1 el caracter nulo. El caracter nulo que tenia inicalmentecad1 es sustituido por el primer caracter de cad2. La cadenacad2 no se toca. strncat() devuelve cad1. no se hacen comprobaciones de límites. Así que es necesario asegurarse que cad1 sea lo suficientemente grande como para mantener su contenido original y el de cad2.

int strncmp(char *cad1,char *cad2, unsigned int cuenta) Esta función compara lexicográficamente un máximo de cuenta caracteres de las dos cadenas terminadas con un caracter nulo y devuelve un entero cuyo significado se presenta a continuación:

Valor             Interpretación

Menos que 0 cad1 es menor que cad2

0                   cad1 es iguala cad2

Mayor que 0 cad1 es mayor que cad2

char *strncpy(char *cad1,char *cad2, unsigned int cuenta) copia cuenta caracteres de la cadena apuntada por cad2 en la cadena apuntada por cad1 . El elemento cad2 debe de tener un caracter final de cadena nulo. La función devuelve un puntero a cad1.

Los caracteres nulos al final, indican el final de la cadena.

Si cad1 y cad2 se solapan, el comportamiento destrncpy() está indefinido. Si la cadena apuntada por cad2 contiene menos caracteres que los indicados por cuenta, se añaden caracteres nulos al final de cad1 hasta que se copie cuenta caracteres. En cambio, si la cadena apuntada por cad2 es mayor que cuenta, la cadena resultante apuntada por cad1 no tiene caracter nulo de terminación.

char strpbrk(char *cad1, char *cad2) compara caracter a caracter de cad1 con cad2 y devuelve un puntero al primer caracter de la cadenas que se correspondan (sean los mismos). El caracter nulo de terminación no se incluye. Si no hay correspondencia se devuelve un puntero nulo.

char *strrchr(char *cad, int ch) devuelve un puntero a la última ocurrencia del byte menos significativo de ch en la cadena apuntada por cad o un puntero nulo si no se encuentra.

int strspn(char *cad1, char *cad2) Esta función devuelve la longitud de la sub cadena inicial apuntada por cad1 que está constituida sólo por aquellos caracteres contenidos en la cadena apuntada por cad2. Es decir, strspn()devuelve el índice del primer caracter en la cadena apuntada por cad1 que no se corresponde con ningún caracter de la cadena apuntada por cad2.

char *strstr(char *cad1,char *cad2) devuelve un puntero a la dirección de la primera ocurrencia en la cadena apuntada por cad1 de la cadena apuntada por cad2 excepto el caracter nulo de terminación decad2. Si no la encuentra, devuelve un puntero nulo.

char *strtok(char *cad1, char *cad2) Esta función devuelve un puntero a la siguiente palabra de la cadena apuntada por cad1. Los caracteres que constituyen la cadena apuntada por cad2 son los delimitadores que identifican la palabra. Se devuelve un puntero nulo cuando no existe ninguna palabra que devolver.

La primera vez que se llama a strtok(), cad1 se utiliza realmente en la llamada. Las llamadas posteriores utilizan un puntero nulo para el primer argumento. De esta forma, la cadena completa se puede reducir a sus palabras.

Es importante entender que esta función modifica la cadena apuntada por cad1. Cada vez que se encuentra una palabra se pone un carácter nulo donde estaba el delimitador. De esta forma, strtok() puede continuar avanzando por la cadena. Nótese que la cadena inicial es, por tanto, destruida.

Es posible utilizar un conjunto diferente de delimitadores para cada llamada strtok().

int tolower(int ch) Mediante esta función se regresa el equivalente en minúsculas de ch si ch es una letra; en cualquier otro caso devuelve ch sin modificar.

int toupper(int ch) devuelve la mayúscula de ch si ch es una letra; en cualquier otro, devuelve ch sin modificar.

 


OTRAS FUNCIONES)

 

#include<assert.h>

void assert(exp) /* exp es cualquier expresión válida en C*/ escribe la información de error en stderr y entonces aborta la ejecución del programa si la expresión exp tiene el valor de cero. En cualquier otro caso, assert() no hace nada.

·       La macro assert() se utiliza normalmente para ayudar a verificar que un programa opera correctamente. La expresión se dispone de modo que se evalúe a true (regrese un valor diferente de cero) sólo cuando no han tenido lugar errores.

·       No es necesario eliminar las sentencias assert() del código fuente una vez que el programa se haya depurado, ya que si la macro NDEBUG aparece definida (como cualquier otra) entonces las macros assert() son ignoradas.

 

(include<stdlib.h>

void abort()da lugar a la terminación auto-mática del programa. Ningún archivo es volcado. En entornos que lo soportan, abort() devuelve un valor definido por la aplicación al proceso que haya hecho la llamada (normalmente el sistema operativo). Su uso principal es prevenir una fuga del programa cerrando los archivos activos.

int abs(int num) devuelve el valor absoluto del entero num.

int atexit(func)                 void (*func)();

La función atexit() fija la función apuntada por func como la función a ser llamada una vez alcanzada la terminación normal del programa.

La función atexit() devuelve cero si la función queda establecida como función de terminación; en cualquier otro caso devuelve un valor distinto de cero.

·       El estándar ANSI propuesto especifica que al menos se pueden fijar32 funciones de terminación siendo llamadas en orden inverso al de su establecimiento. En otras palabras, la naturaleza del proceso de registro es como una pila.

·       La función atexit() se llama algunas veces onexit()por compiladores que desvían ligeramente del estándar propuesto.

double atof(char *cad Esta función devuelve la cadena apuntada por cad a un valor de tipo double. La cadena debe tener un número válido en punto flotante. Esto incluye espacios en blanco, signos de puntuación distintos del punto, y caracteres que no sean E o e. esto supone que si atof()se llama con la cadena "100.00HOLA" se devuelve el valor 100.00.

int atoi(char *cad) convierte la cadena apuntada por cad a un valor int. La cadena debe contener un número entero válido. Si este no es el caso, el valor devuelto queda indefinido.

·       El número puede acabar con cualquier caracter que no forme parte de un número entero. Esto incluye espacios en blanco, signos de puntuación y otros que no sean dígitos. Esto supone que si atoi() se llama con 123.23 se devuelve el valor entero 123 y el .23se ignora.

int atol(char *cad) convierte la cadena apuntada por cad aun valor long int. La cadena debe contener un número entero de tipo long válido. Si no es este el caso, el valor devuelto queda indefinido.

·       El número puede acabar con cualquier caracter que no forme parte de un número entero. Esto incluye espacios en blanco, signos de puntuación y otros que no sean dígitos. Esto supone que si atol() se llama con 123.23 se devuelve el valor entero 123 y el .23se ignora.

void *bsearch(void*clave, void *base, unsigned int num, unsigned int tam, int (*compara)(); La función bsearch() realiza una búsqueda binaria en un arreglo ordenado donde clave es el objeto a buscar, base es un puntero al primer elemento del arreglo. El número de elementos en el arreglo está especificado por num y el tamaño (en bytes)de cada elemento está descrito en tam. La función apuntada compara se utiliza para comparar un elemento del arreglo con la clave. La forma de la función de comparación debe ser .

compara(void *elemento1,void *elemento2)

Debe devolver los siguientes valores:

Si elemento1 es menor que elemento2, devuelve un valor menor que cero.

Si elemento1 es igual que elemento2, devuelve cero.

Si elemento1 es mayor que elemento2, devuelve un valor mayor que cero.

·       El arreglo debe estar ordenado en orden ascendente con la menor dirección conteniendo al elemento más pequeño. Si el arreglo no contiene la clave, se devuelve un puntero nulo.

·       La mayor parte de los compiladores que no son completamente compatibles con el estándar ANSI propuesto, sustituyen los punteros void por punteros char en esta definición y usan un molde de tipo cuando trabajan con otros tipos de datos.

void exit(int estado) da lugar inmediatamente a la terminación normal de un programa. El valor de estado se pasa al proceso de llamada - normalmente el sistema operativo- si el entorno lo soporta. Por convenio, el valor de estado es 0, cuando se ha producido una terminación normal del programa. Un valor distinto de cero puede utilizarse para indicar un error definido por la aplicación.

div_t div(int numer, int denom) devuelve el cociente y el resto de la operación numer/denom. El tipo de estructura div_t está definido en stdlib.h y tiene al menos estos dos campos:

int quot; /*el cociente*/

int rem /*el resto*/

int itoa( int num, char cad, int radix) convierte el entero num a su cadena equivalente y sitúa el resultado en la cadena apuntada por cad. La base de la cadena de salida se determina por radix, que se encuentra normalmente en el rango 2 a 16.

La función itoa devuelve un puntero a cad. Generalmente no devuelve valor de error. Asegúrese al llamar a itoa() que la cadena es lo suficientemente grande como para contener el resultado transformado.

Su uso principal es convertir tipos de datos enteros a cadenas de modo que pueden ser enviados a un dispositivo no soportado directamente por el sistema de E/S usual de C - es decir, a un dispositivo no de flujo -. Lo mismo se puede utilizar con printf().

long labs(long num) Al ejecutar esta función labs() se devuelve el valor absoluto de num, un long int.

ldiv_t ldiv(long int numer, long int denom) Devuelve el cociente y el resto de la operación numer/denom que son números enteros de tipo long.

El tipo de estructura ldiv_t está definido en stdlib.h y tiene al menos estos dos campos:

int quot; /*el cociente*/

int rem /*el resto*/

int ltoa( int long num, char cad, int radix) convierte el entero num de tipo long a su cadena equivalente y sitúa el resultado en la cadena apuntada por cad. La base de la cadena de salida se determina por radix, que se encuentra normalmente en el rango 2 a 16.

La función ltoa() devuelve un puntero a cad. Generalmente no devuelve valor de error. Asegúrese al llamar a ltoa() que la cadena es lo suficientemente grande como para contener el resultado transformado.

Su uso principal es transformar enteros en cadenas de modo que pueden ser enviados a un dispositivo no soportado directamente por el sistema de E/S usual de C - es decir, a un dispositivo de no flujo-. Lo mismo se puede utilizar con printf().

void perror(char *cad) proyecta el valor de la variable global errno en una cadena y escribe esta cadena en stderr. Si el valor de cad no es nulo, la cadena se escribe primero seguida de dos puntos, y después por el propio mensaje de error.

void qsort(base, num, tam,(compara))

void *base;

unsigned int num, tam;

int (*compara)(elemento1,elemento2);

const void *elemento1;

const void *elemento2;

Esta función ordena un arreglo, utilizando el algoritmo de ordenación quic-ksort. Esta función no retorna valor alguno.

·       La variable base es un puntero al primer elemento de un arreglo. num es el número de elementos del arreglo. bytes es la longitud en bytes de un elemento.

·       compara es un puntero a una función definida por el usuario, que compara dos elementos y retorna valor: Si elemento1 es menor que elemento2 devuelve un valor menor que cero. Si elemento1 es igual a elemento2 devuelve cero. Si elemento1 es mayor que elemento2 devuelve un valor mayor que cero.

·       El arreglo es ordenado en forma ascendente con la dirección más pequeña conteniendo el menor elemento.

·       Se sustituyen por punteros de tipo char los punteros de tipo void en los compiladores que no son totalmente compatibles con el compilador estándar.

int rand() genera un flujo de números pseudo aleatorios. Cada vez que se llama, se devuelve un entero entre 0 y RAND_MAX.

 

void srand(unsigned int semilla) utiliza semilla para fijar un punto de partida para el flujo generado por rand(), que devuelve números pseudo aleatorios.

La función srand() se utiliza normalmente para permitir que ejecuciones múltiples de un programa utilicen diferentes flujos de números pseudo aleatorios.

long int strtol(char *ini, char *fin, int radix) Convierte la representación en cadena de caracteres de un número- almacenada en la cadena apuntada por ini- en un número de tipo long int y devuelve el resultado. La base del número está determinada por radix. Si radix es 0, debe estar en el rango de 2 a 36.

La función strtol() trabaja de la siguiente forma: primero elimina cualquier espacio en blanco de la cadena apuntada por ini. A continuación, se lee cada uno de los caracteres que constituyen el número . Cualquier caracter que no pueda formar parte de un número de tipo long int finaliza el proceso. Por último, fin se deja apuntando al resto, si lo hay, de la cadena original. Esto supone que si strtol() se llama con 100.000 pliers, se devuelve el valor de 100L y fin apunta al espacio que precede a pliers.

Si se produce un error de conversión, strtol() devuelve LONG_MAX para desbordamiento o LONG_MIN para desbordamiento por abajo. Si no se produce la conversión, se devuelve cero.

unsigned long int strtoul(char *ini, char *fin, int radix) Convierte la representación en cadena de caracteres de un número- almacenada en la cadena apuntada por ini- en un número de tipo long int y devuelve el resultado. La base del número está determinada por radix. Si radix es 0, la base viene determinada por las reglas que gobiernan la especificación de constantes. Si radix está especificada, debe estar en el rango de 2 a 36.

La función strtoul() trabaja de la siguiente forma: primero elimina cualquier espacio en blanco de la cadena apuntada por ini. A continuación, se lee cada uno de los caracteres que constituyen el número . Cualquier caracter que no pueda formar parte de un unsigned long int da lugar a que el proceso se detenga. Esto incluye espacios en blanco, puntuación y caracteres. Finalmente, fin se deja apuntando al resto, si lo hay, de la cadena original. Esto supone que si strtoul() se llama con 100.000 pliers, se devuelve el valor de 100L y fin apunta al espacio que precede a pliers.

Si se produce un error de conversión, strtoul() devuelve ULONG_MAX para desbordamiento o ULONG_MIN para desbordamiento por abajo. Si no se produce la conversión, se devuelve cero.

int system(char *cad) pasa la cadena apuntada por cad como una orden al procesador de órdenes del sistema operativo. El system() se llama con un puntero nulo, devuelve un valor distinto de cero si está presente un procesador de órdenes; en cualquier otro caso devuelve 0. Esta función devuelve cero si fue completamente ejecutada; en cualquier otro caso devuelve un valor distinto de cero.


Programa ejemplo

El siguiente programa, contiene una función que valida que únicamente se lean números enteros y otra que sólo reciba letras.

#include <stdio.h>

#include<string.h>

 

void main()

{

 int cifra;

 char word[20];

 clrscr();

 

 switch(menu())

 {

  case 1: cifra=numeros();

        printf("\n%d",cifra);

        break;

  case 2: captura(word);

        printf("\n%s",word);

        break;

  default: exit(0);

 }

 

getch();

}

 

captura(char palabra[])

{

 char *letra;

 char alfabeto[]="ABCDEFGHIJKLMN¥OPQRSTUVWXYZabcdefghijklmnñopqrstuvwxyz";

 int i;

 

 palabra[0]='\0';

 clrscr();

 

 do

 {

   *letra=getch();

  for (i=0;i<=53;i++)

   {

     if (alfabeto[i]==*letra)

    {

       printf("%c",*letra);

      strcat(palabra,letra);

        break;

     }

    }

 }while((*letra!=13) && (strlen(palabra)<20));

}

 

numeros()

{

char cadena[10];

 char car='\0';

int i=0;

 int cantidad;

 do

 {

   car=getch();

   switch(car)

   {

     case'0': cadena[i]=car;

          printf("%c",car);

          break;

     case'1': cadena[i]=car;

        printf("%c",car);

          break;

     case'2': cadena[i]=car;

          printf("%c",car);

          break;

     case'3': cadena[i]=car;

        printf("%c",car);

          break;

     case'4': cadena[i]=car;

          printf("%c",car);

          break;

     case'5': cadena[i]=car;

          printf("%c",car);

          break;

     case'6': cadena[i]=car;

         printf("%c",car);

          break;

     case'7': cadena[i]=car;

          printf("%c",car);

          break;

     case'8': cadena[i]=car;

          printf("%c",car);

          break;

     case'9': cadena[i]=car;

          printf("%c",car);

          break;

      default: i--;

         break;

   }

  i++;

 }while((car!=13) && (i<5));

    cantidad=atoi(cadena);

    return(cantidad);

 }

menu()

 

{

  int numero;

  printf("Escoge una opción:\n");

  printf("1.Escribir sólo números\n");

  printf("2.Escribir únicamenteletras\n");

  printf("Opción: ");

  scanf(" %d",&numero);

  return(numero);

}

 


En los arreglos con tamaño, se tiene que calcular que la longitud del arreglo sea lo suficientemente grande para que fueran almacenados todos los elementos que se desean. Si se tuviéra que inicializar varios arreglos de cadena seria fastidioso contar cuantos caracteres ocupa cada arreglo.

 

Es posible que C calcule automáticamente la longitud del arreglo utilizando la inicialización de arreglos indeterminados la cual permite que el compilador de C cree automáticamente un arreglo suficientemente grande para mantener todos los inicializadores presentes si el tamaño del arreglo no está especificado.

 

El uso de la inicialización de los arreglos indeterminados permite al programador cambiar el contenido de cualquiera de las cadenas sin tener que reconsiderar el tamaño del arreglo. También puede utilizarse en arreglos multidimensionales. En este caso, se debe especificar todo, sin considerar la dimensión que se encuentra más a la izquierda para permitir al compilador de C indexar el arreglo adecuadamente. El método es similar a la especificación de parámetros de un arreglo. De este modo se pueden construir tablas de longitudes variables, y el compilador asignará automáticamente el espacio suficiente para ellas.

 

La ventaja de este tipo de declaración sobre la versión del tamaño determinado es que la tabla puede alargarse o acortarse sin cambiar las dimensiones del arreglo.

 


Éste tipo de arreglos se utiliza principalmente para mantener punteros a mensajes de error.

Por ejemplo, podemos crear una función que muestre un mensaje de error determinado y su número correspondiente.

 

    error(int numero)

   {

       static char*err[]={

       "Errorde punto flotante\n",

       "Errorde sintaxis\n",

       "Número demasiado pequeño\n",

       "Númerodemasiado grande\n"

        };

printf("Error %d: %s" número, err[numero]);

   }

 

 

La función anterior recibe un entero como parámetro. Este indica el número de elemento del array que contiene el apuntador al primer elemento de la cadena de caracteres que corresponde. Tanto el número de error (número de elemento) como su mensaje de error correspondiente se presentan en pantalla.

 

Un puntero a puntero es una forma de indirección múltiple, o un encadenamiento de punteros. Sabemos que un puntero es una variable que contiene la dirección de un valor determinado. Un puntero a puntero es una variable que contiene la dirección del lugar que contiene la dirección de una variable.

 

Una variable que es un puntero a puntero tiene que declararse como tal. Esto se hace colocando un * adicional del lado izquierdo del nombre dela variable. Por ejemplo:

 

  double ** tolerancia;

 

Esta declaración le indica al compilador que la variable tolerancia es un puntero a un puntero que contiene la dirección de una variable de tipo double.

 

Veamos un ejemplo:

 

   main()

   {

     int n,*p,**q;

 

       n=5;

       p=&n;

     q=&p;

 

      printf("%d",**q) /*imprimireel valor de x*/

    }

 

Aquí, n está declarado como un entero, p como un puntero a entero y q como un puntero a puntero a entero. Las asignaciones de la función nos d n una idea de como se relacionan las tres variables entre si: El contenido de la variable n es 5; a su vez, asignamos al puntero p la dirección de la variable que contiene ese número. Finalmente, como q es un puntero a un puntero, sólo puede contener direcciones por tanto, guarda la dirección de la variable donde se encuentra el valor de la dirección donde se encuentra el 5.

 

Mediante la llamada a printf() comprobamos lo dicho, ya que despliega el contenido de número a pesar de que es llamado desde una variable puntero a puntero.

 

Problemas con punteros

Utilizar punteros dentro de la programación es necesario en la implementación de algunos programas. Por ahora, no te preocupes sino encuentras el uso práctico de esta herramienta. Conforme vayas dominando tanto la programación como el lenguaje C, te dar s cuenta de las formas en que puedas aplicarlo. Sin embargo, es muy fácil cometer errores al utilizarlos ya que nada da más problemas que un puntero descontrolado.

 

Un puntero erróneo es difícil de encontrar porque el problema es que cada vez que se realiza una operación utilizando ese puntero, se está leyendo o escribiendo en algún lugar desconocido de la memoria. Si se leé de él, lo peor que puede ocurrir es que se obtenga basura. Sin embargo, si se escribe en él, se est  escribiendo en otras partes de código o datos. El hecho de estar perdiendo datos, puede hacerse evidente hasta la ejecución del programa, y los datos perdidos pueden llegar a ver el fallo en un lugar erróneo. Puede haber poca o ninguna evidencia de que el puntero sea el problema. Este tipo de errores hace que los programadores pierdan el sueño y el tiempo una y otra vez.

 

Lo mejor para evitar este tipo de errores, es prevenirlos. En esta sección te mostramos los errores m s frecuentes que se cometen en la utilización de punteros:

 

Puntero no inicializado

 

Se incurre en este error, cuando se utiliza un puntero antes de haberlo inicializado. Veamos un ejemplo:

 

    main() /*Este programa est incorrecto*/

    {

      char l, *p;

 

      l='m';

    *p=l; 

    }

 

El problema en este programa es que se est  asignando 'm' a alguna posición de memoria desconocida ya que el puntero p nunca fué inicializado. Como consecuencia, el programa se para . La solución para evitar este tipo de contratiempos es asegurar siempre que el puntero esté apuntando a alguna dirección v lida antes de usarlo.

 

Error en la utilización de punteros

 

Este tipo de error se suscita cuando no se utilizan correctamente los operadores* o &.

 

 main() /*Este programa es erróneo*/

 {

   int n, *p;

   n=10;

   p=n;

   printf("%d",*p);

 }

 

 

La llamada a printf() no imprime el valor de n en la pantalla sino un valor desconocido ya que la asignación p=x; es incorrecta. Esta sentencia asigna el valor 10 al puntero p, aquí es donde se comete el error ya que un puntero sólo puede recibir direcciones. Para corregir el programa se escribir   p=&x.>

 

El utilizar punteros, no quiere decir que vayas a tener problemas con ellos en tu programa. De hecho, cualquier tipo de datos o estructura puede producir errores si no est  bien estructurada tanto sintáctica como lógicamente. Por tanto, sólo hay que tener cuidado, y asegurarse de saber a donde apunta cada puntero antes de usarlo.

 

Hosted by www.Geocities.ws

1