Logo DIE

Fundamentos de Lenguaje C

Unidad de Apoyo para el Aprendizaje

Iniciar

Introducción


Una vez que un problema dado ha sido analizado, donde se identifican los datos de entrada y la salida deseada, que se ha diseñado un algoritmo que lo resuelva de manera eficiente (procesamiento de datos), y que se ha representado el algoritmo de manera gráfica o escrita (diagrama de flujo o pseudocódigo), se puede proceder a la etapa de codificación.

La codificación se puede realizar en cualquier lenguaje de programación estructurada, como Pascal, Python, Fortran o PHP. En este curso se aprenderá el uso del lenguaje de programación C.

En del ciclo de vida del software, la implementación de un algoritmo se encuentra dentro de la etapa de codificación del problema. Esta etapa va muy unida a la etapa de pruebas:

Esquema

Ciclo de vida del software, resaltando las etapas de codificación y pruebas.



Elaborar programas en lenguaje C, utilizando las instrucciones de control de tipo secuencial, para realizar la declaración de variables de diferentes tipos de datos, así como efectuar llamadas a funciones externas de entrada y salida, que permitan asignar y mostrar valores de variables y expresiones.

Lenguaje de programación C


Los lenguajes de programación son lenguajes creados por el ser humano para poder comunicarse con las computadoras; así, podríamos decir que lenguaje de programación es el conjunto de símbolos y palabras que permiten al usuario de una computadora darle instrucciones y órdenes para que la computadora los ejecute.

Esquema

El proceso de desarrollo del lenguaje C se origina con la creación de un lenguaje llamado BCPL, creado por Martin Richards.

BCPL tuvo influencia en un lenguaje llamado B, usado en 1970 e inventado por Ken Thompson.

Esto permitió el desarrollo de C en 1971, cuya invención e implementó fue Dennis Ritchie.




C es un lenguaje de programación de propósito general que ofrece como ventajas economía de expresión, control de flujo y estructuras de datos y conjunto de operadores.


Es también, un lenguaje de propósito general basado en el paradigma estructurado.


El teorema del programa estructurado demostrado por Böhm-Jacopini, dicta que todo programa puede desarrollarse utilizando únicamente 3 instrucciones de control:


Secuencia, Selección, Iteración



Por otro lado, C es un lenguaje compilado, es decir, existe un programa (llamado compilador) que, a partir de un código en lenguaje C, genera un código objeto (ejecutable).

Para crear un programa en C se siguen tres etapas principales:



Esquema



El lenguaje C está basado en el concepto de funciones. Un programa C es una colección de una o más funciones, en donde cada una tiene un nombre y una lista de argumentos. Una de estas funciones se llama main (principal). El programa siempre comenzará por la ejecución de la función main, la cual debe escribirse seguida de paréntesis de la siguiente manera: main()

Al momento de ejecutar un programa objeto (código binario), se ejecutarán únicamente las instrucciones que estén definidas dentro de la función main. La función main puede contener sentencias, estructuras de control y comentarios. Dentro de las sentencias se encuentran la declaración y/o asignación de variables, la realización de operaciones básicas y las llamadas a funciones.

Licencia GPL de GNU

El software que se utilizará en esta UAPA es libre, bajo la licencia GPL de GNU, es decir, se puede modificar y distribuir mientras se mantenga la licencia GPL.

/*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Jorge A. Solano
*
*/





Sintaxis básica




Para programar correctamente en lenguaje C, se deben seguir ciertas reglas o normas (sintaxis), ya que, si no las respetamos, los programas no compilarán correctamente y marcarán errores. Por todo esto es importante conocer la sintaxis básica del lenguaje C.

Como ya comentamos, todo programa en C consta de uno o más módulos llamados funciones y una de estas funciones se llama:

main

Función que siempre debe existir, ya que será por la que el programa comenzará su ejecución; desde esta función se puede acceder a las demás.

Las instrucciones elementales, también denominadas instrucciones de expresión o sentencias, deben terminar en un punto y coma.



