Pro2324 Help

Bloque 1 - Conceptos Básicos

Introducción

La programación busca resolver problemas mediante la construcción de programas ejecutables en un * computador*.

Programa
  • Conjunto unitario de instrucciones que permite a una computadora realizar funciones diversas, como el tratamiento de textos, el diseño de gráficos, la resolución de problemas matemáticos, el manejo de bancos de datos, etc.

  • Codificación en cualquier lenguaje de programación específico de uno o varios algoritmos.

Computador

Máquina electrónica que, mediante determinados programas, permite almacenar y tratar información, y resolver problemas de diversa índole.

Los lenguajes de programación están diseñados de forma que sólo se requiere que los programadores indiquen sus intenciones explícitamente.

Algoritmos

Algoritmo

Conjunto ordenado y finito de operaciones que permite hallar la solución de un problema.

Condiciones necesarias:

  • Finitud.

  • No ambigüedad.

Propiedades deseables:

  • Generalidad.

  • Eficiencia.

  • Independencia del medio de ejecución.

Representación de algoritmos

  • Lenguaje natural.

  • Pseudocódigo.

  • Diagramas de flujo u ordinogramas.

  • Diagramas N-S (Nassi-Schneiderman).

  • Métodos formales matemáticos.

Diagramas de flujo u ordinogramas

Un diagrama de flujo es la representación gráfica de un algoritmo o proceso.

Forma

Nombre

Forma

Descripción

Línea de flujo

Línea de flujo

Flecha

Línea saliendo de un símbolo y apuntando a otro.

Terminal

Terminal

Óvalo

Inicio o fin de un programa o subprocesos.

Proceso

Proceso

​ Rectángulo

Conjunto de operaciones que cambian el valor, forma o ubicación de datos.

Decisión

Decisión

​ Rombo

​ Muestra una operación condicional que determina cuál de los dos caminos tomará el programa. La operación es comúnmente una pregunta de sí/no o una prueba de verdadero/falso.

Entrada

Entrada

​Paralelogramo

Proceso de hacer entrar datos​ en la forma de ingresar datos.

Salida

Salida

Hoja de papel impresa

Proceso de hacer salir datos, en la forma de mostrar resultados.

Pseudocódigo

Descripción de alto nivel compacta e informal del principio operativo de un programa informático u otro algoritmo.

Utiliza las convenciones estructurales de un lenguaje de programación real, pero está diseñado para la lectura humana en lugar de la lectura mediante máquina, y con independencia de cualquier otro lenguaje de programación.

Lenguajes de programación

Tipos de lenguajes de programación

Generaciones de los lenguajes de programación

  1. Primera generación: Lenguaje máquina.

  2. Segunda generación: Lenguajes de ensamblador.

  3. Tercera generación: Lenguajes de alto nivel.

    • Lenguajes compilados.

    • Lenguajes interpretados.

    • Lenguajes híbridos.

Lenguajes compilados y lenguajes interpretados

Ejecución de un programa compilado:

  • Se realiza previamente la compilación del programa fuente en la versión equivalente del programa en lenguaje máquina.

    • Esta versión se conoce como programa objeto.

  • El programa objeto se une, eventualmente, con los subprogramas de biblioteca descritos en el programa fuente para obtener el programa ejecutable.

    • Esto lo realiza el montador de enlaces (linker).

  • Se inica el programa ejecutable.

Ejecución de un programa interpretado:

  • Se iteran los siguientes pasos:

    • Obtención de la siguiente instrucción a ejecutar del código fuente.

    • Análisis de la instrucción y determinación de las acciones a ejecutar.

    • Ejecución de las correspondientes acciones.

Propiedades deseables de los lenguajes de programación

  • Claridad.

  • Buena definición.

  • Independencia de la máquina.

  • Notación estándar.

  • Niveles de abstracción.

  • Control de errores.

  • Verificación de programas.

