
C es un lenguaje de programación originalmente desarrollado por Dennis Ritchie entre 1969 y 1972 en los Laboratorios Bell,2 como evolución del anterior lenguaje B, a su vez basado en
Instalar minGW
Configurar variables de entorno
Compilar desde la consola
Instalar minGW
Configurar variables de entorno
Compilar desde la consola
Directivas del preprocesador
Declaraciones globales
La función main() ; int main()
Funciones definidas por el usuario
Comentarios del programa
Las directivas son instrucciones que se ejecuten antes de que se compile el programa.
Para crear una directiva se utilizan: #include y #define.
Siempre se utiliza el símbolo de almohadilla, numeral, “gatito”.
Las directivas NO son sentencias, no terminan con punto y coma.
Las directivas pueden definir macros, nombres de constantes, archivos fuente adicionales.
Las declaraciones globales indican al compilador que las funciones o variables definidas de esa forma son accesibles desde cualquier parte del programa.
Las declaraciones globales se definen antes de la función main(),
Las funciones declaradas como globales se les llama prototipos.
Las funciones definidas por el usuario ontan de una tarea única, son definidas entre llaves y pueden constar de una o varias sentencias.
No hay un número delimitado de funciones que se puedan declarar en un programa C.
Una función se llama o se invoca con su nombre y los paréntesis y los parámetros, si es que procede.
En C las funciones declaradas por el usuario es necesario un prototipo.
Los comentarios en C inician con /* y terminan con */
Todo lo escrito entre ambos símbolos el compilador no lo toma en cuenta.
Se pueden hacer comentarios entre una sola o varias líneas de texto.
Para definir una variable hay que describir el tipo de dato.
Se puede asignar su valor inicial.
Se puede utilizar un guión bajo en el nombre de la variable.
Declaración y asignación (opcional).
En C hay que declara las variables antes de ser utilizadas.
En C hay que declarar las variables antes del bloque que las utiliza.
Dependiendo de donde definamos la variables, puede tener un alcance o ámbito (scope) local o global.
Las variables locales son definidas en una función y sólo existen dentro de las llaves.
Terminando la función, las variables locales desaparecen.
Las variables globales son definidas fuera de una función y son “visibles” desde cualquier parte del programa, incluidas las funciones.
Se recomienda disminuir al máximo el uso de variables globales.
Para controlar los procesos de entrada y salida es necesario el encabezado stdio.h.
La salida por lo general es a pantalla y la entrada de datos es por medio del teclado.
La función principal de salida a pantalla es printf().
Su sintaxis es una cadena de control, separada por comas de los datos.
En esta clase puedes encontrar los apuntes de la sección 1
Una expresión es el conjunto de variables, constantes y literales (operandos) modificados por operadores que nos regresan un valor válido.
Si el operador necesita dos operandos, por ejemplo la suma, se le llama operador binario.
Si el operador funciona con sólo un operando se le llama operador unario.
Si el operador necesita tres operadores se le conoce como ternario.
Los operadores aritméticos siguen las reglas de la aritméticas tradicionales.
Los operadores multiplicativos (multiplicación, división y residuo) tienen mayor precedencia que los operadores aditivos (suma y resta).
Por medio de los paréntesis podemos cambiar la precedencia.
Los operadores + y - si se utilizan antes de un operando, tienen mayor precedencia y se consideran operadores unarios.
Las expresiones matemáticas entre paréntesis tienen prioridad sobre todos los operadores.
La asociatividad determina el origen en que se agrupan los operadores de igual prioridad, es decir, de izquierda a derecha o de derecha a izquierda.
Las subexpresiones entre paréntesis se evalúan en primer lugar según el modo estándar y los resultados se combinan para evaluar la expresión completa.
Si los paréntesis están anidados se ejecutan de los más internos a los menos internos.
Los operadores de incremento (++) y de decremento (--) suman o restan, respectivamente, una unidad a la variable.
c++ equivale a c = c + 1;
Estos operadores se pueden utilizar como prefijo o como sufijo.
Si los operadores están de prefijos, la operación de incremento o decremento se efectúa antes que la operación de asignación.
Si los operadores están de sufijos, la asignación se efectúa primero y el incremento o decremento a continuación.
C no tiene valores booleanas (true/false). En cambio tenemos el tipo entero (int) donde cero es falso y diferente a cero es verdadero.
Cuando se utilizan los operadores en una expresión, el operador relacional produce un 0 (falso) o un 1 (verdadero).
== igualdad
!= diferente
> mayor que
< menor que
>= mayor igual
<=menor que
Los operadores lógicos en C son ! (not), && (and) y || (or)
El operador condicional u operador ternario ? : regresa un valor dependiendo si la condición es verdadera o falsa.
Tiene asociatividad de derecha a izquierda.
Si el resultado de la expresión condicional es verdadero (diferente a cero) regresa el primer valor, si es falso (igual a cero) regresa el valor después de los dos puntos.
El operador coma permite combinar dos o más expresiones separadas por comas en una sola línea.
int a = 10, b = 20;
Se evalúa de izquierda a derecha.
Tiene la más baja prioridad de los operadores.
Determina el tamaño de un tipo de dato o variable que ocupa en memoria en bytes.
sizeof (variable)
sizeof (tipoDato)
sizeof (expresión)
El operador sizeof es unario.
Se le llama “conversión de tipos” cuando cambiamos el tipo de una variable sin cambiar su valor.
Existe la conversión implícita (automática) y la conversión explícita (realizada por el programador).
A la conversión explícita también se le llama “cast”:
(float) i;
(int) 3.4;
Apuntes dela sección 2: Operadores y expresiones
Las estructuras condicionales controlan el flujo de un programa.
Las estructuras condicionales combinan instrucciones o sentencias individuales en una simple unidad con una entrada y salida.
Se utilizan las llaves {} para agrupar las sentencias.
Una variación de la sentencia if es la palabra reservada “else”, que ejecuta una sentencia o bloque de sentencias si la condición es falsa (igual a cero).
Puede existir una sentencia if sin else, pero no puede haber un else sin if.
Si sólo hay una sentencia, tanto en if como en el else, se pueden omitir las llaves.
Las sentencias condicionales ifs se pueden anidar una dentro de otra tanto en el bloque de if o en el bloque else.
No hay límite en las sentencias anidadas.
Se recomienda no anidar más de tres estructuras condicionales.
También se siguen las reglas de las llaves cuando sólo hay una sentencia.
Por medio de la sentencia switch podremos seleccionar varias opciones de una variable o expresión simple.
A esta variable o expresión se le conoce como expresión de control o selector.
Esta expresión no puede ser double, float o string.
Debe ser int o char.
La sintaxis general de esta sentencia es:
Por medio de la sentencia switch podremos seleccionar varias opciones de una variable o expresión simple.
A esta variable o expresión se le conoce como expresión de control o selector.
Esta expresión no puede ser double, float o string.
Debe ser int o char.
El operador condicional u operador ternario ? : regresa un valor dependiendo si la condición es verdadera o falsa.
Tiene asociatividad de derecha a izquierda.
Si el resultado de la expresión condicional es verdadero (diferente a cero) regresa el primer valor, si es falso (igual a cero) regresa el valor después de los dos puntos.
Apuntes a la sección 3: Estructuras condicionales
Las estructuras cíclicas o bucles nos darán “músculos” a nuestros programas.
Son “parientes” de las estructuras de control, a diferencia que se repiten mientras la sentencia de control sea verdadera.
A cada repetición que se repitan se le llama “bucle”, “ciclo” o “iteración”.
Cuando la expresión condicional es falsa, se termina el bucle.
La sentencia do..while() primero se hace el bloque de sentencias y luego la expresión condicional .
También aplican las reglas de las llaves de las estructuras condicionales.
Cada repetición del bucle se llama “iteración”.
La representación del ciclo do..while es el siguiente:
El ciclo for se utiliza, principalmente, cuando sabes el valor de inicio, el valor final y el incremento.
Se puede contar con una o más variables de control del ciclo.
El ciclo for se forma de tres partes o expresiones:
Expresión de inicio: establece los valores iniciales de
Expresión de control: el ciclo se repetirá mientras esta expresión sea verdadera o diferente de cero.
Expresión de incremento o decremento: Modifica las variables de control del ciclo.
Por medio de la sentencia break podemos salir del ciclo o bucle.
Siempre se utiliza con una instrucción condicional.
Por medio de la sentencia continue repetimos el ciclo sin ejecutar las instrucciones abajo de ella.
También se utiliza con una instrucción condicional.
Podemos anidar varios ciclos.
Hay que tener cuidado en que no se confundan las variables de control.
La función puts() escribe la cadena apuntado por cadena en el stream apuntado por stdout, y añade un carácter de línea nueva a la salida. El carácter nulo final no es escrito.
La función putchar() la función retorna el carácter escrito.
Podemos utilizar las enumeraciones (enum) dentro de un ciclo for().
También podemos crear sentencias nulas en los ciclos for().
Apuntes sección 4: Estructuras cíclicas
Una función es un bloque de código de lenguaje C que no es ejecutado inmediatamente, sino que puede ser "llamado" o ejecutado desde el código "principal".
Una función es la definición de una "rutina" (o pequeño programa) , que se puede ejecutar una o varias veces.
La declaración de una función se le conoce como “prototipo”.
Un prototipo es la cabecera de la función, pero termina con punto y coma.
En algunos compiladores no es necesario el uso de prototipos, pero es una buena práctica.
Con los prototipos el compilador verifica las comprobaciones de las llamadas de las funciones.
Por medio de las tres puntos (...) podemos indicarle a una función, y a su prototipo, que se van a recibir un número indefinido de parámetros.
Para ello, necesitamos el archivo de cabecera <stdarg.h> con macros (funciones en línea).
Dentro de este archivo está definido el tipo de datos va_list.
La función va_start() inicializa el puntero para manejar la lista de datos pasada a la función.
va_start(va_list puntero,ultimofijo);
La función va_strart() inicializa el apuntador de tal forma que referencia al primer parámetro de la lista.
El segundo argumento es el último argumento fijo de la función que se está implementando.
Por omisión los parámetros en las funciones del lenguaje C se pasan por valor.
Si desea pasar un parámetro por referencia hay que utilizar un apuntador.
Para pasar una variable por referencia debemos utilizar & antes del nombre de la variable.
Una variable o parámetro apuntador se declara escribiendo el asterisco (*) antes del nombre de la variable.
Las funciones en línea son segmentos de código que el preprocesador las sustituye antes de compilar.
Son más rápidas que las funciones.
Se utilizan cuando la función es una expresión, su código es pequeño y es muy utilizado en el programa.
Con las macros aumenta el tamaño del código binario.
Si el programa llama x veces a la función en línea, el preprocesador copiará x veces el código.
Ámbito de programa
Ámbito del archivo
Ámbito de una función
Ámbito de bloque
Ámbito de programa
Ámbito del archivo
Ámbito de una función
Ámbito de bloque
Para manipular los caracteres tenemos el archivo de cabecera <ctype.h>
Las funciones de este archivo son:
isalpha(char)
islower(char)
isupper(char)
isdigit(char)
isxdigit(char)
isalnum(char)
Dentro del archivo de cabecera <ctype.h> también tenemos las siguientes funciones de prueba de caracteres especiales y de conversión:
isctrl(char)
isgraph(char)
isprint(char)
ispunct(char)
isspace(char)
tolower(char)
toupper(char)
Dentro del archivo de cabecera <ctype.h> también tenemos las siguientes funciones de prueba de caracteres especiales y de conversión:
isctrl(char)
isgraph(char)
isprint(char)
ispunct(char)
isspace(char)
tolower(char)
toupper(char)
sin (x), Seno de x
cos (x), Coseno de x
tan (x), Tangente de x
sinh (x), Seno hiperbólico de x
cosh (x), Coseno hiperbólico de x
tanh (x), Tangente hiperbólico de x
atan (x), Arcotangente de x
atan2 (x,y), Arcotangente de x e y
log (x), Logaritmo neperiano de x
log10 (x), Logaritmo decimal de x
rand(void): RAND_MAX en <stdlib.h>
srand(semilla): Inicializa el generador de número aleatorio. Se utiliza para el punto de inicio o semilla.
randomize: Inicializa la semilla con time
random(num): genera un número aleatorio entre 0 y num.
int abs(int num); Calcula el valor absoluto de un entero num. Si el resultado no puede ser representado, el comportamiento no está definido.
int atoi(const char *numPtr); Convierte la porción inicial de la cadena apuntada por numPtr a una representación de int.
double atof(const char *numPtr); Convierte la porción inicial de la cadena apuntada por numPtr a una representación de double.
Las funciones recursivas son funciones que dentro de su bloque de sentencias se llama o invoca a sí misma.
Hay que tener cuidado en no crear un ciclo infinito o recursión infinita.
Apuntes de la sección 5: Funciones
En el lenguaje C los arreglos sólo pueden contener un tipo de dato.
int enteros[6];
float precio[10];
Se puede acceder a un elemento por medio del índice.
printf(“%d”,enteros[2]);
El lenguaje C NO comprueba si el índice solicitado sobrepasó el tamaño del arreglo. Por lo general el compilador NO enviará un mensaje de error.
En el lenguaje C podemos crear arreglos de varias dimensiones.
Un arreglo de dos dimensiones también se le considera una “tabla”.
Cada dimensión se define entre corchetes.
int tabla[5][5];
No podemos definir con un solo corchete [5,5]
Para acceder a un elemento necesitamos un corchete por cada dimensión.
tabla[3][2] = 100;
En el lenguaje C los arreglos se pasan a las funciones por referencia, no por valor.
Si se modifica un arreglo en una función, los valores de los elementos en el arreglo se modifican.
Es como si utilizáramos el operador &.
Por lo general hay que pasar como parámetro el número de elementos del arreglo.
Una cadena es un arreglo de caracteres que terminan en un caracter nulo, NULL o \0.
El operador asterisco (*) a un apuntador a char se obtiene el caracter que forma su contenido.
Se puede acceder a un caracter con los corchetes y el índice.
La longitud de un arreglo es el número de caracteres más uno.
La función scanf() se termina cuando introducimos un espacio en blanco, por lo que no nos sirve para introducir cadenas.
Para introducir cadenas utilizamos la función gets().
Por medio de la función strlen() sabemos la longitud de la cadena.
int getchar(void); La función getchar podemos leer caracter por caracter. En caso de error de lectura o fin de archivo, regresará un EOF.
La función putchar(void) se utiliza en imprimir caracter por caracter. Es contraria a getchar().
La función puts() visualiza una cadena incluyendo el caracter nulo del final.
char *strcat(char*s1, const char *s2);
Añade una copia de la cadena apuntada por s2 (incluyendo el carácter nulo) al final de la cadena apuntada por s1. El carácter inicial de s2 sobrescribe el carácter nulo al final de s1.
char *strcat(char*s1, const char *s2);
Añade una copia de la cadena apuntada por s2 (incluyendo el carácter nulo) al final de la cadena apuntada por s1. El carácter inicial de s2 sobrescribe el carácter nulo al final de s1.
int strcmp(const char *s1, const char *s2);
Compara la cadena apuntada por s1 con la cadena apuntada por s2.
int strncmp(const char *s1, const char *s2, size_t n);
Compara no más de n caracteres (caracteres posteriores al carácter nulo no se tienen en cuenta) de la cadena apuntada por s1 con la cadena apuntada por s2.
char *strtok(char *s1, const char *s2);
Rompe la cadena s1 en segmentos o tokens.
Esta ruptura destruye s1, en el proceso.
La forma de romper la cadena depende de la secuencia de caracteres de la cadena s2.
Estos caracteres se denominan [caracteres] delimitadores.
La función recorrerá la cadena en busca de alguno de los delimitadores de la cadena s2.
Si necesitamos que el usuario capture primero un número con scanf() y luego una cadena con gets(), el código de [return] o [enter] se mantiene en el buffer interno, y no le dejará funcionar la función gets().
Podemos solucionarlo limpiando el buffer en el scanf().
La otra solución es utilizar dos gets() y convertir la cadena a entero con la función atoi() o atol().
Apuntes sección 6: Arreglos y Cadenas
Una estructura es una colección de diferente tipos de datos.
A cada elemento de una estructura se le llama miembro.
Una definición de una estructura es:
struct <nombreEstructura>
{
<tipoDato> <nombreMiembro>;
<tipoDato> <nombreMiembro>;
<tipoDato> <nombreMiembro>;
...
};
Para poblar o acceder a la información de un miembro de la estructura, podemos utilizar la notación punto o, por medio de un puntero, utilizar la flecha:
<variable estructura>.<miembro>
O
<puntero estructura>-><miembro>
Dentro de una estructura podemos utilizar otras estructuras.
Se consideran estructuras anidadas.
Accedemos a los datos por los puntos o por los apuntadores (punteros).
Podemos definir un arreglo de estructuras.
Accedemos a la información con el elemento del arreglo y la notación punto.
Podemos poblar las estructuras con las funciones scanf() y gets().
Podemos pasar las estructuras completas como parámetros por valor o por referencia.
Las uniones son estructuras que permiten almacenar diferentes elementos de diferente tipo en el mismo espacio, pero no en forma
union [<identificador>] {
[<tipo> <nombre_variable>[,<nombre_variable>,...]];
} [<variable_union>[,<variable_union>,...];
Todos los miembros de una unión ocupan el mismo espacio e inician en el mismo punto.
La longitud de una unión es su miembro más largo.
El operador sizeof() nos indicará la longitud de la unión en bytes.
Apuntes sección 7: Estructuras y Uniones
Apuntes de la sección 8:
Manejo de archivos
El lenguaje C maneja la información de los archivos mediante los flujos (stream).
Los flujos conducen los datos entre el archivo y el programa.
Entre el origen y el destino existe un canal (pipe).
La captación de los datos se realiza por medio de un buffer (memoria intermedia).
En el lenguaje C contamos con secuencia de texto y secuencias binarias.
En el programa, el archivo tiene un nombre interno que es un apuntador a una estructura FILE.
typedef struct{
short level;
unsigned flags,
char fd;
unsigned char hold;
short bsize;
unsigned char *buffer, *curp;
unsigned istemp;
short token;
} FILE;
La función fputc(), la cual es idéntica a putc(), escribe un caracter en el archivo apuntado por FILE.
Si falla la función, envía una constante EOF.
Las funciones fprintf() y fscanf() funcionan igual a las funciones printf() y scanf(), solo que escriben y leen los datos de un archivo.
Su primer parámetro es el apuntador del archivo.
Ambas funciones se encuentran en <stdio.h>
La función feof() devuelve diferente a cero si encuentra un fin de archivo EOF, y cero si no encuentra EOF.
char *fgets(char *cadena, int n, FILE *stream);
Esta función lee como máximo uno menos que el número de caracteres indicado por n desde el stream apuntado por stream al arreglo apuntado por cadena.
Ningún carácter adicional es leído después del carácter de nueva línea (el cual es retenido) o después de un final de fichero (EOF).
Un carácter nulo es escrito inmediatamente después del último carácter leído en el arreglo de caracteres (cadena).
Apuntes sección 9: Manejo de archivos
(Bubble Sort en inglés) es un algoritmo sencillo de ordenamiento.
Toma siempre un par de elementos del arreglo y si el primero es mayor al elemento de la derecha, se hace intercambio y se pregunta con el siguiente par de elementos.
Por ello los elementos más “ligeros” suben como “burbujas” en el arreglo.
El algoritmo es sencillo pero realiza muchas operaciones.
(Bubble Sort en inglés) es un algoritmo sencillo de ordenamiento.
Toma siempre un par de elementos del arreglo y si el primero es mayor al elemento de la derecha, se hace intercambio y se pregunta con el siguiente par de elementos.
Por ello los elementos más “ligeros” suben como “burbujas” en el arreglo.
El algoritmo es sencillo pero realiza muchas operaciones.
El ordenamiento por selección (Selection Sort en inglés) es ligeramente mejor al algoritmo de la burbuja.
En el caso de tener que ordenar un arreglo de enteros, esta mejora no es muy sustancial, pero cuando hay que ordenar un arreglo de estructuras más complejas, la operación sería más costosa.
Este algoritmo realiza muchas menos operaciones que el de la burbuja, por lo que lo mejora en algo.
Tomar el pivote el valor central
Pasar a la izquierda los valores menores al pivote
Pasar a la derecha los valores mayores al pivote
Repetir el proceso 1 con la lista de la izquierda
Repetir el proceso 1 con la lista de la derecha
Buscar el punto medio del arreglo.
Si el valor central es igual al buscado, detenemos la búsqueda.
Si el valor de buscado es mayor al valor central, buscas en el central + 1 al último de los elementos del arreglo.
Si el valor de buscado es menor al valor central, buscas en el central - 1 al primero de los elementos del arreglo.
Regresar al punto 1.
Apuntes de la sección 10: ejemplos de programas de lenguaje C
El lenguaje C es uno de los lenguajes básicos más exitosos. Muchos otros lenguajes como Java, C#, Objective C, JavaScript o PHP se basan en su sintaxis. C es un lenguaje de programación originalmente desarrollado por Dennis Ritchie entre 1969 y 1972 en los Laboratorios Bell . Este curso está orientado a los programadores que deseen introducirse en los principios del lenguaje C. Nuestros objetivos son:
Aprender a instalar el compilador del Lenguaje C y construirá programas básicos.
Comprender los tipos de datos y la creación de variables.
Construir estructuras condicionales y cíclicas.
Crear sus propias funciones y comprenderá el ámbito de las variables.
Manejar los arreglos, cadenas, estructuras y uniones que son estructuras de datos más complejas.
Aplicar los apuntadores y leerá y escribirá datos en archivos.
Realizar ejercicios para aplicar lo conocido en algoritmos como ordenación por burbujas, selección, inserción y quicksort.
Para tomar este curso debes tener una computadora con Windows 7 o superior, conexión a internet y un editor de código como SublimeText, Brackets, Dreamweaver, etc.
Contarás con los archivos fuentes terminados en cada una de las secciones y los apuntes de cada sección al final de la misma.
Incluye el eBook del curso.