Está en la página 1de 11

Intrusiones del Procesador

Una máquina puede llegar a funcionar con un juego de instrucciones muy limitado (recuérdese,
por ejemplo, la máquina de Turing que sólo tiene 4 instrucciones, incluso se han diseñado
máquinas teóricas con menos instrucciones), estos implificaría mucho los circuitos de la máquina.
Sin embargo, un conjunto de instrucciones demasiado implicado origina, como consecuencia, unos
programas demasiado complejos e ineficientes. Es necesario encontrar un compromiso entre la
simplicidad del hardware y del software. Un mínimo para llegar a ese compromiso se consigue con
los tipos de instrucciones siguientes:

 Instrucciones de transferencia de datos.


 Instrucciones aritméticas.
 Instrucciones lógicas.
 Instrucciones de control del flujo del programa (bifurcaciones, bucles, procedimientos,
etc.)
 Instrucciones de entrada y salida.

Funciones

una función es una sección de un programa que calcula un valor de manera independiente al resto
del programa.

Una función tiene tres componentes importantes:

 los parámetros, que son los valores que recibe la función como entrada;
 el código de la función, que son las operaciones que hace la función; y
 el resultado (o valor de retorno), que es el valor final que entrega la función.

Función main

Cada programa de C tiene una función principal que se debe llamar main. Si su código sigue el
modelo de programación Unicode, puede utilizar la versión de carácter ancho de main, wmain. La
función main sirve como punto de partida para la ejecución del programa. Normalmente, controla
la ejecución del programa dirigiendo las llamadas a otras funciones del programa. Un programa
deja de ejecutarse normalmente al final de main, aunque puede finalizar en otros puntos del
programa por distintos motivos. A veces, quizás cuando se detecta un error, puede resultar
conveniente forzar la finalización de un programa. Para ello, utilice la función exit.

Sintaxis

main( int argc, char *argv[ ], char *envp[ ] )

Estructura de Operaciones

Las estructuras son colecciones de variables relacionadas bajo un nombre. Las estructuras pueden
contener variables de muchos tipos diferentes de datos - a diferencia de los arreglos que
contienen unicamente elementos de un mismo tipo de datos.
Las estructuras son tipos de datos derivados - están construidas utilizando objetos de otros tipos.
Considere la siguiente definición de estructura:

struct ejemplo {

char c;

int i;};

Funciones de Entrada y Salida

La función scanf.

Mediante la función scanf podemos introducir cualquier combinación de valores numéricos,


caracteres sueltos y cadenas de caracteres a través del teclado. En definitiva, scanf lee datos
formateados de la entrada estándar. Cuando hablamos de datos formateados, nos referimos a que
los datos se pueden presentar en distintos formatos. La función devolverá el número de datos que
se han introducido correctamente.

En general, una referencia a la función scanf se escribe:

scanf (cadena de control, lista de argumentos);

scanf(tipo, &var);

La función printf.

Mediante la función printf podemos escribir datos en el dispositivo de salida estándar (pantalla).
Complementariamente a scanf, printf puede escribir cualquier combinación de valores numéricos,
caracteres sueltos y cadenas de caracteres. La función printf transporta datos desde la memoria a
la pantalla, a diferencia de scanf, que envía datos desde el teclado para almacenarlos en la
memoria. La función printf devuelve el número de caracteres escritos. Si devuelve un valor
negativo indica que se ha producido un error.

En general, una referencia a la función printf se escribe:

printf (cadena de control, lista de argumentos);

Argumento de La función Scanf

la función scanf() (scan-format, analizar con formato), en realidad representa a una familia de
funciones que analizan una entrada de datos con formato y cargan el resultado en los argumentos
que se pasan por referencia a dicha función o funciones:

 La función scanf() lee los datos de entrada en el stdin (flujo de entrada estándar).
 La función fscanf() (file-scanf) lee en un flujo de entrada dado, por lo general un fichero
(file) abierto para lectura.
 La función sscanf() (string-scanf) obtiene la entrada que se va a analizar de una cadena de
caracteres dada (string).
Veamos en una tabla los carácteres de conversión más frecuentes:

Carácter  Significado
c Lee un carácter simple
d Lee un entero decimal 
i Lee un entero decimal, octal o hexadecimal
e Lee un número en punto flotante
f Lee un número en punto flotante
g Usa %e o %f, el más corto en long.
o Lee un entero octal corto
s Lee una cadena de caracteres
u Lee un entero decimal sin signo
x Lee un entero hexadecimal 
[...] Lee una cadena de caracteres con caracteres de espaciado
p Lee un puntero