Paradigmas de programación

  • Imperativa.

    • C, Pascal, Cobol, Fortran...

  • Orientada a Objetos.

    • Java, C++, C#, .NET...

  • Funcional.

    • LISP, Scheme, ML...

  • Lógica o declarativa

    • PROLOG...

  • Concurrente.

  • Tiempo real.

Instrucciones

  • Asignación: Evaluar una expresión y almacenar el resultado en una variable.

    • a = b + c.

  • Entrada/Salida: Transferencia de información con el exterior a través de dispositivos de entrada (teclado, ficheros, etc.) y salida (monitor, impresora, etc.).

    • printf, scanf...

  • Control de flujo:

    • Condiciones: if, if-else, switch...

    • Bucles: while, do-while, for...

  • Llamada y retorno de subrutinas: Dividir el programa en pequeñas unidades que se ejecutarán cuando convenga.

Elementos

  • Alfabeto: conjunto de símbolos válidos para construir textos en el lenguaje.

    • Palabras clave: if, else, while...

    • Caracteres: a... z, A... Z, #, ?...

    • Dígitos: 0... 9.

    • Otros símbolos: ., ,, ', ;, (), {}...

  • Léxico: vocabulario formado a partir del alfabeto.

  • Sintaxis: conjunto de reglas gramaticales que permiten derivar frases correctas en el lenguaje.

    • Notaciones para expresar las reglas:

      • Backus-Naur.

      • Grafo Sintáctico.

  • Semántica: conjunto de reglas que permiten derivar frases con sentido o significado en el lenguaje.

Notación BNF

Creada por J. Backus y P. Naur para describir la sintaxis del lenguaje ALGOL 60.

Para describir el lenguaje se utilizan reglas que se construyen con tres tipos de símbolos:

  • Metasímbolos: propios de la notación BNF.

  • Símbolos terminales: se usan en el texto del programa tal y como aparecen en la regla (sin comillas).

  • Símbolos no terminales: resto de símbolos. Se definen utilizando combinaciones de símbolos terminales, no terminales y metasímbolos

Metasímbolo

Significado

::=

Se define como

\|

Opción alternativa

(a \| b)

a ó b pero no ambos

[palabra]

0 ó 1 vez palabra

{palabra}

0 ó más veces palabra

'xyz'

Símbolo terminal

.

Final de la regla

Definición de un dígito con 10 reglas:

digito ::= '0'. digito ::= '1'. digito ::= '2'. digito ::= '3'. digito ::= '4'. digito ::= '5'. digito ::= '6'. digito ::= '7'. digito ::= '8'. digito ::= '9'.

Definición de un dígito con una única regla:

digito ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'.

Definición de un número entero:

entero_sin_signo ::= digito {digito}. signo ::= '+' | '-'. entero ::= [signo] entero_sin_signo.

Definición de un identificador:

identificador ::= letra { [ guion_bajo] (letra | digito) }

Diagramas de Conway

Herramienta gráfica para describir la sintaxis de un lenguaje.

Se utilizan también símbolos terminales y no terminales:

  • Símbolos terminales: se representan por un círculo o rectángulo redondeado.

  • Símbolos no terminales: se representan mediante un rectángulo.

Ambos símbolos se enlazan con flechas que indican el orden en que se debe realizar la interpretación de los diagramas.

Programas

Tipos de programas

  • Programas de aplicación.

  • Editores.

  • Compiladores.

  • Traductores.

  • Montadores de enlace (linkers).

  • Sistemas operativos.

  • Programas de servicio.

Sistema Operativo

Conjunto de programas que tienen como objetivo:

  • Facilitar la utilización del computador:

    • Acceso a los usuarios autorizados.

    • Edición de ficheros de texto.

    • Configuración y ejecución de programas.

    • Seguridad y protección

  • Gestión óptima de la máquina:

    • Gestión de memoria.

    • Control de dispositivos periféricos.

    • Acceso a ficheros.

    • Asignación de recursos y ordenación de tareas.

