Estoy leyendo una cadena de sdin con un scanf haciendo:
scanf("%[^\n]s", msg); %[^\n]s lee hasta que se encuentra un nuevo carácter de línea. ¿Es esto legal en ANSI-C?
No debe usar este formato por varias razones:
La s en "%[^\n]s" no es parte del especificador de conversión, es un carácter simple que scanf intentará hacer coincidir después de que los caracteres se lean de la línea, en un momento en que el carácter actual sea una nueva línea o el final del archivo. Deberías quitar la s .
scanf("%[^\n]", msg); fallará y devolverá 0, dejando msg sin cambios si el usuario presiona enter con una línea de entrada vacía.
scanf("%[^\n]", msg); provocará un desbordamiento de búfer para cualquier línea de entrada suficientemente larga. El número máximo de caracteres para almacenar en la matriz a la que apunta msg debe especificarse entre % y [ como:
char buf[100]; if (scanf("%99[^\n]", msg) == 1) { // msg contains the input line, up to 99 characters // the remainder if this input line is still in stdin // so is the newline } scanf("%99[^\n]", msg); no consume la nueva línea y deja caracteres adicionales en el flujo de entrada si se escribieron más de 99 antes de la nueva línea, lo que puede no ser el comportamiento esperado.
Aquí hay una alternativa más segura:
// read a line of input, discard extra characters and the trailing newline int mygets(char *dest, size_t size) { int c; size_t i = 0; while ((c = getchar()) != EOF && c != '\n') { if (i + 1 < size) { dest[i++] = c; } } if (size > 0) dest[i] = '\0'; if (c == EOF && (i == 0 || ferror(stdin))) return EOF; else return (int)i; }¿Es legal el especificador de formato %[^\n]s en C89?
Sí, es "legal", como en el comportamiento se definirá.
El %[^\n] escaneará cualquier cosa excepto un carácter de nueva línea. s escaneará un s . s nunca coincidirá, porque habrá una nueva línea en el búfer o una condición de error. Aún así, es "válido".