Ejemplo

// Este ejemplo guarda un número en n.

int n;
printf("Introduce un numero: ");
scanf("%d",&n);

// Este ejemplo guarda un caracter en m.

char m;
printf("Introduce un caracter: ");
scanf("%c",&m);

// Este ejemplo guarda una cadena de caracteres (solamente una palabra) en cad.
// Notese la ausencia de &

char cad[20];
printf("Introduce una palabra: ");
scanf("%s",cad);

printf("Introduce una palabra: ");


scanf("%10s",cad); // lee máximo 10 caracteres y le concatena el caracter cero.

Argumento de la función Printf


Numerosos lenguajes de programación implementan una función printf (print formatted), para
mostrar una cadena con formato. Esta, originaria del lenguaje de programación C, tiene un
prototipo similar al siguiente:

int printf(const char* formato,...)

Derivaciones

 Sprintf: que índica el número de caracteres leídos


 Fprintf: permite que la salida de printf pueda escribirse en cualquier archivo. Los
programadores suelen utilizarlo para imprimir errores, pero puede funcionar con cualquier
archivo abierto con la función fopen. Su prototipo, dentro del archivo de cabecera stdio.h
 Snprintf: produce una salida con formato como printf, pero en vez de enviarlo al stdout lo
escribe a una cadena de caracteres. A diferencia de sprintf esta necesita el número de
bytes que queremos escribir, pudiendo evitar así más fácilmente un problema de
desbordamiento de buffer. Su prototipo, dentro del archivo de cabecera stdio.h,

Veamos en una tabla los carácteres de conversión más frecuentes

Carácter  Significado
c Escribe un carácter simple
d Escribe un entero decimal con signo
i Escribe un entero decimal, octal o hexadecimal con signo
e Escribe un número en punto flotante con exponente
f Escribe un número en punto flotante sin exponente
g Usa %e o %f, el más corto en longitud
o Escribe un entero octal, sin el cero inicial
s Escribe una cadena de caracteres
u Escribe un entero decimal sin signo
x Escribe un entero hexadecimal sin el prefijo 0x.

Ejemplo de uso ( C ):

#include <stdio.h>

int main()
{
char cadena[12];
char buffer[120];
char* buffer1 = "Hemos escrito un ESLOGAN con sprintf - ";
int i,j, numerito=78989, tam_cad, tam_buffer;
for(i=0; buffer1[i]!='\0'; i++) buffer[i]=buffer1[i]; /* Copiamos un STRING a Cadena y medimos su
tamaño */
tam_buffer=i;
tam_cad=sprintf(cadena ,"%d", numerito); /* Pasamos a cadena el número ( de entero a char* )
*/
for(i=0,j=tam_buffer; i<tam_cad; i++, j++) buffer[j]=cadena[i]; // Le pegamos la cadena
( contiene el numeritoo )
buffer[j]='\0';

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

return(0);
}

Todos los tipos de datos primitivos en el lenguaje C

Como hemos estado aprendiendo a programar utilizando el lenguaje C no nos hemos quedado a
hilar fino en los tipos de datos primitivos.

Cada vez que necesitamos almacenar un entero utilizamos el tipo int, también dijimos que el tipo
char permite almacenar un entero pequeño, pero el lenguaje C permite definir distintos tipos de
enteros según la capacidad máxima a almacenar y si necesitamos guardar el signo.

Hay cuatro modificadores de tipo para las variables enteras: signed, unsigned, short y long que nos
permiten ampliar los tipos enteros en el lenguaje C.

 char (permite almacenar un valor entero entre -128 y 127 o entre 0 y 255 dependiendo del
compilador utilizado)
 signed char (permite almacenar un valor entero entre [-128 , 127])
 unsigned char (permite almacenar un valor entero entre [0 , 255])
 signed short int ( permite almacenar un valor como mínimo entre[-32767 , 32767])
 Cuando definimos una variable de este tipo podemos resumirla poniendo solo short o
short int o signed short.
 unsigned short int ( permite almacenar un valor como mínimo entre[0 , 65535])
 Cuando definimos una variable de este tipo podemos resumirla poniendo solo unsigned