Elementos de un programa

Un programa se crea utilizando un alfabeto de símbolos (léxico) para construir:

  • Identificadores.

  • Etiquetas.

  • Directivas remotas, de interface y de implementación.

  • Constantes.

  • Números sin signo, números reales...

  • Cadenas de caracteres (strings) y variables.

Símbolos predefinidos

Símbolos predefinidos: conjunto de símbolos que constituyen el alfabeto del lenguaje.

En el caso de varios lenguajes de programación es el juego de caracteres ASCII.

Tabla ASCII de 7 bits:

  • Cada símbolo una posición.

  • Un número entero asociado a cada carácter.

  • Los códigos 0-31 y 127 no son imprimibles.

  • La diferencia entre el código ASCII de una letra mayúscula y su correspondiente minúscula es de 32.

Símbolos especiales

Símbolos especiales: símbolos con un significado especial dentro del lenguaje que se usan para representar delimitadores, operadores y otros elementos sintácticos.

special-symbol ::= '+' | '-' | '*' | '/' | '=' | '<' | '>' | '{' | '}' | '&' | ',' | ':' | ';' | '^' | '(' | ')' | '[' | '' | '<=' | '>=' | '==' | '..' | '!=' | word-symbol .

Palabras reservadas

Palabras reservadas (keywords) se utilizan para especificar nombres de instrucciones, funciones de librería, tipos de datos, operadores, etc.

  • No se pueden redefinir para usarlas como identificadores.

auto enum restrict* unsigned break extern return void case float short volatile char for signed while const goto sizeof _Bool* continue if static _Complex* default inline* struct _Imaginary* do int switch double long typedef else register union

Identificadores

Identificadores: son nombres que pueden utilizarse para denominar una función, una constante, una variable, un tipo, una función, una interfaz...

underscore ::= '_' . identifier ::= letter { [ underscore ] ( letter | digit ) } .

El nombre debe ser apropiado y tener un significado adecuado al uso destinado para el identificador.

Constantes

Constantes: identificadores que se corresponden a un valor constante que no varía durante la ejecución del programa.

constant-definition ::= identifier '=' constant-expression

Variables

Variables: identificadores que se corresponden a valores que pueden cambiar durante la ejecución de un programa, permaneciendo dentro del rango establecido para su tipo.

Cuando se declara una variable:

  • Se presenta el identificador, antes no existía.

  • Se reserva la memoria necesaria para el tipo de datos de la variable.

  • Se asocia el identificador con la dirección de memoria donde comienza.

  • Se asocia el identificador con una cierta interpretación de memoria.

No adoptan valores hasta que el programa se los asigna, por ello es fundamental inicializarlas:

  • En una instrucción de asignación.

  • En la declaración.

  • Mediante entrada por teclado.

  • Llamando a una función.

Los tipos de variable y valor tienen que ser los mismos o compatibles.

Comentarios

Comentarios: sirven para documentar los programas, y no ejecutan ninguna acción.

Los comentarios pueden intercalarse en cualquier lugar de un programa.

Los símbolos y formato de los comentarios dependen del lenguaje de programación utilizado.

Tipos de Datos y Operadores

Clasificaciones de los Tipos de Datos

Según sean sus constituyentes:

  • Simples.

    • Numéricos.

    • Caracteres.

    • Punteros.

  • Compuestos.

  • Estructurados.

  • No estructurados.

Según quien los haya definido:

  • Predeterminados.

  • Definidos por el usuario.

    • Enumerados.

Según la relación entre los valores de referencia:

  • Ordinales.

  • No ordinales.

Según la denominación:

  • Con nombre.

  • Sin nombre (Anónimos).

