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%spara imprimir cadenas,%dpara 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()