Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
ÍNDICE:
1
4.01.- Introducción al lenguaje C.
El lenguaje C fue desarrollado por Dennis Ritchie a principios de la década de los setenta (1972) en
los laboratorios Bell Telephone. Es el resultado de dos lenguajes anteriores, el B creado por Ken
Thompson en el mismo laboratorio y basado a su vez en el BCPL creado por Martin Richard en la
universidad de Cambridge. Debido a su popularidad, los compiladores de este lenguaje (programas
que convierten el lenguaje C en código máquina) difieren levemente de la definición original. Por ello
el Instituto Nacional Americano de Stándares ANSI con el objetivo de poner orden y proporcionar un
lenguaje aceptados por todos, establece las normas ANSI para C. Aun así, los distintos compiladores,
pueden ofrecer características propias añadidas a este estándar.
Esto es debido a que este lenguaje está pensado para ello. La manipulación de bits, bytes,
direcciones, archivos, creación de rutinas adaptadas a cada tipo de ordenador denominadas funciones
...etc.
Derivado de esta última propiedad, los programas fuentes escritos en C tienen una gran
portabilidad (en este caso podemos definirlo como propiedad de compilar un programa fuente en
equipos distintos) ya que deja en manos de las funciones de biblioteca la mayoría de las características
que dependen de la computadora.
Los intérpretes y compiladores son programas que ejecutan códigos o programas fuentes
escritos en un lenguaje determinado. Es decir si por ejemplo escribimos un programa fuente en Basic o
en C este programa puede ser ejecutado en nuestro PC bien por un programa compilador o bien por un
programa intérprete.
Un programa intérprete lee línea a línea el código fuente y lleva a cabo las instrucciones
específicas en ellas contenidas. Luego para ejecutar nuestro código fuente tendremos por fuerza que
estar dentro del programa intérprete.
Por contra un programa compilador, coge este código fuente y lo traduce por completo a
código máquina, dando como resultado un programa ejecutable con extensión exe y por lo tanto
pudiéndose ejecutar sin necesidad ya del compilador.
Por último podemos decir que durante la realización de un programa extenso, es más cómodo
el trabajar con un intérprete, pero una vez obtenido el texto fuente ya depurado y funcionando
correctamente, necesitaremos de un programa compilador que nos lo traduzca a código máquina por
entero obteniendo ya el programa ejecutable.
2
Linkado: Si el código fuente utiliza, como es corriente en C, funciones de biblioteca, (estas son
pequeños programas ya compilados que realizan una acción concreta, suministradas estas funciones
por los distintos programas compiladores) después del proceso de compilado se realiza el linkado
donde el programa traducido se ensambla con las distintas funciones utilizadas en él. El programa
traducido a código máquina sin ensamblar toma la extensión obj y después de linkarse, la extensión
exe.
OPERACIÓN
P
B) Operaciones de transferencia entrada/salida:
ENTRADA/SALIDA
3
C) Símbolo de toma de decisión:
NO ¿CONDICIÓN
CUMPLIDA?
SI
E) Símbolo de conexión:
Muchas veces un ordinograma no cabe en una
sola hoja. Por ello, es necesario utilizar este símbolo
para conexión de ordinogramas parciales. En el 3
interior del círculo se indica el mismo número para
indicar que estos puntos están unidos.
INI
F) Símbolo de comienzo o de fin de proceso:
FIN
4
4.01.2. Identificadores y palabras claves.
Todos los programas escritos en C se estructuran en distintas funciones, una de las cuales ha de
llamarse de manera obligada main(), si el programa sólo consta de una función, esta deberá llamarse
así.
Toda función debe tener un nombre (que debe cumplir la regla de los identificadores), unos
argumentos encerrados entre paréntesis y si no tiene argumentos estos paréntesis deben de aparecer de
una manera obligada y a continuación aparecerá lo que es el cuerpo de la función encerrado este entre
llaves.
En la primera, ordenamos al compilador que compile antes de nuestro archivo fuente, el archivo
stdio.h correspondiente a una serie de funciones estandares de entrada/salida de datos en pantalla y
teclado(Standard Input/Ouput) y que se utilizarán en el programa. Las dos líneas indican lo mismo con
la salvedad de que en la primera línea se indica mediante las dobles comillas que el archivo de
cabecera está en el mismo subdirector de trabajo, mientras que en la segunda línea se indica mediante
los símbolos < y > que el archivo en cuestión se halla dentro del subdirector especificado en el
compilador, denominado normalmente include.
Esta orden servirá por lo tanto para compilar dos archivos fuente cualesquiera, es decir si
tuviésemos dos archivos fuentes, por ejemplo arc1.c y arc2.c si incluyésemos en el archivo segundo la
5
orden #include"arc1.c" y compilásemos el segundo archivo, se habría compilado el primero y a
continuación el segundo dando como resultado un único archivo de salida denominado arc2.exe.
Es de señalar que esta orden debe de empezar obligatoriamente con el símbolo de almohadilla
# y al contrario de casi todas las ordenes o declaraciones no termina en punto y coma.
Cada archivo de cabecera tiene asociada una serie de funciones de biblioteca, si se utiliza en el
programa alguna de ellas, este archivo deberá incluirse de la forma ya vista. Por ejemplo, en el
ejemplo siguiente se utilizan las funciones printf() y scanf() siendo necesario incluir el archivo de
cabecera stdio.h.
/* PROGRAMA DE EJEMPLO
*************************** */
#include<stdio.h>
int main(void) //void indica vacía, es decir, función que no acepta ningún valor
{
float a,r; //declaración de variable
printf("escribe un nº positivo menor de 1000\n"); //llamada a la función de escritura en pantalla
fflush(stdin);//limpia el teclado
getchar(): //espera la pulsación de un intro
return 0; //devuelve el valor cero al sistema indicando que se ha cerrado correctamente
}
/* PROGRAMA DE EJEMPLO
*************************** */
#define PI 3.141593
int main(void) //void indica vacía, es decir, función que no acepta ningún valor
{
6
float long, r; //declaración de variable
printf("Introduce el radio de la circunferencia=");
scanf("%f",&r); //captura el valor escrito y lo asigna a r
long=2*PI*r;
printf("\n La longitud de la circunferencia es=%f",longr);//imprime en pantalla el valor de long
printf("\n-------Fin ----------“);// el símbolo \n realiza un salto de línea en la pantalla
Delay(1);//espera 1 segundo
return 0; //devuelve el valor cero al sistema indicando que se ha cerrado correctamente
}
7
4.02.- Entorno gráfico del CVI.
LabWindows/CVI es un entorno de desarrollo integrado para programadores en lenguaje C. Se
basa fundamentalmente en un entorno interactivo para desarrollo de programas y una librerías de
funciones para crear aplicaciones de adquisición de datos y control de instrumentos.
LabWindows/CVI contiene además un conjunto de herramientas software para la adquisición, análisis
y presentación.
Para utilizar LabWindows/CVI, el programador no necesita ser un experto conocedor de técnicas
avanzadas de programación ni de los detalles internos del sistema operativo Windows.
Como ventajas a versiones anteriores, decir, que LabWindows/CVI contiene la especificación del
lenguaje ANSI C, lo que proporciona máxima flexibilidad a la hora de desarrollar aplicaciones.
Las herramientas que básicamente forman este entorno de desarrollo y que iremos describiendo a lo
largo de este tema son las siguientes:
La clave de la potencia de LabWindows/CVI está en sus librerías que proporcionan funciones para
todas las fases del desarrollo de una aplicación de adquisición de datos o de control de
instrumentación. Así tenemos:
1. Cinco librerías para adquisición de datos: Instrument library, GPIB/GPIB 488.2 library,
Data Acquisition library, RS232 library y VXI library.
2. Dos librerías para análisis de datos: Formatting and I/O library y Advanced Analysis
library.
5. Dos librerías para redes y comunicación entre procesos: Dinamic Data Exchange (DDE)
library y Transmission Control Protocol (TCP) library.
Además, tal y como se comentó anteriormente, la librería completa ANSI C también está integrada en
el entorno de desarrollo de LabWindows/CVI.
8
En el entorno de LabWindows/CVI se trabaja por proyectos, para ello es conveniente crear una carpeta
donde guardar dicho proyecto:
En la pantalla de bienvenida, podemos
abrir un proyecto o crear uno nuevo,
aparte podemos ver algunos ejemplos o
consultar información acerca del
programa.
Primero: crearemos una carpeta, p.e. en mis documentos a la que llamaremos EJEMPLO 1 y en la
pantalla de bienvenida elegiremos New Proyect (nuevo proyecto)
9
Nuestra aplicación estará formada por varios archivos, uno de ellos será el que contiene el código
fuente de la aplicación (*.c), otro será el que contiene la información sobre las funciones gráficas
utilizadas (*.uir), y otro archivo que contiene información sobre el espacio de trabajo y archivos que
componen el proyecto (*.cws). El
archivo que relaciona a todos será
(*.prj).
10
Insertándose en el editor las siguientes
líneas:
#include <cvirte.h>
int main ()
{
int cont;
char a;
printf(“HOLA MUNDO”);
El siguiente paso será ejecutar dicho programa, para ello pulsaremos Run/Debug Ejercicio1dbg.exe
O pulsando el icono
#include <ansi_c.h>
Este ejercicio simple, nos muestra en pantalla el código ASCII mediante el cual, se almacenan en
formato binario los caracteres alfabéticos de los distintos idiomas más extendidos.
Para ello hemos utilizado un bucle for y la función printf( ) reconocidos por el estándar ANSI
11
4.03.- Variables y tipos de datos.
Los diferentes variables a utilizar en un programa escrito en C, se declaran al principio del
mismo, acabándose siempre en punto y coma, por ejemplo:
char a;
Esta declaración significa que a será una variable que almacenará un dato tipo char.
Los tipos de datos se diferencian en el número de bytes que reservarán para su
almacenamiento, es decir un tipo de datos por ejemplo char se almacena en un byte (8 bits) y sólo
podrá contener 256 números distintos (2 elevado a 8) comprendidos entre 0 y 255, pensado este tipo
para almacenar números correspondientes a caracteres alfanuméricos, de control o símbolos gráficos.
Esta correspondencia la establece la tabla de codificación que nuestro ordenador utilice siendo la más
usual en PC la tabla ASCII. Es decir si queremos almacenar el carácter a en una posición determinada
de memoria, se almacenará el número ASCII correspondiente que en el caso del carácter a
corresponde al 97 evidentemente escrito en binario (1100001).
12
Como ya hemos mencionado, una variable de tipo char se almacena en un byte (8 bits) y sólo
se puede almacenar 256 números distintos en un byte, comprendidos entre 0 (0000 0000) y 255 (1111
1111), pudiendo así contener cualquier número asignado por la tabla ASCII a cada carácter, símbolos
o códigos de control.
Como vemos en estos ejemplos, al igual que se definen las variables a utilizar en el programa,
podemos darles inicialmente algún valor si ello nos interesa.
En las variables de tipo char (carácter) podemos almacenar números desde -128 a 127, pero si
lo que queremos es guardar un carácter, tendremos que poner este entre comillas simples, que es la
forma de decirle al compilador que debe transformar este carácter el su código ASCII correspondiente
Es decir si escribimos char t=’5’; se guardará en el cajón denominado t el valor del código
ASCII correspondiente a 5 que es el número 53 (00110101 en binario).
Por contra, si escribimos char=5; se guardará en t el numero 5 (000000101 en binario).
4-13
4.04.- Cadena de caracteres.
Primero: si estas cadenas se tuviesen que escribir en la pantalla, las secuencias de escape( \n \t \” \xa7
etc ) se ejecutan pero no se escriben (con algunas excepciones, por ejemplo si quisiéramos utilizar
dobles comillas, estas se escribirán como secuencia de escape para no ser confundidas por el
compilador como apertura y cierre de una cadena)
4-14
letra='a';
putchar(letra);
getchar();
return 0;
}
Un array es una variable que puede almacenar un conjunto de datos de idéntico tipo. Es decir
podemos definir arrays de caracteres, de números enteros o de coma flotante (más adelante se dedica
un tema exclusivamente a los arrays ya que estos podrán ser multidimensionales y almacenar no sólo a
caracteres sino a cadena de caracteres)
ejemplo:
char a[10];
char texto[8]="Sevilla";
char texto[8]={’S’,’e’,’v’,’i’,’l’,’l’,’a’,’\0’}
char nombre[]="España"; (la manera más cómoda)
int num[4];
int num[]={3,45,678,21}; (array de 4 números int)
long int numeros[57];
float res_cuentas[5]={0.034,45,67,23,0.98};
Quedando el resto de las casillas o cajones con el número 0. A continuación vemos algunos
ejemplos:
Ejemplo 1:
#include<ansi_c.h>
int main(void)
{
int cont,a[5]={2,3,4}; //rellenamos las tres primeras casillas o registros
for(cont=0 ; cont<5 ; ++cont) printf("\n a[cont]=%d",a[cont]);
4-15
fflush(stdin);//limpia el buffer del teclado
getchar();
return 0;
}
Ejemplo 2:
#include <ansi_c.h>
int main (void)
{
int cont;
char a[]="ESPAñA";
a[4]=165;
puts(a);
fflush(stdin);//limpia el teclado
getchar();
return 0;
}
char a[10];
int num[4];
int num[4];
long int numeros[57];
En todas ellas se expresa la capacidad del array.
Los elementos de un array se numeran desde 0 a n-1 siendo n el número que expresa la
capacidad del array.
ejemplo:
char ciu[]="Malaga";
M a l a g a \0
ciu[0] ciu[1] ciu[2] ciu[3] ciu[4] ciu[5] ciu[6]
luego para un array denominado "ciu" de 7 elementos, estos irán desde ciu[0] a ciu[6].
Se podrá operar con cualquier elemento de un array de una forma individual, por ejemplo si
tenemos dos arrays de 4 numeros enteros denominados a y b, podremos realizar cualquier operación
con cualquier elemento de ambos:
int a[]={7,8,9,34};
int b[]={45,10,12,30};
4-16
podremos en cualquier parte del programa procesar cualquiera de estos elementos
individualmente, es decir:
c=a[0]+a[3]; (c tomará el valor 7+34=41)
d=a[2]-b[0]; (d tomará el valor 9-45=-36)
#include <ansi_c.h>
int main (void)
{
int x,y,suma;
x=3;
y=10;
suma=x+y;
printf("suma=%d",suma);
getchar();
return 0;
}
Ejemplo 2:
#include <ansi_c.h>
int main (void)
{
int x,y,resto;
x=3;
y=10;
resto=y%x;
4-17
printf("resto=%d",resto);
getchar();
return 0;
}
Para el resto de operaciones matemáticas se pueden utilizar funciones matemáticas de biblioteca para
lo cual deberemos incluir como archivo de cabecera math.h .
Ejemplo:
#include<stdio.h>
#include<math.h>
int main(int argc, char *argv[]){
double a=34,b=12,resultado;
resultado=pow(a,b);
printf("a elevado a b=%lf",resultado);
return 0;
}
(En la primera línea de programa se declaran las variables a y b como tipo int asignándoles
además un valor.
En la segunda línea se declara la variable resultado como tipo float.
En la tercera, se utiliza la función de biblioteca pow(x,y) contenida en los archivos de librerías
math.lib y cuyo archivo de cabecera math.h es necesario incluir al principio del programa.
En la cuarta línea se presenta el valor de la variable resultado, llamando a esta mediante %lf
El operador % (resto de división entera) sólo se empleará con números enteros o variables de
tipo int, ya que si operamos con números decimales, esta no parece muy lógica. El resto de operadores
son utilizables con todo tipo de números o variables.
Otro modo de expresar operaciones algebraicas de una manera más concisa es la siguiente:
a+=100; equivale a: a=a+100;
x-=z; equivale a: x=x-z;
a*=50-b; equivale a: a=a*(50-b);
precio/=coste; equivale a: precio=precio/coste;
El operador sizeof (tamaño de) que indicará el número de bytes reservados por un número o
variable, por ejemplo:
4-18
int a,t;
t=sizeof a;
t tendrá el valor de 2, correspondiente al número de bytes reservados para un número int).
También se puede utilizar de la siguiente manera:
int x,y,z,u,v;
x=sizeof(char); // almacenará 1
y=sizeof(int); // almacenará 2 ó 4 bytes
z=sizeof(long int);
u=sizeof(float) /* almacenará 4
v=sizeof(double) /* almacenará 8
printf("\n el tipo char reservara=%d bytes",x);
printf("\n int =%d",y);
printf("\n long int=%d",z);
printf("\n float=%d",u);
printf("\n double=%d",v);
4-19
#include <ansi_c.h>
#include <cvirte.h>
x=a<b;
printf("valor de x=%d=",x);
while(getchar()!='\n';//equivale a fflush(stdin)
getchar();
Cls();//limpia la pantalla
fflush(stdin)//limpia el buffer del teclado
return 0;
}
4-20
#include <ansi_c.h>
#include <cvirte.h>
La función gets() sirve para capturar una cadena de caracteres (alfanuméricos) y la función
puts() para mostrar una cadena en pantalla. Ejemplo:
#include <ansi_c.h>
#include <cvirte.h>
char linea[80];
gets(linea);
puts(linea);
getchar();
return 0;
}
gets(linea) capturará la cadena escrita hasta 80 caracteres o hasta que pulsemos enter. La sentencia
puts(linea); presentará en pantalla a dicha cadena.
La función printf() se utiliza para la escritura en pantalla de cualquier valor numérico, carácter
o cadena de caracteres. Se puede denominar como una salida de datos con formato. Su expresión
general es la siguiente:
#include <ansi_c.h>
4-21
#include <cvirte.h>
char palabra[10];
float num_dec;
int ent;
printf(« Escribe una palabra, un numero entero y un numero con decimales\n") ;
scanf("%s %d %f",palabra,&ent,&num_dec);
printf("palabra=%s entero=%d numero con dec=%f",palabra,ent,num_dec);
printf("\nfin del programa");
fflush(stdin)
getchar();
return 0;
}
Vemos en la línea 5º como la cadena de control de scanf() realiza tres asignaciones utilizando
el símbolo % común a ambas funciones y a continuación las letras s d f que corresponden a los
distintos formatos de cadena int y float.
También es importante señalar que las variables van precedidas del signo & salvo los arrays
de caracteres. Si escribimos en la pantalla:
perro 135 87995.125
y pulsamos enter se introducirá: perro -----> palabra[10]
135 -----> ent
87995.125 ---> num_dec
También se hubieran introducido de igual manera si hubiésemos escrito cada dato pulsando
enter al final del mismo. Es decir:
perro (enter)
135 (enter)
87995.125 (enter)
Por último la línea 7ª mostrará el mensaje en pantalla fin del programa utilizando printf() sin
llamada a ninguna variable. Comprobar que si no se hubiese puesto al principio un salto de linea \n se
hubiese escrito este mensaje a continuación de lo último escrito en pantalla.
Podemos decir que:
printf("fin del programa\n"); equivale puts("fin del programa");
Formatos comunes:
c -----> carácter
s -----> cadena
4-22
o -----> entero octal
x -----> entero hexadecimal
[...] -----> Entre corchetes se incluyen los caracteres que se pueden capturar.
[^\n] -----> El acento circunflejo excluye el carácter que no podrá capturar (en este caso el
fin de línea o enter)
Ejemplo 1.- Programa que captura una cadena compuesta sólo por los carácteres abcdeABCDE
incluido el carácter de espaciado.
#include <ansi_c.h>
#include <cvirte.h>
char letra[20];
scanf("%[abcdeABCDE ]",letra);
puts(letra);
printf("%s",letra);
getchar();
return 0;
}
Ejemplo 2.- Programa que captura todos los caracteres, incluido el espaciado, salvo el fin de línea
(enter).
#include <ansi_c.h>
4-23
#include <cvirte.h>
4-24
4.10.- Funciones matemáticas.
4-25
cantidad en doble precisión. stdlib.h
4-26
fwrite(s,il,i2,f)int Escribir i2 elementos, cada uno
de i1 bytes, desde la cadena s
hasta el archivo f. stdio.h
Notas: Tipo refiere al tipo de la cantidad devuelta por la función. Un asterisco denota un puntero.
4-27
s denota un argumento cadena
u denota un argumento entero sin signo
4-28
4.11.- Ejercios básicos.
Ejercicio 4.11.1- Determina cuales expresiones son verdaderas y cuales son falsas:
100<5 falso
20!=20 falso
20==20 verdadero
'b'>'c' falso
100<3 && 'a'<'c' falso
100>3 || 'a'>'c' verdadero
106>12&&5==5 verdadera
106>12 && 5==5 (también puede escribirse así)
106 > 12 && 5 == 5 (o así)
!(34<500 || 5>2) falsa
!(100!=5&&7<10||2==5) falso
(escribir a=’M’ es igual a escribir a=77 que es el número asignado por la tabla ASCII
a dicho carácter)
a) k=a+i; k=87
b) y=(i!=21 && x>0.5)? 100:0.25; y=100
c) b=5+a; b=82
d) i+=j; i=15
e) j%=2; j=1
f) x*=10; x=30
g) y=(!(i=<j)&&(a>40))? 0.005:8.45; y=0.005
h) k=(((i%j)*5)<2)? 20:0; k=20
i) y=((10*x>0.5)&&(5<=i)&&(2<x*i)) y=1
int a,b=53,c=’0’;
4-29
int x=10,y=2,z;
(En la codificación ASCII, el valor 53 corresponde al carácter 5, y al carácter cero le
corresponde el valor 48)
Ejercicio 4.11.4.- Programa que solicita la entrada de un número y lo escribe en octal y hexadecimal.
#include <ansi_c.h>
#include <cvirte.h>
int a;
printf("escriba un número n=");
scanf("%d",&a); /*se escribirá en decimal*/
printf("\n\n dec=%d octal=%o hex=%x",a,a,a);
getchar();
return 0;
}
#include <ansi_c.h>
#include <cvirte.h>
int a;
clrscr();
printf("escriba un número hexadecimal n=");
scanf("%x",&a); /*se deberá escribir en hexadecimal*/
printf("\n\n decimal=%d",a);
printf("\n\n octal=%o",a);
while(getchar()!='\n');//vaciado del buffer del teclado
getchar();
return 0;
}
4-30
La especificación de un campo determina el números de caracteres o dígitos de un número.
Veamos algunos ejemplos:
Ejercicio 4.11.6.- Programa que acepta la introducción de tres números int de sólo tres dígitos y los
presenta en un campo de 5 espacios.
#include <ansi_c.h>
#include <cvirte.h>
int a,b,c;
scanf("%3d %3d %3d",&a,&b,&c);
printf("\na=%5d b=%5d c=%5d",a,b,c);
while(getchar()!='\n');
getchar();
return 0;
}
si escribimos: aparecerá en pantalla:
123 -----> a= 1 b= 2 c= 3
456 876 123 -----> a= 456 b= 876 c= 123
123456789 -----> a= 123 b= 456 c= 789
12 3456 789 -----> a= 12 b= 345 c= 6
Ya que tenemos definido un campo de tres espacios para introducir los números enteros, y un
campo de 5 espacios para su presentación en pantalla. Si queremos que se ajusten a la izquierda
tendremos que emplear el signo menos.
Ejercicio 4.11.7.- Programa que acepta la introducción de tres números int de sólo tres dígitos y los
presenta en un campo de 5 espacios ajustándolos a la izquierda.
#include <ansi_c.h>
#include <cvirte.h>
int a,b,c;
scanf("%3d %3d %3d",&a,&b,&c);
printf("\na=%-5d b=%-5d c=%-5d",a,b,c);
getchar();
return 0;
}
4-31
Es de señalar que el signo menos ocupará también un espacio.
Ejercicio 4.11.8.- Programa que captura y presenta dos números decimales en distintos formatos.
#include <ansi_c.h>
#include <cvirte.h>
float a,b;
scanf("%f %f",&a,&b);
printf("número a=%f \nnúmero b=%f",a,b);
printf("\n\nnúmero a=%2.2f \nnúmero b=%4.3f",a,b);
printf("\n\nnúmero a=%g \nnúmero b=%g”,a,b);
printf("\n\nnúmero a=%e \nnúmero b=%e",a,b);
getchar();
return 0;
}
int num[3];
clrscr();
scanf("%d",&num[0]);
scanf("%d",&num[1]);
scanf("%d",&num[2]);
printf("%d %d %d",num[0],num[1],num[2]);
getchar();
return 0;
}
Ejercicio 4.11.10.- Realiza un programa en el que se pueda introducir una cadena hasta pulsar enter y
posteriormente nos dé el número de caracteres de la misma, utilizar la función strlen().
#include <ansi_c.h>
#include <cvirte.h>
4-32
puts("escribe una frase");
gets(cad);
i=strlen(cad);
printf("la frase tiene=%d
caracteres",i);
getchar();
return 0;
}
Ejercicio 4.11.11.- Escribe un programa que compare dos cadenas y nos diga si son iguales o no,
utilizar la función strcmp().
#include <ansi_c.h>
#include <cvirte.h>
Ejercicio 4.11.12- Programa para calcular la longitud de una circunferencia y el área de un circulo,
dado el radio*/
#define pi 3.141592654
#include <ansi_c.h>
#include <cvirte.h>
4-33
}
Ejercicio 4.11.12.- Cálculo de la tensión instantánea en un condensador Vc aplicarle una Vcc fija a
través de una R Vc=Vcc(1-e-t/RC)
#define e 2.7182818
#include <ansi_c.h>
#include <cvirte.h>
float Vcc,r,t,c,i,v;
printf("\n\n\n\t prog. para calcular la tension en un C.");
printf("\n\n\t escriba el valor de \"Vcc\" en voltios");
printf("\n\t \" \" \" \" \"c\" en faradios");
printf("\n\t \" \" \" \" \"r\" en ohmios");
printf("\n\t \" \" \" \" \"t\" en segundos");
printf("\n\n\t Vcc=");
scanf("%f",&Vcc);
printf("\n\t c=");
scanf("%f",&c);
printf("\n\t r=");
scanf("%f",&r);
printf("\n\t t=");
scanf("%f",&t);
i=(Vcc/r)*exp(-t/r*c);
printf("\n\t intensidad (A) en el instante dado i=%f",i);
i=(Vcc/r)*pow(e,(-t/r*c));
printf("\n\t i=%f",i);
v=Vcc-r*i;
printf("\n\t tensión (V) de C en dicho instante v=%f",v);
getchar();
return 0;
}
Ejercicio 4.11.13.- Realiza un programa que calcule las soluciones de una ecuación de segundo grado.
#include <ansi_c.h>
#include <cvirte.h>
float a,b,c,x1,ra,rb;
char p;
printf("Prog.para cal.las raices de una ec.
de 2º grado");
printf("\n\n\t introduce el valor de \"a\",
\"b\" y \"c\"");
printf("\n\t para una expresión general de
\"axx+bx+c=0\"");
printf("\n\t a=");
scanf("%f",&a);
printf("\t b=");
scanf("%f",&b);
4-34
printf("\t c=");
scanf("%f",&c);
ra=(b*b-4*a*c);
p=(ra<0)? 'i':' ';
ra=(ra>0)? ra:ra*-1;
ra=sqrt(ra);
printf("\n\n\t ra=%f",ra);
rb=ra/(2*a);
x1=(-b/(2*a));
printf("\n\n\t x1=%f+%f%c y x2=%f-%f%c",
x1,rb,p,x2,rb,p);
printf("\n\npulsa enter para continuar");
getchar();
return 0;
}
Vc/Vcc=1-e-t/RC --->
(1-Vc/Vcc)=e-t/RC ---> ln(1-Vc/Vcc)=-t/RC
luego: t=-RC.ln(1-Vc/Vcc)
Ejercicio 4.11.15.- (propuesto): Realiza un programa similar al anterior, donde podamos seleccionar
el % de carga(Vc=Vcc(1-e- T/RC).
Ejercicio 4.11.16.- (propuesto): Realiza un programa que presente en pantalla todos los caracteres
ASCII y su número correspondiente.
Ejercicio 4.11.17.- (propuesto): Realiza un programa que convierta una cadena alfabética de hasta 6
caracteres en mayúsculas (esta podrá introducirse en mayúsculas o minúscula).
4-35
4.12.- Sentencias de control.
Las sentencias de control condicional el flujo de un programa. Si hasta aquí, todos los
programas vistos, las líneas de un programa cualquiera se ejecutaban una sola vez y de una manera
correlativa. Con este tipo de sentencias podremos ejecutar una línea o un grupo de líneas si se cumplen
una condición o la expresión anexa a la palabra de control, por ejemplo:
...
línea 4;
while(a=>b){
línea 5;
línea 6;
línea 7;
}
línea 8;
...
En este ejemplo, las líneas 5,6 y 7 (encerradas entre llaves) se ejecutarán si la condición anexa
a while, es decir, (a=>b) es verdadera.
Podremos ejecutar una líneas o un grupo de líneas un número determinado de veces, o elegir
un grupo de sentencias de entre varios, dependiendo del valor de una variable, o saltar a otra parte del
programa (la famosa instrucción goto) aunque esto por lo que ya se explicó con respecto a los
programas estructurados, sólo será recomendable si con ello el programa gana en claridad.
Estas condiciones serán expresiones lógicas o aritméticas, al igual que las utilizadas con el
operador condicional.
Evidentemente, a poco que se complique un programa será necesario utilizar estas sentencias
de control pertenecientes todas ellas a las palabras claves de C.
Estas sentencias son:
4-36
4.12.1.- La sentencia while.
La sentencia while podemos traducirla por mientras, llevará anexa una expresión y mientras
esta sea válida la sentencia o grupo de sentencias encerradas entre llaves, se ejecutará.
#include <ansi_c.h>
#include <cvirte.h>
Ejemplo 2º: Programa que pregunta cuantas veces se escribirá la palabra HOLA.
#include <ansi_c.h>
#include <cvirte.h>
Esta sentencia compuesta se puede traducir por haz tal cosa mientras la expresión sea
válida. Se diferencia de la anterior en que al menos la sentencia simple o compuesta (grupo de
sentencias simples) se ejecutará al menos una vez.
Ejemplo 3º: Programa que pide la introducción de un número menor de 1000 y si este
no es correcto lo pedirá indefinidamente hasta que se cumpla la condición.
4-37
#include <ansi_c.h>
#include <cvirte.h>
Ejemplo 4º: Programa que calcula la suma y media de una serie de números.
#include <ansi_c.h>
#include <cvirte.h>
printf("¿cuantos números?");
scanf("%d",&n);
do{
printf("\n x=");
scanf("%f",&x);
suma +=x;
media=suma/cont;
printf(" suma=%6.2f",suma);
printf(" media=%6.2f",media);
++cont;
}while(cont<=n);
puts("\npulsa una tecla");
getchar();
return(0)
}
...
if(a<300 && b!='s') printf("ERROR PRUEBA OTRA VEZ");
...
4-38
...
if(a<300 && b!='s'){
printf("ERROR PRUEBA OTRA VEZ");
++n_fallos;
sleep(1);
}
...
Ejemplo 7º: Programa que solicita la entrada de un número, y escribirá en pantalla si es positivo o
negativo.
#include <ansi_c.h>
#include <cvirte.h>
puts("escribe un número");
scanf("%f",&a);
if(a>=0) puts("el nº es positivo");
else puts("el nº es negativo");
puts("\aFIN");
getchar():
return 0;
}
4-39
#include <ansi_c.h>
#include <cvirte.h>
Donde la sentencia simple controlada por for se ha tabulado para indicar que depende
de ella.
#include <ansi_c.h>
#include <cvirte.h>
printf("cuantas potencias?");
scanf("%i",&b);
for(cont=1; cont<= b;++cont){
printf("\n%g",x);
x*=2;
}
printf("\n pulsa una tecla ");
getchar();
return 0;
}
#include <ansi_c.h>
4-40
#include <cvirte.h>
Con ésta sentencia, podemos ejecutar una línea o grupo de líneas pertenecientes a un grupo
mayor. Esta funcionará con una variable de carácter, que dependiendo del valor que tome, el flujo del
programa se desviará entre distintas opciones denominadas case.
Ejemplo 11º: Problema que solicita la elección de un color mediante la pulsación de
una tecla y luego escribe en pantalla dicho color.
#include <ansi_c.h>
#include <cvirte.h>
4-41
Se utiliza para saltar las sentencias posteriores dentro de un bucle si se da la condición anterior
if.
Ejemplo 12º: Programa que solicita la introducción de un número menor de 1000 y positivo, y
si es mayor o negativo vuelve a solicitarlo de una manera reiterativa. Si es correcto sale del bucle.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
float a;
do{
puts("\nescribe un número menor de 1000=");
scanf("%f",&a);
if(a>=0)continue;
puts("\nEl número es negativo");
}while(a>1000||a<0);
puts("el número es correcto");
getchar();
return 0;
}
En el programa si (a>0) saltará las sentencias posteriores del bucle, pero no saldrá de él. Si no
es válida el bucle seguiré ejecutándose.
La sentencia exit sirve para terminar un programa incluso si se está en cualquier tipo de bucle.
Ejemplo 13: Escribe un programa que obtenga un número entero positivo desde el teclado, e
imprima el mensaje "HOLA" tantas veces como indique el número, y que acabe si el número es
negativo.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int t;
printf("escribe un nº
entero positivo\n");
scanf("%d",&t);
if(t<0)exit(0);
for(;t>0;--t)
printf("\nHOLA");
getchar();
return 0;
}
4.13.- Funciones.
4-42
Un código fuente de un programa consta de distintas funciones, una de las cuales debe ser la
función main. Hasta ahora, todos los programas que hemos visto constan tan sólo de esta función.
Una función es un segmento del programa que realiza una determinada tarea bien definida
(podemos decir que se asemeja a una subrutina o una macro). Podemos definirla también como una
unidad de código autocontenida, diseñada para realizar tareas determinadas.
Estas se definirán al igual que main() entre llaves y tendrán un nombre y unos argumentos
denominados formales encerrados entre paréntesis.
Veamos un ejemplo de programa que contenga una función denominada funcion_1():
void main()
{
línea 1;
línea 2;
funcion_1( ); /*llamada a la función*/
línea 4;
...
línea 25;
funcion_1( );//llamada a la función
línea 27 ;
}
A una función podemos tratarla como una caja negra, a la que podemos introducir un valor o
varios (opcional) denominados argumentos formales de tipo char, int, float...etc, ejecuta una acción
y/o procesa esta entrada, y puede devolver (opcional) otro valor.
Ejemplo 1º: La función saluda() no tendrá argumentos formales y tampoco devolverá valor alguno,
tan sólo ejecutará una acción simple.
#include <ansi_c.h>
#include <cvirte.h>
4-43
void saluda( void){
puts("\n\nHOLA \nEstas dentro de la función");
puts("pulsa una tecla para continuar");
getchar();
return;
}
int main (int argc, char *argv[]){
La palabra clave return sirve para retornar de nuevo al programa o función principal main().
Si a continuación de return aparece una expresión entre paréntesis, esta queda como valor de retorno
de dicha función.
Las funciones distintas de main debe ir delante de estas o declararse en main, al igual que las
variables a utilizar, veamos un ejemplo;
Ejemplo 2º: La función mayor() va a aceptar dos valores enteros (argumentos formales) y va a
devolver el mayor de ellos.
#include <ansi_c.h>
#include <cvirte.h>
if(x>y) return(x);
else return(y);
}
Vemos que en la definición de la función va precedida del tipo de valor que devuelve int
mayor() y que dentro de los paréntesis se definen los tipos de los argumentos que acepta.
Ejemplo 3º:
4-44
#include <ansi_c.h>
#include <cvirte.h>
4.14.- Recursividad..
#include <ansi_c.h>
#include <cvirte.h>
int a;
void asterisco(int x);
puts("¿números de asteriscos a escribir?");
scanf("%d",&a);
asterisco(a);
puts("\n");
4-45
getchar();
return 0;
}
void asterisco(int x)
{
if(x==1) return;
putchar('*');
asterisco(x-1);
}
int a[4][2]; almacenará 4*2=8 números enteros cuatro filas por dos columnas:
a[0][0] a[0][1]
a[1][0] a[1][1]
a[2][0] a[2][1]
a[3][0] a[3][1]
char letras[]="California"; almacenará once caracteres correspondientes a las diez letras mas el
nulo ’\0’ ( donde las "casillas" del array se llenaran
con el código ASCII de los caracteres:
letras[0]--->’C’
letras[1]--->’a’
letras[2]--->’l’
...
letras[9]--->’a’
letras[10]-->’\0’
color[0]--->’R’
4-46
color[1]--->’E’
color[2]--->’D’
char color[]="RED"; igual que los dos casos anteriores (con el carácter nulo).
El lenguaje C no permite operaciones que impliquen arrays completos (al contrario de otros
lenguajes), así que estos deben realizarse elemento a elemento, por supuesto que la dimensión de
ambos debe ser idéntica.
Ejemplo primero: vamos a realizar un programa que defina a dos arrays a y b de tres números
enteros, dandole valores iniciales en ambos y nos presente en pantalla el resultado que debe ser otro
array al que denominaremos c.
#include <ansi_c.h>
#include <cvirte.h>
int n,c[3];
int a[3]={7,14,32};
int b[3]={14,4,100};
for(n=0;n<3;++n) c[n]=a[n]+b[n];
printf("c[0]=%d \n",c[0]);
printf("c[1]=%d \n",c[1]);
printf("c[2]=%d \n",c[2]);
getchar();
}
Vemos que es necesario efectuar un bucle que vaya sumando cada elemento del array a con el
correspondiente elemento del array b. Este programa podría haberse realizado también de una manera
más resumida:
#include <ansi_c.h>
#include <cvirte.h>
int n,c[3];
int a[3]={7,14,32};
int b[3]={14,4,100};
for(n=0;n<3;++n) printf("\n c[%d]=%d",n,a[n]+b[n]);
getchar();
}
Ejemplo segundo: Supongamos que queremos leer una lista de n cantidades en coma flotante y
calcular la media. Además de calcular simplemente la suma, se calculará también la desviación de
4-47
cada uno de los valores respecto a la media, siguiendo la expresión d = xi - media donde xi representa
las cantidades i=1,2,3, ...,n y media representa la media calculada.
#include <ansi_c.h>
#include <cvirte.h>
int n,cont;
float media,d,suma=0;
float lista[100]; /*array con capacidad para 100 números float*/
/*leer el valor de n */
printf("¿Cuantos números para calcular la media?");
scanf("%d",&n);
printf("\n");
Vemos que cuando hacemos referencia a un elemento del array lista en la segunda función
scanf se utiliza un ampersand & (scanf("%f",&lista[cont]);).
Para pasar un array a una función, el nombre del array debe aparecer solo sin
corchetes. Los valores del array pueden ser alterados por la función y ser reconocidos dentro de main
sin ningún problema.
Veamos un ejemplo de un programa que presenta los tres números enteros de un array,
llama a la función sumauno(que sumará una unidad a cada número y presentará de nuevo los tres
números del array:
#include <ansi_c.h>
#include <cvirte.h>
4-48
for(cont=0;cont<3;++cont)printf("n[%d]=%d\n",cont,n[cont]);
suma_uno(n);
for(cont=0;cont<3;++cont)printf("n[%d]=%d\n",cont,n[cont]);
getchar();
return 0;
}
void suma_uno(int x[3]) //o mejor void suma_uno(int *x) acepta un puntero a entero
{
int cont;
for(cont=0;cont<3;++cont)x[cont]+=1;
return;
}
Los arrays multidimensionales son definidos prácticamente de la misma manera que los arrays
unidimensionales, excepto que se requiere un par separado de corchetes para cada índice. Así un array
bidimensional requerirá dos corchetes, un array tridimensional tres ... y así sucesivamente.
Ejemplo:
int numeros[4][7] ---> tendrá una capacidad de 4 filas por siete columnas de números
int, es decir, una capacidad de 4*7=28 números int.
float cifras[3][5][8] ---> tendrá una capacidad de 3 filas por cinco columnas por 8
tablas de números float, es decir, una capacidad de 3*5*8=120 números float.
Estos elementos dependiendo del tipo como se haya definido el array (int, float, chart ...etc)
podrán contener un número o una letra.
int a[5][3]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
Veamos como ejemplo un programa que defina un array de 5 filas por tres columnas y que
represente en la pantalla a modo de matriz todos sus elementos. Realizar el programa de la forma más
reducida posible.
4-49
#include <ansi_c.h>
#include <cvirte.h>
int a[5][3]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int f,c;
for(f=0;f<5;++f){
putchar('\n');
for(c=0;c<3;++c)
printf("a[%d][%d]=%2d ",f,c,a[f][c]);
}
getchar();
return 0;
}
Para procesar arrays multidimensionales, por ejemplo sumar dos arrays, estos deben tener las
mismas dimensiones, veamos un ejemplo de ello realizando un programa que sume dos arrays de
cuatro filas por dos columnas de numeros enteros y nos muestre el resultado. Los valores iniciales
serán: a[4][2]={1,2,3,4,5,6,7,8} y b[4][2]={10,20,30,40,50,60,70,80}
#include <ansi_c.h>
#include <cvirte.h>
int f,c;
int a[4][2]={1,2,3,4,5,6,7,8};
int b[4][2]={10,20,30,40,50,60,70,80};
int r[4][2];
for(c=0;c<2;++c){
for(f=0;f<4;++f)
r[f][c]=a[f][c]+b[f][c];
}
for(c=0;c<2;++c){
putchar('\n');
for(f=0;f<4;++f)
printf("r[%d][%d]=%3d ",f,c,r[f][c]);
}
getchar();
return 0;
}
Ejemplo de programa que pide la introducción de elementos en una tabla de 3*2 y luego muestra dicha
tabla:
#include <ansi_c.h>
4-50
int contF,contC,tabla[3][2];
for(contF=0;contF<3;++contF){
for(contC=0;contC<2;++contC){
printf("\n tabla[%d][%d]=",contF,contC);
scanf("%d",&tabla[contF][contC]);
}
}
for(contF=0;contF<3;++contF){
for(contC=0;contC<2;++contC){
printf(" tabla[%d][%d]=%d",contF,contC,tabla[contF][contC]);
}
printf("\n");
scanf("%f",&semilla);
srand(semilla);
//bucle para introducir aleatoriamente todos los datos
for(f=0;f<5;++f){
for(c=0;c<10;++c){
x[f][c]=rand()%10;
4-51
}
}
printf("\n\n El numero de veces que se repite es %d",n);
fflush(stdin);
getchar();
printf("\n Fin del programa");
Delay(2);
return 0;
}
Vamos a ver como primer ejemplo, un programa que acepte diez frases de hasta 15 caracteres
y posteriormente las muestre.
#include <ansi_c.h>
#include <cvirte.h>
int n;
char x[10][15];
for(n=0;n<10;++n){
printf("\nescribe la frase numero%d= \n",n);
gets(x[cont]); //scanf(“%s”,&x[n]); //scanf("%[^\n]",x[n]);
getchar();
}
getchar();
for(n=0;n<10;++n)
printf("\nla frase numero%d es: \n%s",n,x[n]);
getchar();
return 0;
}
Vamos a ver como segundo ejemplo, un programa que reordene un array de 5 números
enteros, y posteriormente los muestre ya ordenados:
#include <ansi_c.h>
#include <cvirte.h>
4-52
int main (void)
{
int num[5],cont_a,cont_b,aux;
for(cont_a=0;cont_a<5;++cont_a){
printf("\n num[%d]=",cont_a);
scanf("%d",&num[cont_a]);
}
for(cont_a=0;cont_a<4;++cont_a){
for(cont_b=cont_a+1;cont_b<5;++cont_b)
if(num[cont_a]>num[cont_b]){
aux=num[cont_a];
num[cont_a]=num[cont_b];
num[cont_b]=aux;
}
for(cont_a=0;cont_a<5;++cont_a)
printf("\nnum[%d]=%d",cont_a,num[cont_a]);
fflush(stdin);//limpia teclado
getchar();
}
Vamos a ver como tercer ejemplo, un programa para reordenar cadenas de caracteres. Supongamos
que queramos introducir una lista de nombres y reordenarlas alfabéticamente. El problema planteado
es similar al ordenar una lista de números. Las palabras las introduciremos en un array bidimensional
de caracteres, por lo que cada palabra será introducida en una fila de este array. Y por último
utilizaremos las funciones de biblioteca strcmpi y strcpy, estas funciones se usan para comparar dos
cadenas y para copiar una cadena en otra respectivamente.
La función strcmpi es una variación de la función strcmp, que compara alfabéticamente cadenas sin
distinguir entre mayúsculas y minúsculas, al contrario de strcpm que sí las tiene en cuenta.
La función strcmpi acepta dos cadenas como argumentos y devuelve un valor entero, dependiendo del
orden relativo de las dos cadenas, tal como sigue:
- Devuelve un valor negativo si la 1ª cadena precede alfabéticamente a la 2º.
- Devuelve un valor cero si ambas cadenas son idénticas.
- Devuelve un valor positivo si la 2ª precede alfabéticamente a la 1ª.
Por tanto si la strcmpi(cadena1,cadena2) retorna un valor positivo, indicará que la segunda cadena
deberá ir delante de la primera.
Por último, el programa aceptará un número no determinado de cadenas, hasta que los tres primeros
caracteres de una cadena sean FIN, ignorandose esta palabra.
#include <ansi_c.h>
#include <cvirte.h>
4-53
#include <string.h>
int cont_a,cont_b;
char x[5][12];
for(cont_a=0;cont<5;++cont_a){
printf("escribe la frase nº%d",cont_a);
gets(x[cont_a]);
}
for(cont_a=0;cont_a<4;++cont_a)
for(cont_b=cont_a+1;cont_b<5;++cont_b)
if(strcmp(x[cont_a],x[cont_b])>0){
strcpy(aux,x[cont_a]);
strcpy(x[cont_a],x[cont_b]);
strcpy(x[cont_b],aux);
}
printf(“\n\n\n”);
for(cont_a=0;cont_a<5;++cont_a)
printf(“\n%s”,x[cont_a]);
getchar();
return 0;
}
4-54
4.16.-Punteros.
4.16.1.-Concepto de puntero.
Un puntero es una variable que almacena la posición o dirección de memoria de otro dato que
puede ser una variable o un elemento de un array. Un puntero nos proporciona la posibilidad de usar
direcciones de memoria, esto hace que los programas que utilizan punteros puedan ser más eficientes,
ya que permiten aproximarnos a la forma de trabajo de la máquina.
Los punteros están muy relacionados con los arrays, el nombre del array en en realidad un
puntero al primer elemeinto del mismo.
variable: x = 10
dirección de la variable: &x = 5AF
puntero de esta variable: px = 5AF
o bien: punt_x = 5AF
valor almacenado en dicha dirección: 10
valor almacenado donde apunta el puntero: *px = 10
Vemos que si la variable es x, &x representa su dirección, y por lo tanto un puntero de dicha
variable que podremos denominarlo como queramos (no tiene porqué llamarse así) por ejemplo
punt_x o px o puntero_1 tendrá como valor la dirección de esta variable. Mencionar también que se
representa por *punt_x al valor almacenado por la variable x, es decir al valor almacenado donde
apunta dicho puntero.
int u = 3;
int v;
int *pu; /*declaración de puntero de un entero(de la variable u)*/
int *pv; /*puntero de la variable de un entero(de la variable v)*/
pu = &u; /*asigna la dirección de u al puntero pu*/
v = *pu; /*asigna el valor de u a v ya que *pu=u=3*/
pv = &v; /*asigna la dirección de v al puntero pv*/
4-55
En pantalla se presentará el valor de las variables, las direcciones de dichas variables, los
punteros de dichas variables y por último el valor almacenado a donde apuntan dichos punteros, luego:
u = *pu v = *pv
&u = pu &v = pv
#include <ansi_c.h>
#include <cvirte.h>
int u1,u2;
int v=3;
int *pv=&v;/*hace innecesaria la línea “pv=&v” */
u1=2*(v+5);
u2=2*(*pv+5);
printf("\n u1=%d u2=%d",u1,u2);
getchar();
return 0;
}
El programa presentará un mismo valor para ambas variables u1 y u2 de 16. luego podremos
tratar a v de igual forma a *pv.
Es importante reseñar que no se puede asignar una dirección concreta a un puntero, es decir,
no podremos por ejemplo escribir en un programa &x=5AF; sino que será el propio ordenador quien
asigne una dirección.
Ya hemos visto en los ejemplos anteriores como declarar punteros a variables int. En general, un
puntero debe ser declarado como cualquier otra variable y asignarle posteriormente un valor (que será
en este caso una dirección de variable). La expresión general podría ser:
tipo_dato *punt_var;
Por ejemplo:
float u; /*declaración de la variable u*/
float *ptu; /*declaración del puntero de u*/
char a; /*declaración de la variable a*/
char *punt_a /*declaración del puntero de a*/
Es importante señalar que en la definición del puntero se utiliza el asterisco (float *ptu)
pero no en la sentencia de asignación de la dirección (ptu=&u).
4-56
4.16.2.- Paso de punteros a una función.
Vimos en el capítulo anterior como pasar un array como argumento en una llamada a una
función, siendo todos los elementos de esta accesibles por dicha función. También podemos en una
llamada a una función, pasar como argumento a un puntero. En ambos casos citados se conoce este
paso de información como paso de argumentos por referencia.
En el caso de pasar un valor o valores de tipo int, char o float ..etc en una llamada a una
función, se conoce este paso de información como paso de argumentos por valor.
En este último caso, este valor puede modificarse en dicha función, a no ser que la variable sea
externa y por lo tanto adcesible a las distintas funciones del programa.
Veamos un ejemplo:
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int u=1;
int v=3;
void func1(int u, int v);
void func2(int *pu,int *pv);
printf("\nAntes de la llamada a func1: u=%d v=%d",u,v);
4-57
getchar();
func1(u,v);
getchar();
printf("\n\nDespués de la llamada a func1: u=%d v=%d",u,v);
getchar();
printf("\nAhora vamos allamar a func2, pulsa una tecla");
getchar();
func2(&u,&v);
printf("\n\nDespués de llamar a func2: u=%d v=%d",u,v);
getchar();
return 0;
}
Al ejecutar el programa, mostrará los valores 1 y 3 antes de llamar a func1, dentro de func1 los
valores serán los asignados por la función es decir, cero en ambos casos. Al mostrarse de nuevo los
valores de ambas variables ya fuera de func1, los valores vuelven a ser de 1 y 3, por lo tanto func1 no a
podido modificar estos valores (paso por valor).
La llamarse a func2 estos se modifican dentro de la función, mostrandose en pantalla el valor
de cero para ambas variables al igual que en la primera función, pero con la diferencia de que al salir
de dicha función, estos valores sí han sido modificados manteniendose ahora el valor de cero dado por
la función (paso por referencia).
4-58
x[0] *x
x[1] *(x+1)
x[2] *(x+2)
... ...
x[n] *(x+n)
Veamos un ejemplo:
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int x[8]={2,4,6,8,10,12,14,16};
int i;
for(i=0;i<8;++i)
printf("\ni=%d x[i]=%d *(x+i)=%d &x[i]=%x
x+i=%x",i,x[i],*(x+i),&x[i],x+i);
getchar();
return 0;
}
Veremos que lod valores x[i] son iguales a *(x+i), y los valores &x[i] iguales a x+i.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int x[12],i;
for(i=0;i<12;++i){
printf("escribe el nº %2dº=",i);
scanf("%d",&x[i]);
}
for(i=0;i<12;++i){
printf("\ni=%2d x[%2d]=%6d *(x+%d)=%6d",i,i,x[i],i,*(x+i));
printf("printf("&x[%2d]=%3x x+%2d=%3x",i,&x[i],i,x+i);
}
getchar();
return 0 ;
}
Veremos al ejecutar el programa que el valor x[i] es igual a *(x+i) y que la dirección
&x[i] es igual a x+i.
4-59
Las dos definiciones son equivalentes, pero la definición convencional de un array produce la
reserva de un bloque fijo de memoria al principio de la ejecución del programa, mientras que esto no
ocurre si se define como puntero. Sin embargo, cuando se va a almacenar un número importante de
datos, por ejemplo 10 números int, es conveniente reservar un bloque de memoria por adelantado, para
ello utilizaremos la función de biblioteca malloc() para asignar suficiente memoria al array.
La función malloc() devuelve un puntero a un carácter siendo x un puntero int por lo que,
siendo eceptable la forma de uso anterior ( x=malloc(10*sizeof(int)) ), se puede realizar para mayor
seguridad una conversión de tipo de la siguiente forma:
x=(int*)malloc(10*sizeof(int));
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int i,n,*x;
void reordenar(int n,int *x);
4-60
/*reordenar todos los elementos del array*/
reordenar(n,x); /*mostrar la lista de números reordenada*/
printf("\n\nLista de números reordenada: \n\n");
for(i=0;i<n;++i)printf("i=%d x=%d\n",i+1,*(x+i));
getchar();
}
4-61
con cuidado. Supongamos que px es una variable puntero que representa la dirección de una variable
x. Podemos escribir expresiones como ++px, --px, (px+3), (px+i) y (px-i), donde i es una variable
entera. Cada expresión representará una dirección localizada a cierta distancia de la posición original
representada po px. La distancia exacta será el producto de la cantidad entera por el número de bytes o
palabras que ocupa cada elemento al cual apunta px.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int *px,*py;
static int a[6]={1,2,3,4,5,6};
px=&a[0];
py=&a[5];
printf(“px=%x py=%x”,px,py);
printf(“\n\npy-px=%x”,py-px);
getchar();
return 0;
}
py-px=5
La diferencia entre 5C y 52 es de 10, pero al estar almacenados como números int, el resultado
es el esperado, es decir, 5.
A modo de resumen, las operaciones que pueden realizarse con punteros son:
- A una variable puntero se le puede asignar la dirección de una variable ordinaria (pv=&v).
- A una variable puntero se le puede asignar el valor de otra variable puntero (por ejemplo
px=py), siempre que ambos punteros apunten al mismo tipo de datos.
- Una cantidad entera puede ser sumada o restada a una variable puntero (por ejemplo pv+3,
++pv).
- Una variable puntero puede ser restada de otra siempre que apunten a datos del mismo array.
- Dos variables puntero pueden ser comparadas siempre que ambas apunten a datos del mismo
tipo.
void SumaCinco(int *x,int *y){
*(y)=*(x)+5;
*(y+1)=*(x+1)+5;
4-62
*(y+2)=*(x+2)+5;
return;
}
Las variables se pueden clasificar por el tipo de datos (char, int, float ...etc) o bien por el tipo
de almacenamiento, dividiéndose en auto, extern, static y register.
A veces el tipo de almacenamiento asociado a una variable se puede establecer simplemente
por la localización de su declaración en el programa. En otras situaciones, sin embargo, la palabra
clave que especifica un tipo particular de almacenamiento se tiene que colocar al principio de la
declaración de la variable. Veremos como dependiendo del tipo de almacenamiento, una variable se
podrá comportar de una u otra manera.
Veamos simplemente en como se realiza estas declaraciones sin profundizar en su significado:
char
Tipo de datos: int
float
Variables:
auto
Tipo de almacenamiento: extern
static
4-63
register
Variables automáticas: Estas variables se declaran dentro de una función y son locales a esta, es
decir serán reconocidas sólo dentro de dicha función. Las variables automáticas no son necesarias
declararlas como tales, por lo tanto, cualquier variable declarada como hasta este momento (sin
ninguna alusión a su forma de almacenamiento) se interpretará como una variable automática.
Variables externas: Estas no están ligadas a una función determinada. Su ámbito se extiende desde el
punto en que se declaran, hasta el resto del programa, por lo que pueden ser llamadas por cualquier
función posterior. Mantienen para una función el valor asignado desde otra, por lo que es interesante a
la hora de transferir información desde una función a otra, ya que el comando return sólo transfiere un
dato.
Una definición de variable externa debe realizarse fuera de cualquier función y
normalmente antes de las funciones que acceden a esta.
Variables estáticas: Este tipo de variables se definen dentro de una función, por lo tanto son de
ámbito local. Para ello es obligatorio emplear la palabra clave static ya que si no se consideraría
automática.
Al contrario que las variables automáticas, estas retienen el valor almacenado durante toda la
vida del programa.
A todas las variables estáticas cuyas declaraciones no incluyan valores iniciales explícitos se
les asignará el valor cero.
SumaUno();
printf("\nEl nuevo valor de a es: %d",a);
SumaUno();
printf("\nEl nuevo valor de a es: %d",a);
4-64
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int cont;
void función(void);
for(cont=1;cont<=5;cont++){
printf("Aquí está la prueba %d:\n",cont);
funcion();
}
getchar();
return 0;
}
void funcion(void)
{
int a=1;
static int b=1;
printf("a=%d b=%d\n",a++,b++);
}
Cada vez que se accede a la función funcion(), la variable a toma el valor 1, pero la variable
estática b contiene el último valor asignado, ignorando el que se le da en su definición.
#include <ansi_c.h>
return(0);
4-65
4.18.- Programación a bajo nivel.
C permite la manipulación de bits individualmente dentro de una palabra. Así los bits pueden
ser desplazados hacia la izquierda o hacia la derecha, invertidos, o enmascarados. Las plicaciones que
requieren tale operaciones son familiars a los programadores en lenguaje ensamblador. C también
permite organizar en grupos individuales los bits dentro de una palabra. Esto permite empaquetar
datos de una sola palabra.
Este tipo de almacenamiento se utiliza casi exclusivamente a los tipos int y char. La palabra
clave register obliga al compilador de C a mantener el valor de las variables declaradas de esta manera
en un registro del microprocesador, en lugar de la memoria, que es donde habitualmente se almacenan
las variables. Esto hace que las operaciones sobre estas sean mucho más rápidas, ya que no se requiere
un acceso a memoria. Esta característica las hace ideales para el control de un bucle.
Este tipo de almacenamiento sólo puede aplicarse a variables locales, y a los parámetros
formales en una definición de función. No se permiten variables externas del tipo register.
- El operador de complemento a uno ~ (alt+126) es un operador monario que invierto los bits de su
operando, por tanto los unos se transforman en ceros y los ceros en unos. Este operador precede
siempre a su operando. El operando tiene que ser un entero (incluido integer long, short, unsigned o
char). Generalmente el operando será un octal o una cantidad hexadecimal sin signo, pero no es
obligatorio. Ejemplo (para 16 bits):
Expresión: Valor:
~0xc5 0xff3a
~0x1111 0xeeee
~0xffff 0
~52 01777725
~0177777 0
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
{
char f;
int x,y=0x5b3c;
x=sizeof(int);
printf("\nel numero di bits para int es=%d",x);
printf("\nel numero HEXAD=%x COMP A UNO=%x\n",y,~y);
getchar();
return 0;
4-66
}
- Los operadores lógicos a nivel de bits y& o exc^ (alt+94) o | cada uno de estos operadores
requiere operandos. Las operaciones se realizan independientemente bit a bit.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int a=0x5f,b=0xa7,c;
c=a&b;
printf("\nel resultado es=%x\n",c);
getchar( );
return 0;
}
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int a=0x5f,b=0xa7,c;
c=a&b;
printf("\nel resultado es=%x\n",c);
c=a^b;
printf("\nel resultado es=%x\n",c);
c=a|b;
printf("\nel resultado es=%x\n",c);
getchar();
return 0;
}
5f 0101 1111
a7 1000 0111
res a^b=d8 1101 1000
4-67
5f 0101 1111
a7 1000 0111
res a|b=df 1101 1111
Para obtener el resultado original, debemos operar el dato resultante con la máscara (secreta)
Ejercicio nº 1: Realiza como ejercicio un programa que solicite la escritura de una frase no mayor de
50caracteres, los encripte y los muestre en pantalla. Posteriormente los desencriptará y mostrará de
nuevo en pantalla la frase inicial. Usar como máscara 0xa7.
#include <ansi_c.h>
for(cont=0;cont<50;++cont){
res2[cont]=0;
res[cont]=0;
}
for(cont=0;cont<50;++cont){
if(frase[cont]==0)break;
res[cont]=frase[cont]^0xa7;
}
4-68
printf("\n\n La frase encriptada queda=%s",res);
for(cont=0;cont<50;++cont){
if(res[cont]==0)break;
res2[cont]=res[cont]^0xa7;
}
getchar();
return(0);
Ejercicio nº 2: Realiza un programa que nos indique en pantalla con verdadero o falso si el bit nº 10 de
in registro int es uno -> verdadero o 0-> falso. Para ello el programa nos solicitará la entrada de un
número int (este número int, podría ser en realidad un registro de una tarjeta de adquisición de datos,
donde cada bit corresponde a una entrada digital 0-1). Utilizar para ello la operación lógica adecuada y
una máscara para dicho fin.
Los dos operadores de desplazamiento a nivel de bits son desplazamiento a la izquierda << y
desplazamiento a la derecha >> Cada operador requiere dos operandos. El primero es un operando de
tipo entero que representa el patrón de bits a desplazar, el segundo es un entero sin signo que indica el
número de desplazamientos (si los bits en el primer operando son desplazados en 1,2,3 bits, y así
sucesivamente). Este valor no puede exceder del número de bits asociado con el tamaño de palabra del
primer operando.
El operador de desplazamiento a la izquierda produce que los bits en el primer operando sean
desplazados a la izquierda el número de posiciones indicado por el segundo operando. Los bits de más
a la izquierda (los de desbordamiento) en el patrón original de bis se perderán. Las posiciones de la
derecha que quedan vacantes se rellenan con ceros.
Por ejemplo, supongamos que a es una variable entera sin signo cuyo valor es 0x6dbf. La expresión
b=a<<6;
int b,a=0x6dbf;
b=a<<6; //desplazará 6 posiciones los bits de la variable a y el número binario //restante
lo introducirá en b
//también se podría haber escrito de la forma a<<=6 equivale a a=a<<6
Comprobar:
a=0x6dbf -> 0110 1101 1011 1111
b=0x6fc0 -> 0110 1111 1100 0000 <- desplazamiento de 6 bits a la izquierda
#include <utility.h>
#include <ansi_c.h>
#include <cvirte.h>
4-69
int main (void){
int b,a=0xf;
b=a>>3; //probar b=a<<6;
printf("b=%x",b);
fflush(stdin);
getchar();
return 0;
}
Unas de las virtudes del C está en la facilidad para procesar datos complejos, siendo una
herramienta muy potente para ello, el formato de estructura.
Esta es una especie de superarray, que puede estar formado por distintos tipos de datos int,
char, float. También punteros, arrays y otras estructuras pueden ser incluidas como elementos dentro
de una estructura principal. Los elementos que conforma dicha estructura se denominan miembros.
Estrechamente relacionada con estas lo están las uniones, cuya diferencia estriba en que todos
los miembros de la unión tienen el mismo área de almacenamiento, independientemente del tipo que
sean.
En la declaración de una estructura deben ser definidos todos sus miembros, veamos un
ejemplo:
#define TIT 40
#define AUT 30
#include <ansi_c.h>
#include <cvirte.h>
int main (void){
struct { /*definición de la estructura*/
char titulo[TIT];
char autor[AUT];
int precio;
}ficha;
4-70
Vemos con este ejemplo que una vez definida la estructura ficha podemos acceder a todos sus
miembros anteponiendo al nombre de estos elementos, el nombre de la estructura, como por ejemplo:
ficha.precio o ficha.titulo.
/*PROGRAMA QUE CREA 100 FICHAS PERO QUE ESCRIBE EN LA FICHA CERO
Y LEE LA FICHA CERO*/
#include <ansi_c.h>
#include <cvirte.h>
int main (void){
struct { /*definición de la estructura*/
char titulo[40];
char autor[30];
int precio;
}ficha[100];
printf("Introduzca título del libro:\n");
gets(ficha[0].titulo);
printf("Introduzca el nombre del autor:\n");
gets(ficha[0].autor);
printf("Introduzca ahora su precio:\n");
scanf("%d",&ficha[0].precio);
printf("\n\nDatos introducidos:");
printf("%s por %s:%d ptas.\n",ficha[0].titulo,ficha[0].autor,ficha[0].precio);
4-71
printf("Introduzca título del libro:");
gets(ficha[n].titulo);
printf("Introduzca el nombre del autor:");
gets(ficha[n].autor);
printf("Introduzca ahora su precio:");
scanf("%d",&ficha[n].precio);
break;
case 2:
printf("\nN Ficha a leer=");
scanf("%d",&n);
printf("\n\nTitulo:%s\nAutor:%s\nPrecio:%d",
ficha[n].titulo,ficha[n].autor,ficha[n].precio);
break;
case 3:
break;
default:
printf("\nELIGE CORRECTAMENTE POR FAVOR");
}
}while(elec!=3);
printf("\n\nFIN DEL PROGRAMA");
fflush (stdin);
getchar();
return;
}
case 1:
printf("n de ficha a escribir(0-99)=");
scanf("%d",&cont);
fflush(stdin);
printf("\n Introduzca t\xa1tulo del libro:");// \xa1 es el código ASCII de í
gets(ficha[cont].titulo);
printf("\n Introduzca el nombre del autor:");
gets(ficha[cont].autor);
printf("\n Introduzca ahora su precio:");
scanf("%d",& ficha[cont].precio);
printf("\n\n Datos introducidos:");
break;
case 2:
4-72
printf("n de ficha a consultar(0-99)=");
scanf("%d",&cont);
printf("\nTitulo:%s \n Autor:%s \n precio=%d euros.\n", ficha[cont].titulo, ficha[cont].autor,
ficha[cont].precio);
fflush(stdin);
getchar();
break;
case 3:
exit(0);
default:
printf("\n\nELIGE CORRECTAMENTE");
fflush(stdin);
getchar();
}
}while(1);
}
4-73
Hemos definido en el ejemplo anterior una estructura denominada ficha Podemos declarar otras
estructuras (podemos denominarlas también variables de estructuras)con idénticos miembros, de la
siguiente forma:
1ª lib_inf
2ª lib_lit
3ª lib_elec
Podremos de igual forma acceder a un miembro de cualquiera de ellas, por ejemplo:
libros.titulo
lib_inf.titulo
lib_elec.precio
(serán todas ellas variables distintas)
También se podría haber declarado estas estructuras, sin haber utilizado una estructura patrón, de la
siguiente forma:
Tal vez, la forma más elegante de crear multiples estructuras iguales es crear un patrón o tabla
modelo, y haciendo referencia a esta tabla, todas las estructuras semejantes que necesitemos, veamos
un ejemplo:
4-74
char titulo[40];
char autor[30];
int precio;
};
struct ficha libros_tec,lib_elec,lib_lit,lib_inf; /*definición de las variables del tipo estructuras*/
...etc
Esta figura correspondería a una estructura compleja, la forma de programarla será bastante intuitiva,
vistos los apartados anteriores:
struct libros
l
ibros_tec,libros_fil,libros_elec;
//declaración de 2 variables de tipo
estructura libros.
4-75
4.19.3- Array de estructuras.
4-76
4.20.- Archivos.
/*********************************************************************************
PROGRAMA QUE ALMACENA FICHAS EN UN ARCHIVO Y LAS RECUPERA
PRESENTA UN MENÚ PARA ESCRIBIR O LEER FICHAS, Y PARA SALVAR LA INFORMACIÓN EN
UN ARCHIVO O LEER LA INFORMACIÓN DESDE UN ARCHIVO
*********************************************************************************/
#include <utility.h>
#include <ansi_c.h>
#include <cvirte.h>
char nombre[10];
void salvar(void)
{
FILE *punt;
char c, nombre[13];
Cls();
puts("Nombre del archivo donde guardar la informaci\xa2n:");
scanf("%s",nombre);
punt=fopen(nombre,"w");
if (punt==0)puts("Error no se ha podido abrir");
fwrite(&ficha,76,100,punt);
fclose(punt);
return;
}
void leer(void)
{
FILE *punt;
Cls();
puts("Nombre del archivo a leer:");
scanf("%s",nombre);
punt=fopen(nombre,"r");
if (punt==0)puts("Error no se ha podido abrir");
fread(&ficha,76,100,punt);
fclose(punt);
return;
}
int elec, n;
printf("Tamaño de la ficha=%d",sizeof(ficha));
getchar();
do{
printf("\n\n\n1 Escribir una ficha\n2 Leer una ficha\n3 Salvar informaci\xa2n en archivo\n4
Leer fichas de archivo\n5 Salir\n\nOPCION=");
scanf("%d",&elec);
switch(elec){
case 1:
4-77
printf("\nN Ficha a escribir=");
scanf("%d",&n);
getchar();//while(getchar()!='\n') //fflush(stdin);//para que no salte la línea
printf("Introduzca t\xa1tulo del libro:");
gets(ficha[n].titulo);
printf("Introduzca el nombre del autor:");
gets(ficha[n].autor);
printf("Introduzca ahora su precio:");
scanf("%d",&ficha[n].precio);
break;
case 2:
printf("\nN Ficha a leer=");
scanf("%d",&n);
printf("\n\nTitulo: %s\nAutor: %s\nPrecio: %d", ficha[n].titulo, ficha[n].autor, ficha[n].precio);
break;
case 3:
salvar();
break;
case 4:
leer();
break;
case 5:
break;
default:
printf("\nELIGE CORRECTAMENTE POR FAVOR");
}
}while(elec!=5);
getchar();
return;
}
/*********************************************************************************
PROGRAMA QUE CREA UN ARRAY DE 100 NÚMEROS FLOAT DONDE PODEMOS INTRODUCIR
VALORES, LEERLOS
SALVARLOS EN UN ARCHIVO Y RECUPERARLOS
*********************************************************************************/
#include <utility.h>
#include <ansi_c.h>
#include <cvirte.h>
int tamanno=100;
float numeros[100];
void salvar(void)
{
FILE *punt;
char c, nombre[13];
int cont;
Cls();
puts("?Nombre del archivo");
scanf("%s",nombre);
4-78
punt=fopen(nombre,"w+");
if (punt==0)puts("Error no se ha podido abrir");
/* TAMBIEN SE PUEDE REALIZAR DE ESTA MANERA
for(cont=0;cont<tamanno;++cont)
fwrite(numeros+cont,sizeof(float),1,punt); //fwrite(&numeros[cont],sizeof(float),1,punt);
*/
fwrite(numeros,sizeof(float),tamanno,punt);
fclose(punt);
return;
}
void leer(void)
{
FILE *punt;
int cont;
char c, nombre[13];
Cls();
puts("?Nombre del archivo a leer");
scanf("%s",nombre);
punt=fopen(nombre,"r");
if (punt==0)puts("Error no se ha podido abrir");
/* TAMBIEN SE PUEDE REALIZAR DE ESTA MANERA
for(cont=0;cont<tamanno;++cont)
fread(numeros+cont,sizeof(float),1,punt);
//fread(&numeros[cont],sizeof(float),1,punt);
*/
fread(numeros,sizeof(float),tamanno,punt);
fclose(punt);
return;
}
4-79
case 3:
salvar();
break;
case 4:
leer();
break;
case 5:
break;
default:
printf("\nELIGE CORRECTAMENTE POR FAVOR");
}
}while(elec!=5);
getchar();
return;
}
4-80
4.21.- Ejercicios.
4.21.1.- Realiza un programa realiza la tabla de multiplicar 0-10 de cualquier numero inferior o igual a
3276.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int numero=0,contador=0,total=0;
printf("Introduce un número (MAX=3276) n=");
scanf("%d",&numero);
printf("TABLA DE MULTIPLICAR DEL %d\n\n\n", numero);
while (contador<11){
total=contador*numero;
printf("%d",numero);
printf(" * ");
printf("%d",contador);
printf(" = ");
printf("%d\n",total);
contador++;
}
getchar();
return 0;
4.21.2.- Escribir un programa que solicite una entrada de un número menor de 1000 y calcule la raíz
cuadrada de dicho número, en caso contrario dará un mensaje de error y pedirá de nuevo la
introducción del número.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
float a;
char r;
etiqueta_1:
printf("escribe un nº positivo menor de 1000\n\n\t");
scanf("%f",&a);
while(a>0) {
if(a<1000) {
a=sqrt(a);
printf("\n\n\t la raíz es=%.2f",a);
break;
}
else {
printf("numero incorrecto pulsa intro para continuar");
getchar();
break;
}
}
while (a<0) {
printf("numero incorrecto pulsa intro para continuar");
getchar();
break;
}
printf("\n\n\t ¿quieres continuar \"s\" o \"n\"\n\n\t ");
4-81
getchar();
r=getchar();
if (r=='s') goto etiqueta_1;
printf("fin");
getchar();
return 0;
}
4.21.3.- Escribir un programa de tres maneras distintas que simplemente imprima los números del 1 al
99 en pantalla.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int t;
for(t=1;t<100;++t) {
printf("%d ",t);
delay(100);
}
getchar();
return 0;
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int t=1;
while(t<100) printf("%d ",t++);
getchar();
return 0;
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int t=1;
do {
printf("%d ",t++);
} while(t<100);
getchar();
return 0;
4.21.4.- Programa que solicita una entrada de días,horas minutos y segundos separados por comas y
los convierte en segundos.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
long dias,horas,minutos,segundos,seg;
int n; /*número de datos introducidos*/
const int segminuto = 60,minhora = 60,horasdia = 24;
const long seghora = segminuto*minhora; /*constantes calculadas*/
const long segdia = seghora*horasdia;
4-82
printf("\n Conversión de unidades de tiempo a segundos:\n\n");
printf("Días, horas, minutos, segundos: "); /*mensaje*/
n = scanf("%ld,%ld,%ld,%ld",
&dias,&horas,&minutos,&segundos); /*entrada de datos*/
4.21.5.- Crea un programa que pida una cadena de caracteres (una palabra o nombre) y que lo imprima
al contrario utilizar la función de librería "strlen(nombre_cadena)".
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int t;
char s[80];
}
4.21.6.- Escribe un programa en "C" que solicite la introducción de diez números (enteros base 10). A
continuación los mostrará en una línea como comprobación y dará la media aritmética y el valor
máximo de ellos.
Se utilizará para almacenar estos números un array denominado "valor[10]" de tipo int.
Los números podrán ser introducidos escribiéndolos con espacios en blanco entre ellos o
pulsando "enter" a continuación de cada número (utilizar para ello un bucle for).
#define NUM 10
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int i,suma,media,max,valor[NUM];
4-83
printf("Introducir 10 nº enteros separados por esp. en blanco\n");
printf("o pulsando \"enter\"\n");
for(i=0;i<NUM;i++)
scanf("%d",&valor[i]); /*lee los diez numeros*/
printf("los diez nº son:\n");
for(i=0;i<NUM;i++)
printf("%6d",valor[i]); /*comprueba la entrada*/
for(i=0,suma=0;i<NUM;i++)
suma +=valor[i];
media=suma/NUM;
printf("\n\n La media aritmética es:%d",media);
for(max=valor[i],i=1;i<NUM;i++) /*comprueba el valor máximo*/
if(valor[i]>max)
max=valor[i];
printf("\n\n el valor máximo es:%d",max);
getchar();
return 0;
4.21.7.- Escribir una función denominada max(x,y) que devuelve el mayor valor de sus dos
argumentos formales enteros (la función acepta dos números enteros y devuelve un valor entero).
4.21.8.- Realizar un programa que pida introducir 10 números separados por un espacio en blanco o
pulsando "enter" (introducirlos en un array) y utilizando la función creada denominada max(x,y) que
devuelve el mayor valor de sus dos argumentos formales enteros, escribir el mayor de ellos.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int i,m,numeros[10]; //declaración de variables a utilizar.
int max(int x,int y); //declaración de función a utilizar.
printf("introduce diez números separados por espacios en blanco\n");
printf("o pulsando\"enter\", y te diré cual es el mayor\n");
for(i=0;i<10;i++)
scanf("%d",&numeros[i]);
printf("los diez números son:\n");
for(i=0;i<10;i++)
printf("%8d",numeros[i]);
for(i=1;i<10;++i)
m=max(numeros[0],numeros[i]);
printf("\n\nel número mayor es: %d",m);
printf("\nfin...pulsa una tecla\a");
getchar();
return 0;
}
4-84
if(x>y) return(x);
else return(y);
}
4.21.9.- Escribe un programa que solicite la introducción del nombre, dirección y teléfono, y los
muestre a continuación entre dos líneas de asteriscos, utilizar para ello una función denominada
"asteriscos()" que escriba 65 asteriscos.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
char n[30],d[30],t[10]; //declaración de variables a utilizar.
void asteriscos(); //declaración de función a utilizar. Si la función se sitúa antes de
//main() no es necesario declararla
printf("introduce tu nombre\n");
gets(n);
printf("\n introduce tu dirección\n");
gets(d);
printf("\n introduce tu teléfono\n");
gets(t);
asteriscos(); //llamada a la función.
puts(n);
puts(d);
puts(t);
asteriscos();
getchar();
return 0;
}
void asteriscos(void)
{
int cont;
for(cont=1;cont<=65;cont++)
putchar('*');
putchar('\n');
return;
}
4.21.10.- Escribe, al igual que el problema anterior, un programa que solicite la introducción del
nombre, dirección, teléfono y nº de asteriscos, y los muestre a continuación entre dos líneas de
asteriscos, utilizar para ello una función denominada asteriscos(n) que escriba en pantalla un número
n de asteriscos.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
char n[30],d[30],t[10]; //declaración de variables a utilizar.
int n; //declaración de variable a utilizar.
void asteriscos(int n); //declaración de función a utilizar.
printf("introduce tu nombre\n");
gets(n);
printf("\n introduce tu dirección\n");
gets(d);
printf("\n introduce tu teléfono\n");
4-85
gets(t);
printf(“\n introduce el nº de asteriscos a escribir en la línea\n”);
scanf(“%d”,&n);
void asteriscos(int n)
{
int cont;
for(cont=0;cont<n;cont++)
putchar('*');
putchar('\n');
return;
}
4.21.11.- Escribir una función recursiva denominada "print_num() que tenga un argumento entero.
Imprimirá en la pantalla los números del 1 al "n", en donde "n" es el valor de argumento.
print_num(int n){
if(n==1) printf("%d",n);
else {
printf ("%d",n);
print_num(n-1);
}
return;
}
#define PI 3.1415
#include <ansi_c.h>
4-86
#include <cvirte.h>
float r,i,m,a;
int main (int argc, char *argv[]){ void conv_p_b(float x,float y);
void conv_b_p(float w,float z);
float x,y,w,z;
char c;
do{
do{
puts("\t\t--- PROGRAMA DE CONVERSIÓN ----");
puts("\n\t1 Polar a Binómica");
puts("\n\t2 Binómica a Polar");
printf("\n\n\t\t\tPulsa 1 ó 2 opción=");
c=getchar();
if(c=='1'||c=='2')break;
puts("\a\nERROR SELECCIONE CORRECTAMENTE");
getchar();
}while(c!='1'||c!='2');
switch(c){
case '1':
printf("Módulo=");
scanf("%f",&x);
printf("\nArgumento=");
scanf("%f",&y);
conv_p_b(x,y);
printf("\n-------->%.2f%+.2fj",r,i);
break;
case '2':
printf("Parte real=");
scanf("%f",&w);
printf("\nParte imaginaria=");
scanf("%f",&z);
conv_b_p(w,z);
printf("\n--------->%.2f[%.2fº",m,a);
break;
default:
puts("\n\aELIGE CORRECTAMENTE");
break;
}
do{
printf("\n¿Quieres continuar? pulsa \"s\" o \"n\"");
c=getchar();
if(c=='n')break;
if(c!='s'){
puts("\a\nERROR ELIGE CORRECTAMENTE pulsa intro");
getchar();
}
}while(c!='s');
}while(c=='s');
puts("\n\a\t\t FIN");
getchar();
return 0;
}
4-87
void conv_b_p(float w,float z)
{
m=sqrt((w*w)+(z*z));
a=((atan(z/w))*360)/(2*PI);
}
4.21.13.- Escribe un programa en el podamos introducir los números con decimales (float) que
queramos hasta 100 como límite y nos calcule la suma de ellos la media aritmética y el menor de ellos.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int n,cont;
float menor,suma=0;
float lista[100];
for(cont=0,menor=lista[cont];cont<n;cont++)
if(lista[cont]<menor)
menor=valor[cont];
printf("\nEl menor de estos números es %f",menor);
getchar();
return 0;
}
4.21.14.- Escribe un programa en el podamos introducir los números con decimales (float) que
queramos hasta 100 como límite y nos calcule mediante tres funciones denominadas suma(),
madia_arit() y menor(), la suma de ellos la media aritmética y el menor de ellos.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int n,cont;
float menor,suma=0;
float lista[100];
float suma();
float media_arit();
float menor();
4-88
printf(“\n\nLa media aritmética es:%.4f”.media_arit(n,lista));
printf(“\n\nEl menor de ellos es:%.4f”,menor(n,lista));
getchar();
return 0;
}
4.21.15.- Realiza un programa que sea capaz de sumar dos arrays de tres números enteros definidos en
la misma declaración de los arrays y mostrarlos en pantalla.
#include <ansi_c.h>
#include <cvirte.h>
int main (int argc, char *argv[]){
int n,c[3];
int a[3]={7,14,32};
int b[3]={14,4,100};
for(n=0;n<3;++n) c[n]=a[n]+b[n];
for(n=0;n<3;++n) printf("c[%d]=%d\n",n,c[n]);
getchar();
return 0;
}
4.21.16.- Realiza un programa que cree una array de numeros enteros de 3 filas por 4 columnas y pida
la introducción de los mismos mostrando en pantalla cada elemento donde se van a introducir el
número y al final muestre en pantalla la matriz completa.
#include <ansi_c.h>
#include <cvirte.h>
4-89
int main (int argc, char *argv[]){
int num[3][4],n,m;
for(n=0;n<3;++n)
for(m=0;m<4;++m){
printf("escribe el número que quieres introducir en:\n");
printf("num[%d][%d]=",n,m);
scanf("%d",&num[n][m]);
4-90