Tipos de Operadores

  • Aritméticos: proporcionan una ecuación para calcular un valor.

    • +, -, *, /, %.

  • Relacionales: comparan dos expresiones de tipo ordinal, real, cadena de caracteres o conjunto, obteniendo un resultado de tipo lógico.

    • <, >, <=, >=, == (igual), != (distinto).

  • Lógicos: evalúan una o más expresiones lógicas, obteniendo como resultado otro valor lógico.

    • && (AND lógico), || (OR lógico). ! (NOT).

  • Lógicos binarios: permiten manejar cada bit, de forma individual, en una palabra de memoria.

    • & (AND binario), | (OR binario), ^ ( XOR ).

Los distintos tipos de operadores tiene diferente precedencia y asociatividad que depende del lenguaje de programación.

Efectos secundarios

Se dice que una función o expresión tiene efecto colateral o efecto secundario si esta, además de retornar un valor, modifica el estado de su entorno.

Conversión de tipos

En una expresión de asignación o una operación, pueden existir operandos de distinto tipo.

En estas situaciones se realiza una conversion de tipos, que puede ser:

  • implicita si la realiza el propio compilador.

  • explicita si la realiza en programador (casting).

Para realizar una conversión explícita, (casting) se especifica el tipo de dato entre paréntesis delante de la expresión o variable a convertir.

Definición de tipos

Para crear un nuevo tipo de datos en C, se utiliza la palabra reservada typedef:

typedef tipo_de_datos nuevo_tipo;

Tamaño de los Tipos de Datos

El operador sizeof, devuelve el tamaño en bytes que ocupa un determinado tipo de datos o una variable.

Rangos de los Tipos de Datos

Rangos de los Enteros

Rangos en una máquina de 64 bits:

Tipo

Mínimo

Máximo

short int

–32,768

32,767

unsigned short int

0

65,535

int

–2,147,483,648

2,147,483,647

unsigned int

0

4,294,967,295

long int

–263

263–1

unsigned long int

0

264–1

Rangos de los Flotantes

Las características de float y double corresponden a un estándar IEEE:

Tipo

Mínimo

Máximo

Precisión

float

1.17549 × 10–38

3.40282 × 1038

6 digitos

double

2.22507 × 10–308

1.79769 × 10308

15 digitos

Por defecto, las constantes de números en punto flotantes se almacenan como números de doble precisión.

  • Para indicar que solo se desea una precisión simple se pone a letra F (o f) al final de la constante.

  • Para indicar que una constante debe almacenarse en un formato doble largo, se pone la letra L (o l) al final.

Tipo char

Cuando aparece un carácter (tipo char) en un cálculo, C usa su valor entero.

#include <stdio.h> int main() { int i; char ch; i='a'; /* i almacena el valor ascii de 'a', 97 */ ch= 65; /* ch almacena el valor acii 65, que corresponde a 'A' */ printf("%c %c %d %d\n" , i, ch, i, ch); return 0; }

La salida de este programa es: a A 97 65.

C permite trabajar a la vez como int y como char un carácter.

Notaciones comprimidas

Notación larga

Notación comprimida

a = a + b

a += b

a = a - b

a -= b

a = a * b

a *= b

a = a / b

a /= b

a = a % b

a %= b

a = a + 1

a++ o ++a*

a = a - 1

a-- o --a*

  • Las expresiones ++ y -- antes de la variable la modifican inmediatamente.

  • Las expresiones ++ y -- después de la variable devuelven su valor actual y luego la modifican.

int i; i = 1; printf("i es %d\n", --i); /* imprime "i es 0" */ printf("i es %d\n", i); /* imprime "i es 0" */ i = 1; printf("i es %d\n", i--); /* imprime "i es 1" */ printf("i es %d\n", i); /* imprime "i es 0" */

Entrada / Salida

Función printf

La función printf tiene asociado un formato: format string, seguido de los valores (variables que tienen que mostrarse por pantalla).

printf(string, expr1, expr2, ...);

