I/O - E/S
Entrada y Salida (I/O)
El lenguaje de programación C proporciona varias formas de realizar tareas de entrada y salida (I/O). La entrada y salida son conceptos fundamentales en la informática, ya que permiten que los usuarios y aplicaciones externas interactúen con un programa para completar alguna acción.
De manera simple, la entrada se refiere a cualquier dato que se puede proporcionar a un programa en ejecución. Por otro lado, la salida es la información que el programa puede mostrar en la terminal o escribir en un archivo.
Entrada y Salida de Bajo Nivel
En C, las funciones de bajo nivel como read()
y write()
permiten realizar operaciones de entrada y salida directamente con descriptores de archivo (file descriptors). Estas funciones son útiles para leer datos desde archivos o desde la entrada estándar (stdin) y escribir datos en la salida estándar (stdout).
Por ejemplo, la función read()
lee datos arbitrarios hasta un número especificado de bytes y los almacena en un búfer. De manera similar, write()
se utiliza para enviar datos desde el programa hacia un destino, como la terminal o un archivo.
Entrada y Salida de Alto Nivel
Las funciones de alto nivel como fgets()
y printf()
son más comunes en aplicaciones C. Estas funciones proporcionan una interfaz más sencilla para trabajar con datos de entrada y salida.
fgets()
: Se utiliza para leer texto desde la entrada estándar o un archivo. Esta función detiene la lectura al encontrar un carácter de nueva línea (\n
) o al alcanzar un límite de bytes especificado.printf()
: Permite formatear y mostrar mensajes en la salida estándar. Utiliza especificadores de formato como%s
para imprimir cadenas,%d
para enteros, entre otros.
Estas funciones son ideales para trabajar con datos estructurados y para interactuar con los usuarios de manera más intuitiva.
Entrada y Salida de Bajo Nivel con Ejemplo
En C, las funciones de bajo nivel como read()
y write()
trabajan directamente con descriptores de archivo y manejan datos en forma de bytes crudos. Esto significa que no procesan los datos ni aplican formatos, simplemente leen o escriben los bytes tal como están.
Ejemplo de Uso
El siguiente ejemplo muestra cómo se pueden usar read()
y write()
para interactuar con el usuario a través de la entrada y salida estándar:
#include <unistd.h>
#include <string.h>
void demo_data()
{
// Mensaje inicial para el usuario
const char *prompt = "Enter data: ";
write(STDOUT_FILENO, prompt, strlen(prompt));
// Búfer para almacenar la entrada del usuario
char buffer[32] = {};
// Leer datos desde la entrada estándar
int n = read(STDIN_FILENO, buffer, sizeof(buffer));
// Mostrar los datos leídos al usuario
const char *output = "The program read in:\n";
write(STDOUT_FILENO, output, strlen(output));
write(STDOUT_FILENO, buffer, n);
}
Explicación del Código
-
write(STDOUT_FILENO, prompt, strlen(prompt));
Escribe un mensaje en la salida estándar (la terminal) para solicitar datos al usuario. -
read(STDIN_FILENO, buffer, sizeof(buffer));
Lee hasta 32 bytes de datos desde la entrada estándar (teclado) y los almacena en el búfer. -
write(STDOUT_FILENO, buffer, n);
Escribe los datos ingresados por el usuario de vuelta a la salida estándar.
Este enfoque es útil cuando se necesita un control preciso sobre los datos sin aplicar ningún procesamiento adicional, como el manejo de caracteres de nueva línea o el formateo de cadenas.
Python script para el challenge
import interact
import struct
p = interact.Process()
# Menú principal
p.readuntil('Enter Choice')
p.sendline('1') # Low Level IO
# Payload correcto (sin '!')
p.readuntil('Enter data:')
p.sendline(b'Hello\nWorld!\n\xC0\xDE\xF0\x0D')
# Entramos al quiz
p.readuntil('Press enter to start quiz...')
p.sendline('')
# Enviamos string literal exacto
p.readuntil('Enter Answer:')
p.sendline(b'Hello\nWorld!\n\xC0\xDE\xF0\x0D')
# Entramos en modo interactivo
p.interactive()