short.
 signed int (permite almacenar un valor como mínimo entre [-2147483648 , 2147483647]
 Cuando definimos una variable de este tipo podemos resumirla poniendo solo int
 Recordemos que hasta ahora siempre utilizamos este tipo de dato para almacenar
enteros, pero de ahora en más podemos utilizar la más eficiente según la necesidad de
almacenamiento.
 unsigned int (permite almacenar un valor como mínimo entre [0 , 4294967295]
 Cuando definimos una variable de este tipo podemos resumirla poniendo solo unsigned
 signed long int (permite almacenar un valor como mínimo entre [-2147483648 ,
2147483647]
 Cuando definimos una variable de este tipo podemos resumirla poniendo solo long o long
int o signed long
 unsigned long int (permite almacenar un valor como mínimo entre [0 , 4294967295]
 Cuando definimos una variable de este tipo podemos resumirla poniendo solo unsigned
long
 signed long long int (permite almacenar un valor como mínimo entre [?
9223372036854775807 , 9223372036854775807]
 Cuando definimos una variable de este tipo podemos resumirla poniendo solo long long o
long long int o signed long long
 unsigned long long int (permite almacenar un valor como mínimo entre [0 ,
18446744073709551615]

Línea de Control o Estructura de Control

La estructura condicional if ... else

En la gran mayoría de los programas será necesario tomar decisiones sobre qué acciones realizar.
Esas decisiones pueden depender de los datos que introduzca el usuario, de si se ha producido
algún error o de cualquier otra cosa.

La estructura condicional if ... else es la que nos permite tomar ese tipo de decisiones. Traducida
literalmente del inglés, se la podría llamar la estructura "si...si no", es decir, "si se cumple la
condición, haz esto, y sino, haz esto otro".

Un ejemplo sencillo sería el siguiente (no se trata de un programa completo, sino tan sólo una
porción de código):

if (edad < 18) printf("No puedes acceder.\n");

else

printf("Bienvenido.\n");

Operadores de comparación
El símbolo > visto en el último ejemplo es un operador, que en este caso compara dos números
enteros y devuelve verdadero si el primero es mayor, falso en caso contrario.
A continuación, un listado de los posibles operadores de comparación en C y su significado.

Operadores de Comparación

Operador Significado

< estrictamente menor que

> estrictamente mayor que

<= menor o igual que


>= mayor o igual que

== igual a

!= distinto de

Ejemplo

float division(int dividendo, int divisor) {

if (divisor) {

return dividendo / divisor;

} else {

printf ("No se puede dividir por cero\n");

return 0;

Operadores lógicos[editar]

Los operadores && ("y"), || ("o") y ! ("no") son operadores lógicos. Permiten operar con
expresiones lógicas para generar expresiones más complejas.
Por ejemplo: determinar si un año es bisiesto o no. Los años son bisiestos si son divisibles por 4,
pero no si son divisibles por 100, a menos que también sean divisibles por 400.

if ( (!(a % 4) && (a % 100)) || !(a % 400) ) {


printf("es un año bisiesto.\n");
} else {
printf("no es un año bisiesto.\n");
}

Evaluación de cortocircuito[editar]
La evaluación en corto circuito es una característica del lenguaje C que se utiliza para optimizar la
ejecución de programas. Consiste en que el programa puede verificar si una expresión es
verdadera o falsa antes de haber evaluado toda condición.
Por ejemplo, si se tiene una condición como la siguiente:

if ((a > 2) || (b < 4)) {


...
}

La estructura condicional abierta y cerrada switch ... case


La estructura condicional switch ... case se utiliza cuando queremos evitarnos las llamadas
escaleras de decisiones. La estructura if nos puede proporcionar, únicamente, dos resultados, uno
para verdadero y otro para falso. Una estructura switch ... case , por su parte, nos permite elegir
entre muchas opciones. Ejemplo:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
int dia;

printf("¿Qué número de día de la semana es?");


scanf("%i",&dia);

switch(dia) {
case 1 :
printf("Lun, Lunes");
break;
case 2 :
printf("Mar, Martes");
break;
case 3 :
printf("Mier, Miercoles");
break;
case 4 :
printf("Jue, Jueves");
break;
case 5 :
printf("Vie, Viernes");
break;
case 6 :
printf("Sab, Sabado");
break;
case 7 :
printf("Dom, Domingo");
break;
default :
printf("No existe");
}
return 0;
}

La estructura anterior, de realizarse con sentencias if , necesitaría cuatro de ellas, resultando un


enorme bloque muy difícil de leer. En la mayoría de los casos, además, la sentencia switch
proporciona una ganancia en velocidad del código, pues permite al compilador trabajar en base a
que se trata de una decisión múltiple para una única variable, cosa que con sentencias if el
compilador no tiene por qué detectar.
Como vemos, para cada valor de la variable se ejecuta un bloque de sentencias distinto, en el que
no necesitamos llaves. Hay un caso especial, default , que se ejecuta si ningún otro corresponde, y
que no es necesario poner. Es, en todo, equivalente al bloque else de una sentencia if .

Las sentencias break son muy importantes, ya que el comportamiento normal de un bloque
switch es ejecutarlo todo desde la etiqueta case que corresponda hasta el final. Por ello, si no
queremos que se nos ejecute más de un bloque, pondremos sentencias break al final de cada
bloque excepto el último.
Es decir, las etiquetas case son puntos de entrada de la ejecución, y no implican que al acabarse el
bloque case la ejecución salte al final del bloque switch . Las etiquetas case siguientes a la que
hemos utilizado para entrar son, sencillamente, ignoradas.
A la ausencia de sentencias break se le llama, en ocasiones, "dejar caer la cascada switch ".

El bucle while

El bucle while sirve para ejecutar código reiteradas veces.

while (/*condicion*/) {
/* Código */
}

La condición debe de ser una expresión lógica, similar a la de la sentencia if . Primero se evalúa la
condición. Si el resultado es verdadero, se ejecuta el bloque de código. Luego se vuelve a evaluar
la condición, y en caso de dar verdadero se vuelve a ejecutar el bloque. El bucle se corta cuando la
condición da falso.

El bucle for
El bucle for es un bucle muy flexible y a la vez muy potente ya que tiene varias formas
interesantes de implementarlo, su forma más tradicional es la siguiente:

for (/* inicialización */; /* condición */; /* incremento */) {


/* código a ejecutar */
}

Inicialización: en esta parte se inicia la variable que controla el bucle y es la primera sentencia que
ejecuta el bucle. Sólo se ejecuta una vez ya que solo se necesita al principio del bucle.
Expresión condicional: al igual que en el bucle while , esta expresión determina si el bucle
continuará ejecutándose o no.
Incremento: es una sentencia que ejecuta al final de cada iteración del bucle. Por lo general, se
utiliza para incrementar la variable con que se inicio el ciclo. Luego de ejecutar el incremento, el
bucle revisa nuevamente la condición, si es verdadera tiene lugar una ejecución más del cuerpo
del ciclo, si es falsa se termina el ciclo y así.

El bucle do...while
El bucle do...while es un bucle que, por lo menos, se ejecuta una vez. Do significa literalmente
"hacer", y while significa "mientras".
Su forma es esta:

do {
/* CODIGO */
} while (/* Condición de ejecución del bucle */)

Os muestro un ejemplo sencillo de uso:

int aleatorio;
do {
aleatorio = rand();
} while (aleatorio != 25);

La verdad es que este ejemplo puede resultar un poco absurdo, pero es bastante intuitivo. El
código del bucle asigna un valor aleatorio a la variable definida anteriormente, y mientras esa
variable no tenga el valor 25, el bucle sigue ejecutándose.

La sentencia goto
La sentencia goto sirve para indicar al programa que continue ejecutándose desde la línea de
código indicada. Su sintaxis es más o menos así:

/* Código */
ETIQUETA:
/* Código */
goto ETIQUETA;
/* Código */

Así, cuando se ejecute la sentencia goto , el programa "saltará" y continuará su ejecución a partir
de la etiqueta marcada.
Como se puede observar se puede usar para crear un bucle, o para ir a una parte del código u otra
si se combina con una sentencia if...else . Pero por lo general puede obtenerse el mismo efecto
utilizando los bucles anteriormente vistos.
Por eso, la sentencia goto es poco aceptada por la comunidad de programadores, pues puede
provocar que se hagan programas un poco "sucios" y confusos. Sólo en ocasiones muy
excepcionales será recomendado el uso del goto al crear iteraciones muy complejas. Sin embargo,
con el pasar de los años este comando ya ha quedado prácticamente descartado del lenguaje de
los programadores.

También podría gustarte