La cadena de formato puede contener tanto caracteres ordinarios como especificaciones de conversión, que comienzan con el carácter %.

  • Una especificación de conversión es un marcador de posición que representa un valor que se debe completar durante la impresión.

    • %d se usa para valores enteros .

    • %f se usa para valores flotantes.

    • %c se usa para caracteres.

Los caracteres ordinarios en una cadena de formato se imprimen como aparecen en la cadena.

Ejemplo:

int i, j; float x, y; i = 10; j = 20; x = 12.3456f; y = 1234.0f; printf("i = %d, j = %d, x = %f, y = %f \n", i, j, x, y);

Salida:

i = 10, j = 20, x = 12.345600, y = 1234.000000

Consideraciones de conversión

Los compiladores no están obligados a:

  • Verificar que el número de especificaciones de conversión en una cadena de formato coincida con el número de elementos de salida.

printf ("%d %d \n", i); /* INCORRECTO */ printf ("%d \n", i, j); /* INCORRECTO */
  • Verificar que una especificación de conversión sea apropiada.

    • Si el programador usa una especificación incorrecta, el programa producirá una salida sin sentido.

/* i definido como int y x como float */ printf ("%f %d \n", i, x); /*INCORRECTO */

Una especificación de conversión puede tener la forma %m.pX o %-m.pX, donde m y p son constantes enteras y X es una letra que indica el tipo de dato.

  • m y p son opcionales.

    • Si se omite p, también se elimina el punto que separa m y p.

  • m, el ancho de campo mínimo, especifica el número mínimo de caracteres para imprimir.

    • Si el valor a imprimir requiere menos de m caracteres, se justifica a la derecha dentro del campo.

    • Poner un signo menos delante de m causa justificación a la izquierda.

    • Si el valor que se va a imprimir requiere más de m caracteres, el ancho del campo se expande automáticamente al tamaño necesario.

  • p indica el número mínimo de dígitos para mostrar.

    • Si se omite p, se supone que es 1.

Enteros
  • X es d.

  • Si p es más grande de lo necesario, se agregan ceros adicionales al comienzo del número.

Flotantes
  • X puede ser:

    • epara formato exponencial.

      • p indica cuántos dígitos deben aparecer después del punto decimal.

      • El valor predeterminado es 6.

      • Si p es 0, no se muestra ningún punto decimal.

    • f para formato decimal fijo.

      • p tiene el mismo significado que para el especificador e.

    • g para formato exponencial o formato decimal fijo, según el tamaño del número.

      • p indica el número máximo de dígitos significativos que se mostrarán.

      • La conversión g no mostrará ceros finales.

      • Si el número no tiene dígitos después del punto decimal, no muestra el punto decimal.

Ejemplos
#include <stdio.h> int main() { int x = 123; float y = 337.21f; printf("|%d|%5d|%-5d|%5.4d|\n", x, x, x, x); printf("|%+10.7f|%10.3e|%-10g|\n", y, y, y); return 0; }
|123| 123|123 | 0123| |+337.2099915| 3.372e+02|337.21 |

Secuencias de escape

El código \ que se usa en las cadenas de formato se llama secuencia de escape.

Las secuencias de escape permiten que las cadenas contengan caracteres no imprimibles (caracteres de control) y caracteres que tienen un significado especial.

Algunas secuencias de escape son:

  • \a: Alert (bell).

  • \b: Backspace.

  • \n: New line.

  • \t: Horizontal tab.

  • \": Permite incluir " dentro de una cadena.

  • \\: Permite incluir \ dentro de una cadena.

Función Scanf

scanf lee la entrada de acuerdo a un formato particular.

Una cadena de formato scanf puede contener tanto caracteres ordinarios como especificaciones de conversión.

  • Las conversiones permitidas con scanf son esencialmente las mismas que las utilizadas por printf.

