Programar en C, considerado "sucio"
Baltasar García Perez-Schofield

Baltasar García Perez-Schofield @baltasarq

About: Lecturer in programming since 1998

Location:
Spain
Joined:
Apr 14, 2019

Programar en C, considerado "sucio"

Publish Date: Jun 18
5 0

A terminal executing

El otro día me encontraba a mi mismo programando en C de nuevo. Quería ejercitar mis capacidades de bajo nivel creando newish, un pequeño terminal. En este momento, claro, las cosas aún están muy verdes.

El caso es que una de las cuestiones que tenía que abordar era el parsing del comando del usuario. Mi idea con newish es aplicar mis convicciones sobre que añadir espacios como parte del nombre de archivos es una mala idea, utilizando una convención (el carácter subrayado), en su lugar... solo cuando sea necesario. Es decir, para visualizaciones newish ignorará los subrayados, sustituyéndolos por espacios.

Así, dada la ejecución siguiente:

$ touch this_is_a_test.txt
$ ls
newish.c  parser.h   this_is_a_test.txt  util.h
parser.c  README.md  util.c ...
Enter fullscreen mode Exit fullscreen mode

newish lo mostrará de la siguiente manera:

$ newish
newiSH v0.1 20240801

/home/baltasarq/Prys/newish
~: cat
Makefile                f            782        2025-06-18 10:40:18
appinfo.c               f            498        2025-06-18 10:27:57
appinfo.h               f            265        2025-06-18 10:27:57
this is a test.txt      f              0        2025-06-18 10:48:03
error.h                 f           1062        2025-06-18 10:27:57
...
Enter fullscreen mode Exit fullscreen mode

La cuestión es que es necesario hacer el parsing del comando introducido por el usuario, como decía más arriba. Como no va a haber espacios en los nombres de los archivos, el parsing es trivial. Por ejemplo, en C# sería:

List<string> Parse(string cmd)
{
    return cmd.Trim().Split();
}
Enter fullscreen mode Exit fullscreen mode

Pero... ¿Y en C? En C volvemos a los viejos tiempos en cuanto a la manipulación de cadenas. Todas las cadenas tienen un tamaño fijo en memoria que en el caso del comando del usuario, se trata de 8191 caracteres (más el cero que marca el final).

Si no quieres utilizar el heap. como es mi caso (o al menos, tan poco como sea posible), tendrías que crear un vector de cadenas de caracteres. Cada una de estas cadenas tendría una longitud de... pues potencialmente, 8181 caracteres. Así que la idea sería crear, para tan solo el nombre del comando y nueve argumentos, unos 80 Kb de espacio. Si se quieren soportar más parámetros, el tamaño se dispara. ¿Qué podemos hacer?

La programación en bajo nivel, y aquí está la lección que aprendí, no es limpia. Tomemos como ejemplo strtok(cadena, delimitadores), que "divide" una cadena de caracteres en tokens... ¡añadiendo ceros en la propia cadena!

Efectivamente, si tenemos una cadena como la siguiente (el símbolo de dólar marca el final de la cadena, donde hay un cero), en el vector de caracteres cmd,

ls ../ -la$
Enter fullscreen mode Exit fullscreen mode

La transformación a realizar es la siguiente:

ls$../$-la$
Enter fullscreen mode Exit fullscreen mode

Crearíamos los siguientes punteros:

char * cmd_name;
char * args[MAX_CMD_ARGS];
Enter fullscreen mode Exit fullscreen mode

Y mantendríamos la siguiente estructura:

    cmd_name = cmd;
    args[ 0 ] = cmd + 3;
    args[ 1 ] = cmd + 7;
    args[ 2 ] = NULL;
Enter fullscreen mode Exit fullscreen mode

Es mucho más complejo, ¿no?... ¡Aunque también más divertido!

Comments 0 total

    Add comment