Hasta ahora no he tenido problemas al leer desde este con cualquiera de las siguientes funciones (aunque prefiero la segunda):
Código
size_t leerLinea(char *arr, size_t tam) { int c = EOF; size_t i; if (!tam) return 0; arr[i] = c; arr[i] = '\0'; while (c != '\n' && c != EOF) return i; } size_t leerLinea(char *arr, size_t tam) { int c = (tam == 1) ? EOF : 0; return 0; }
Ambas leen tam - 1 caracteres y descartan todo lo que haya luego de los mismos, más sin embargo, aún tengo una duda... la cual creo que haría inútil las funciones anteriores.
Según he leído en las redes, stdin es un (FILE *) stream que, al parecer, sólo se encuentra en memoria; existe un módulo kernel que lo controla y le da un espacio en esta (independientemente del sistema operativo) para que allí, se almacene la información ingresada detrás de cada salto de línea ('\n').
Bien, si todo esto es cierto, me pregunto... ¿cómo acceder a esa zona de memoria? es decir, cómo obtengo esa dirección... la requiero para jugar un rato con la stdin, y ver si me puedo deshacer de las funciones anteriores, pues si logro acceder a esa zona de memoria, tras cada lectura de entrada (con un simple fgets() sin temor a dejar basura) puedo obtener lo que deseo; lo que no, simplemente lo re-escribo con ceros y así "limpio" de una forma más directa la entrada, o bien... almaceno todo lo que el usuario ha ingresado por la terminal y luego doy formato (mi real propósito)...
Lo que busco es, en síntesis, crear una función que reciba todo lo que se ha ingresado por la terminal sin desechar nada, y para eso... requiero saber la ubicación del búfer de stdin para así, como comenté anteriormente, almacenar todo lo que se ingrese... lo deseo hacer por ocio más que nada, sé que sí es posible, ya que la plataforma .NET lo hace... si declaramos un string, no es necesario definir su tamaño ni tampoco el tamaño de la cadena a leer, la plataforma .NET re-asigna memoria hasta lograr almacenar lo que el usuario ha ingresado, en caso de no haber memoria suficiente, lanza una excepción...
Bien, es eso a lo que quisiera llegar... porque sinceramente da pena el manejo de cadenas en C (aunque en C++ se ha mejorado bastante, no es tan eficiente como la plataforma .NET)...
Ya sé que no tiene mucho sentido hacer algo semejante, pues si al caso vamos, si no estamos escribiendo un editor de textos ni nada por el estilo, no es necesario un manejo dinámico de cadenas en C, pues simplemente se usa una de las funciones anteriores para obtener lo que el programa requiere, no lo que el usuario demande... pero mi curiosidad es más grande y como .NET parte de C++ (para C#), y C++ de C, supongo es lógicamente posible. (No quiero reinventar la rueda, simplemente quiero curiosear).
Cualquier información/sugerencia/crítica será bien recibida.
EDITO:
Tal parece que... leyendo un poco sobre punteros (aún no llego a dicho capítulo en el libro de K&R), logré escribir la siguiente función, la cual lee toda la entrada de teclado hasta el salto de línea, y reasigna memoria según necesite cada vez que se llenen 4kB de esta (tengo entendido que Windows y Linux dividen la memoria virtual en páginas de 4kB), es lo que estaba buscando... así pues, me evito problemas con dejar basura en la entrada y obtengo todo lo que el usuario ha ingresado, ya luego doy formato a esa entrada...
Código
char* leerLinea() { int c; size_t p4kB = 4096, i = 0; void *newPtr = NULL; { if (i == p4kB * sizeof (char)) { p4kB += 4096; ptrString = (char*) newPtr; else { return NULL; } } ptrString[i++] = c; } if (ptrString != NULL) { ptrString[i] = '\0'; } else return NULL; return ptrString; }
Como se puede observar, la función devuelve un puntero donde se ubica la lectura de la entrada del usuario hasta encontrar EOF o un salto de línea, el cual es reemplazado con un carácter nulo (fin de cadena). En caso de no poder reasignar memoria, libera la utilizada hasta el momento y retorna un puntero nulo. Finalmente si logra leer todos los caracteres y sobra memoria de la reservada, reasigna memoria para liberar todo el espacio sobrante.
Agradecería usuarios más experimentados me dieran sugerencias para modificar el código, no veo más formas de optimizarlo ni hacerlo más seguro... Ya comprobé que sí es POSIX. Y a mis exigencias, cumple con lo que necesito... espero que a alguien le sirva, pero si aún hay modificaciones que se puedan aplicar para mejorar el código, no duden en hacérmelas saber.