scanf intenta hacer coincidir grupos de caracteres de entrada con las especificaciones de conversión en la cadena de formato.

  • Para cada especificación de conversión, intenta localizar un elemento del tipo apropiado en los datos de entrada, omitiendo espacios en blanco si es necesario.

  • Luego lee el elemento y se detiene cuando alcanza un carácter que no puede pertenecer al elemento.

  • Si el elemento se leyó correctamente, continúa procesando el resto de la cadena de formato.

  • Cuando busca un número, ignora los caracteres de espacio en blanco (espacio, tabulación horizontal y vertical, avance de página y nueva línea).

Conceptos básicos de macros

Directivas

La estructura básica de un programa en C es:

/* Directivas */ int main() { /* Expresiones*/ }

Antes de compilar un programa, primero lo edita un preprocesador.

Los comandos destinados al preprocesador se denominan directivas.

  • En C siempre comienzan con un #. Y no hay ; ni otro marcador especial al final.

Ejemplo:

#include <stdio.h>

<stdio.h> es un encabezado que contiene información sobre la biblioteca de E/S estándar de C.

Definición de macros

Mediante la directiva #define, se pueden definir costantes que utilizar en el resto del programa.

Por ejemplo, si se emplea varias veces el valor de π, se puede escribir:

#include<stdio.h> #define PI 3.1415926 int main() { float radio=0, circulo=0; scanf(“"ntroduzca el radio del círculo %f: ", &radio); circulo = 2*PI*radio; printf("La longitude del círculo es de: %f\n", circulo); return 0 }

El preprocesador del compilador sustituye PI por su valor (3.1415926) en todo el texto del programa.

Introducción a los Punteros

Variables tipo Puntero

El primer paso para comprender los punteros es visualizar lo que representan a nivel de máquina:

  • En la mayoría de las computadoras modernas, la memoria principal se divide en bytes, con cada byte capaz de almacenar ocho bits de información.

  • Cada byte tiene una única dirección.

  • Si hay n bytes en la memoria, se puede interpretar en las direcciones como números que van de 0 a n-1.

Cada variable en un programa ocupa uno o más bytes de memoria.

La dirección del primer byte se dice que es la dirección de la variable.

Las direcciones se pueden almacenar en variables de puntero especiales.

  • Cuando se almacena la dirección de una variable en una variable de puntero se dice que la variable puntero apunta a la otra variable.

Puntero
Variable
Contenido
Dirección

Declaración de punteros

Cuando se declara una variable de puntero, su nombre debe ir precedido por un asterisco *:

Ejemplo:

int *p;

p es una variable de puntero capaz de apuntar a objetos de tipo int.

Se usa el término objeto en lugar de variable, ya que p podría apuntar a un área de la memoria que no pertenece a una variable.

Las variables de puntero pueden aparecer en declaraciones junto con otras variables:

int i, j, a[10], b[20], *p, *q;

C requiere que cada variable de puntero apunte solo a objetos de un tipo particular (el tipo referenciado).

  • No hay restricciones sobre lo cual puede ser el tipo referenciado.

Operadores de Dirección e Indirección

C proporciona un par de operadores diseñados específicamente para su uso con punteros:

  • Para encontrar la dirección de una variable, se usa el operador & (dirección).

  • Para obtener acceso al objeto al que apunta un puntero (contenido), se usa el operador * (indirección).

Una forma de inicializar una variable de puntero es asignarle la dirección de una variable:

int i, *p; p = &i;

Asignar la dirección de i (&i) a la variable p hace que p apunte a i.

También es posible inicializar una variable de puntero en el momento en que se declara:

int i, *p = &i;
p
i
?
&i

Una vez que una variable de puntero apunta a un objeto, se puede usar el operador * (indirección) para acceder a lo que está almacenado en el objeto.

Si p apunta a i, se puede imprimir el valor de i de la siguiente manera:

printf("%d\n", *p);

Si varios punteros apuntan a la misma variable, se puede modificar el valor de esta variable mediante el operador de indirección * y de cualquiera de los punteros.

Cualquier número de variables de puntero puede apuntar al mismo objeto.

Last modified: 06 April 2024