Esquema



Si se necesita crear funciones o bloques de código se utilizan las llaves { } para delimitar dónde comienza y termina dicho bloque o función. Dado que main es una función, su sintaxis completa deberá ser de la siguiente manera:

main(){
}

Esquema


Directivas de preprocesador

Las directivas para el preprocesador aparecen siempre al comienzo de los programas. Se identifican por su primer carácter, que es el carácter almohadilla o numeral (#). Estas directivas le indican al compilador que incluya en el código fuente, el código fuente contenido en los archivos dentro de ‘<‘ y ‘>’. Se utilizan para indicarle al programa que utilice funciones predefinidas en las bibliotecas del lenguaje. La más común es la biblioteca stdio.h, de la que hablaremos más adelante.



Comentarios

Es una buena práctica en cualquier lenguaje de programación realizar comentarios para documentar el programa.



Esquema


Cabe resaltar que el comentario por bloque puede abarcar varios renglones.

Ejemplo

// Comentario por línea
// Otro comentario por línea
/* Comentario por bloque */
/* Comentario por bloque
    que puede ocupar
    varios renglones */

Código con comentarios

#include <stdio.h>

main() {
   // Este código compila y ejecuta
   /* pero no muestra salida alguna
      debido a que un comentario
      ya sea por línea o por bloque */
   // no es tomado en cuenta al momento
   // de compilar el programa,
   /* sólo sirve como documentación en el */
   /*
      código fuente
   */
}

Nota: Al iniciar el programa se deben agregar todas las bibliotecas que se van a utilizar en el mismo, es decir, funciones externas necesarias para ejecutar el programa. En lenguaje C la biblioteca estándar de entrada y salida está definida en 'stdio.h' (standard input - output) y provee, entre otras, funciones para lectura y escritura de datos que se verán a continuación.

Identificadores


Los identificadores son nombres que se les da a algunos elementos de un programa, como variables, funciones y arreglos. Los identificadores se crean especificándolos en las declaraciones; de este modo, se puede utilizar dicho identificador en las sentencias posteriores del programa para referirnos a los elementos asociados a él.

Los identificadores siguen estas reglas:



Esquema


Como norma general, un identificador debe tener los suficientes caracteres para que su significado se reconozca fácilmente, pero se debe evitar un excesivo número de caracteres.



Nota: A pesar de que los identificadores 'areadeltriangulo' o 'perimetro_del_cuadrado' son declaraciones válidas, es una buena práctica utilizar la notación CamelCase para nombrar las variables como convención.



En la notación CamelCase, los nombres de cada palabra empiezan con mayúscula y el resto se escribe con minúsculas (a excepción de la primera palabra, la cual inicia también con minúscula). No se usan puntos ni guiones para separar las palabras; además, las palabras de las constantes se escriben con mayúsculas y se separan con guion bajo.



Palabras reservadas

Hay ciertas palabras reservadas que tienen en un significado predefinido estándar. Las palabras reservadas sólo se pueden utilizar para su propósito ya establecido; no se pueden utilizar como identificadores definidos por el programador. En lenguaje C son las siguientes:

auto

double

int

struct

break

else

long

switch

case

enum

register

typedef

char

extern

return

union

const

float

short

unsigned

continue

for

signed

void

default

goto

sizeof

volatile

do

if

static

while

Palabras reservadas.

Se puede observar que todas las palabras reservadas están en minúsculas. Como los caracteres en minúsculas y mayúsculas no son equivalentes, se puede utilizar una palabra reservada escrita en mayúsculas como un identificador.

Sin embargo, esto no se suele hacer normalmente, ya que al igual que el uso de los guiones bajos (excepto para constantes), se considera propio de un estilo de programación pobre.

Tipos de datos

El lenguaje C ofrece distintos tipos de datos, cada uno de los cuales se puede encontrar representado de forma diferente en la memoria de la computadora.

Tipo

Descripción

Espacio en Memoria

Rango

int

Cantidad entera

2 bytes o una palabra (varía de un compilador a otro)

-32 767 a 32 767

char

Caracter

1 byte

-128 a 127

float

Número en punto flotante (un número que incluye punto decimal y/o exponente)

1 palabra (4 bytes)

3.4E-38 a 3.4 E38

double

Número en punto flotante de doble precisión (más cifras significativas y mayor valor posible del exponente)

2 palabras (8 bytes)

1.7E-308 a 1.7E308

Algunos tipos básicos de datos se pueden ampliar utilizando los cualificadores de tipos de datos short (corto), long (largo), signed (con signo) y unsigned (sin signo). Por ejemplo, se pueden definir cantidades enteras como short int, long int o unsigned int.

Si se omite el clasificador por defecto se considera 'signed'. Los datos de tipo flotante o doble siempre tienen signo.



Declaración de variables

Iniciar

VARIABLE

Es un identificador que se utiliza para representar cierto tipo de información dentro de una determinada parte del programa.

En alguna parte del programa se asigna el dato a la variable. Este valor se puede recuperar después en el programa con simplemente hacer referencia al nombre de la variable.

A una variable se le pueden asignar diferentes valores, sin embargo, el tipo de datos asociado a la variable no puede cambiar.



Para declarar variables en C se tiene la siguiente sintaxis:

[modificadores] tipoDeDato identificador [= valor];

Por lo tanto, una variable puede tener modificadores (estos se analizarán más adelante y son opcionales); debe declarar el tipo de dato que puede contener la variable; debe declarar el identificador (nombre o etiqueta) con el que se va a manejar el valor y se puede asignar un valor inicial a la variable (opcional).

También es posible declarar varios identificadores de un mismo tipo de dato e inicializarlos en el mismo renglón; lo único que se tiene que hacer es separar cada identificador por comas.

tipoDeDato identificador1[= valor], identificador2[= valor];

Código con declaración de variables



Esquema

Modificadores de alcance


Los modificadores que se pueden agregar al inicio de la declaración de variables son const y static.

El modificador const impide que una variable cambie su valor durante la ejecución del programa, es decir, permite crear constantes. Por convención, las constantes se escriben con mayúsculas y se deben inicializar al momento de declararse.

Ejemplo:

const int NUM_MAX = 1000;
const double PI = 3.1415926535897933;

El modificador static indica que la variable permanece en memoria desde su creación y durante toda la ejecución del programa, es decir, permanece estática en la memoria.

Ejemplo:

static int num;
static float resultado = 0;

Nota: Cuando se llegue al tema de funciones se verá la utilidad de las variables estáticas.



Código variables estáticas y constantes



Esquema

Entrada y salida de datos


Se puede acceder a una función de entrada/salida de datos desde cualquier parte de un programa con simplemente escribir el nombre de la función, seguido de una lista de argumentos entre paréntesis. Los argumentos representan los datos que le son enviados a la función. Algunas funciones de entrada/salida no requieren argumentos, pero deben aparecer los paréntesis vacíos.

La mayoría de las versiones de C incluyen una colección de archivos de cabecera que proporcionan la información necesaria para las distintas funciones de biblioteca. Cada archivo contiene generalmente la información necesaria para la utilización de un determinado grupo de funciones de biblioteca.

Estos archivos se incluyen en un programa mediante la instrucción #include al comienzo del programa. Como norma general, el archivo de cabecera requerido para la entrada/salida estándar se llama stdio .h

La biblioteca 'stdio.h' contiene diversas funciones, tanto para imprimir en la salida estándar (monitor) como para leer de la entrada estándar (teclado).

Se pueden escribir datos en el dispositivo de salida estándar, utilizando la función de biblioteca printf.

En términos generales, la función printf se escribe:



printf(cadena de control, argl, arg2, argn)



En donde cadena de control hace referencia a una cadena de caracteres que contiene información sobre el formato de la salida y argl, arg2, ... , argn son argumentos que representan los datos de salida.

Los argumentos pueden ser constantes, variables simples o nombres de arreglos o expresiones más complicadas.

En la cadena de control se incluyen grupos individuales de caracteres, con un grupo de caracteres por cada dato.

Cada grupo de caracteres debe comenzar con el signo de porcentaje (%).

En su forma más sencilla, un grupo de caracteres estará formado por el signo de porcentaje, seguido de un carácter de conversión que indica el tipo de dato correspondiente.

Dentro de la cadena de control, los diferentes grupos de caracteres pueden estar seguidos o pueden estar separados por caracteres de espaciado (espacios en blanco, tabuladores o caracteres de nueva línea).



Carácter de conversión

Significado

c

El dato es visualizado como un carácter

d

El dato es visualizado como un entero decimal con signo

e

El dato es visualizado como un valor en coma flotante con exponente

f

El dato es visualizado como un valor en coma flotante sin exponente

g

El dato es visualizado como un valor en coma flotante utilizando la conversión tipo e o tipo f según sea el caso. No se visualiza no los ceros finales ni el punto decimal cuando no es necesario

i

El dato es visualizado como un entero con signo

o

El dato es visualizado como un entero octal, sin el cero inicial

s

El dato es visualizado como una cadena de caracteres

u

El dato es visualizado como un entero decimal sin signo

x

El dato es visualizado como un entero hexadecimal sin el prefijo 0x

Caracteres de conversión de los datos de salida de uso común [tabla], basada en Gottfried, 1997, Programación en C (p. 102).



Nota: Las cadenas de caracteres se manejarán cuando se aborde el tema de arreglos.



Ejemplos:



Esquema


Para imprimir con formato también se utilizan algunas secuencias de caracteres de escape. C maneja los siguientes:



Esquema



Se pueden leer datos desde el dispositivo de entrada estándar, utilizando la función de biblioteca scanf.

La función scanf se puede utilizar para introducir cualquier combinación de valores numéricos, caracteres individuales y cadenas de caracteres. Es análoga a la función printf, con la diferencia de que su propósito es introducir datos en lugar de visualizarlos.

En términos generales, la función se escribe:

scanf(cadena de control, argl, arg2, ... , argn)

Donde cadena de control hace referencia a una cadena de caracteres que contiene cierta información sobre el formato de los datos y argl,arg2,..., argn son argumentos que representan los datos.

Carácter de conversión

Significado

c

El dato es un carácter

d

El dato es un entero decimal

e

El dato es un valor en coma flotante

f

El dato es un valor en coma flotante

g

El dato es un valor en coma flotante

h

El dato es un entero corto

i

El dato es un entero decimal, octal o hexadecimal

o

El dato es un entero octal

s

El dato es una cadena de caracteres seguida de un carácter de espaciado (se añade automáticamente el carácter nulo \0 al final)

u

El dato es un entero sin signo

x

El dato es un entero hexadecimal

Caracteres de conversión de los datos de entrada de uso común [tabla], basada en Gottfried, 1997, Programación en C (p. 92).



Los argumentos pueden ser variables o arreglos y sus tipos deben coincidir con los indicados por los grupos de caracteres correspondientes en la cadena de control. Cada nombre de variable debe ser precedido por un ampersand( & ); sin embargo, los nombres de arreglos (se verán en lecciones posteriores) no deben ir precedidos por el ampersand.

Esquema


Código almacenar e imprimir variables

Esquema




Operadores


En C existen varios tipos de operadores, como los siguientes:

Aritméticos, unarios, relacionales, lógicos y de asignación

Los operadores aritméticos que maneja lenguaje C se describen en la siguiente tabla:


Operador

Operación

Uso

Resultado

+

Suma

125.78+62.5

188.28

*

Resta

65.3-32.33

32.97

*

Multiplicación

8.27*7

57.75

n

/

División

15/4

3.75

%

Módulo

4%2

0

Los operadores lógicos a nivel de bits que maneja el lenguaje C se describen en la siguiente tabla:


Operador

Operación

Uso

Resultado

>>

Corrimiento a la derecha

8>>2

2

<<

Corrimiento a la izquierda

8<<1

16

&

Operador AND

5&4

4

|

Operador OR

3|2

3

~

Complemento ar-1

~2

1

Los operandos que difieren en el tipo pueden sufrir una conversión de tipo antes de que la expresión alcance su valor final. En general, el resultado final se expresará con la mayor precisión posible, de forma consistente con los tipos de datos de los operandos.

Si los dos operandos son tipos en punto flotante con precisión distinta (por ejemplo, un float y un double), el operando de menor precisión se transformará a la precisión del otro operando y el resultado se expresará con esta mayor precisión.



Conversión de tipos o cast

Si se desea, se puede convertir el valor resultante de una expresión a un tipo de datos diferente. Para hacer esto, la expresión debe ir precedida por el nombre del tipo de datos deseado, encerrado con paréntesis; esto es:

(tipo de datos) expresión

Este tipo de construcción se denomina conversión de tipos (cast).

Ejemplo:

Esquema


Código operadores



Esquema


Precedencia de operadores

Los operadores de C se agrupan jerárquicamente de acuerdo a su precedencia (su orden de evaluación). Las operaciones con mayor precedencia se efectúan antes que las que tienen menor precedencia; sin embargo, se puede alterar el orden natural de evaluación mediante el uso de paréntesis.

Los operadores aritméticos, *, / y % se encuentran dentro de un mismo grupo de precedencia, y + y - se encuentran en otro. El primer grupo tiene mayor precedencia que el segundo.

Por lo tanto, las operaciones de multiplicación, división y resto se efectuarán antes que las de suma y resta.

Otra consideración importante a tener en cuenta es el orden en que se efectuarán operaciones consecutivas dentro del mismo grupo de precedencia. Esto se conoce como asociatividad. Dentro de cada uno de los grupos de precedencia descrito anteriormente, la asociatividad es de izquierda a derecha.

En otras palabras…

Las operaciones consecutivas de suma y resta se efectúan de izquierda a derecha, así como operaciones consecutivas de multiplicación, división y módulo.

La precedencia natural de las operaciones se puede alterar mediante el uso de paréntesis, permitiendo estos que se puedan efectuar operaciones aritméticas de una expresión en el orden que se desee. También se pueden anidar los paréntesis, es decir, un par dentro de otro. En estos casos se efectúan primero las operaciones más internas.

Ejemplo:

(a - b) / (c * d)

A veces es una buena idea utilizar paréntesis para hacer más clara una expresión, aunque no sean necesarios. Por otra parte, se deben evitar en lo posible expresiones sobrecargadas.



Operadores unarios

C incluye una clase de operadores que actúan sobre un solo operando para producir un nuevo valor. Estos operadores se denominan operadores unarios o monarios. Los operadores unarios suelen preceder a su único operando, aunque algunos operadores unarios se escriben detrás de su operando.

El operador unario de uso más frecuente es el menos unario, que consiste en un signo menos - delante de una constante numérica, una variable o una expresión. La operación menos unaria es distinta del operador aritmético que representa la resta (-). El operador resta requiere dos operandos.

Ejemplo:

-743 -raíz -2.5 - (a*5)

Otros dos operadores unarios de uso frecuente son el operador incremento, + +, y el operador decremento, - -.

El operador incremento hace que su operando se incremente en uno, mientras que el operador decremento hace que su operando se decremente en uno. El operando utilizado con cada uno de estos operadores debe ser una variable simple.

++i es equivalente a escribir i = i + 1
- - i es equivalente a escribir i = i – 1

Los operadores incremento y decremento se pueden utilizar de dos formas distintas, dependiendo de si el operador se escribe delante o detrás del operando.

Si el operador precede al operando (por ejemplo ++i), el valor del operando se modificará antes de que se utilice con otro propósito.

Sin embargo, si el operador sigue al operando (por ejemplo, i++), entonces el valor del operando se modificará después de ser utilizado.

Ejemplos:

Esquema


Esquema

Expresiones lógicas


Las expresiones lógicas están constituidas por números, caracteres, constantes o variables que están relacionados entre sí por operadores relacionales o lógicos. Una expresión lógica puede tomar únicamente los valores verdadero o falso.

Los operadores relacionales permiten comparar elementos numéricos, alfanuméricos, constantes o variables.

Operador

Operación

Uso

Resultado

==

Igual que

'h' == 'M'

Falso

!=

Diferente a

'a'!= 'b'

Verdadero

<

Menor que

7<15

Verdadero

>

Mayor que

11>15

Falso

<=

Menor o igual

15<=22

Verdadero

>=

Mayor o igual

20>=35

Falso

Los operadores lógicos permiten formular condiciones complejas a partir de condiciones simples.

Operador

Operación

Uso

!

No

!p

&&

Y

a>0&&a<11

||

O

opc == 1 || salir !=0

Los operadores lógicos actúan sobre operandos que son a su vez expresiones lógicas. Permiten combinar expresiones lógicas individuales, formando otras condiciones lógicas más complicadas que pueden ser verdaderas o falsas.

Ejemplo:
(a>b) && (c

Nota: Lenguaje C maneja los resultados booleanos (verdadero o falso) con números enteros. Cuando el resultado de una comparación es falso, el valor regresado es cero. Cuando la comparación es verdadera, el valor regresado es 1



Código expresiones lógicas

Esquema


Operadores de asignación

Existen varios operadores de asignación en C. Todos se utilizan para formar expresiones de asignación, en las que se asigna el valor de una expresión a un identificador.

El operador de asignación más usado es =

Las expresiones de asignación que utilizan este operador se escriben de la siguiente forma:



identificador = expresión



Donde identificador representa generalmente una variable y expresión una constante, una variable o una expresión más compleja.

Nota: Se debe recordar que el operador de asignación = y el operador de igualdad == son distintos. El operador de asignación se utiliza para asignar un valor a un identificador, mientras que el operador de igualdad se usa para determinar si dos expresiones tienen el mismo valor. No se pueden utilizar estos operadores de forma indistinta.



C posee, además, los cinco siguientes operadores de asignación:

+=, - =, *=, /= y %=

En donde…

expresión 1 += expresión 2
es equivalente a
expresión 1 = expresión 1 + expresión 2

Y de igual forma para los cinco operadores.

<
ícono

Actividad 1. Mi primer programa con variables

Ahora que ya aprendiste cómo declarar variables, operar con ellas e imprimir su contenido, en esta actividad elaborarás un programa en el que pongas a prueba lo aprendido, corrigiendo los errores que presente el programa.

ícono

Actividad 2. Programa para conversión de unidades

Ahora que ya has aprendido el correcto uso de variables, operadores y funciones de entrada y salida, realizarás un programa, cuyo objetivo sea resolver un problema cotidiano. En este caso será un sencillo convertidor de unidades entre sistemas de medición.

ícono

Autoevaluación. Fundamentos de lenguaje C

Los lenguajes de programación al estar conformados por un conjunto de símbolos y palabras permiten al usuario dar instrucciones para que sean ejecutadas por la computadora.

El lenguaje C se fundamenta en el concepto de funciones. Un programa C es una colección de una o más funciones, en donde cada una tiene un nombre y una lista de argumentos.


Fuentes de información

Básicas

Kernighan, B., Ritchie, D. (1991). El lenguaje de programación C. Ciudad de México: Pearson Educación.

Documentos electrónicos

Solano, J., García, E., Sandoval, L., Nakayama, A., Arteaga, I. y Castañeda, M. (2016). Manual de prácticas del laboratorio de Fundamentos de programación. Facultad de Ingeniería. Consultado de http://lcp02.fi-b.unam.mx



Cómo citar


Arteaga, T. I. y Nakayama, M. A. (2018). Fundamentos de lenguaje C. Unidades de Apoyo para el Aprendizaje. CUAED/Facultad de Ingeniería-UNAM. Consultado el (fecha) de (vínculo)