Entonces, después de scanf, el printf(); omite la primera línea
He leído algunas preguntas que dicen que "%[^\n]" debe ser " %[^\n]" para omitir la nueva línea.
Lo he intentado con ambos, pero todavía imprime el mismo resultado y ahora no sé por qué no funciona.

Example input
Enter number of Materi: 4
Materia 1 name : a
Materia 2 name : b
materia 3 name : c
materia 4 name : d

Output:
Materia - 1 : R╒fu
Materia - 2 : a
Materia - 3 : b
Materia - 4 : c
#include<stdio.h>
#include<windows.h>

int main(int argc, const char *argv[]){

    int i;
    int V;

    printf("Enter number of Materi: ");
    scanf("%d", &V); fflush(stdin);

    //Insert materia
    char materia[V][50];
    for(i = 0; i < V; i++){
        printf("Materia %d name : ", i+1);scanf("%[^\n]", &materia[i][50]);fflush(stdin);
    }

    for(i = 0; i < V; i++){
        printf("Materia - %d: %s\n", i+1, materia[i]);
    }
    system("pause");

    return 0;
}


1
Christian Halim 9 may. 2020 a las 18:34

3 respuestas

La mejor respuesta

Hay cuatro errores en el programa.

  • Las nuevas líneas en las que se detendrá el formato scanf "%[^\n]" ya son el siguiente carácter en el búfer de entrada.

  • fflush(stdin) no es estándar, aunque Windows lo admite, no es portátil. Pero no está utilizando Windows porque no admite el VLA char materia[V][50];

  • La matriz pasada a scanf es incorrecta.

  • Puede tener desbordamiento de búfer.

Aquí está el código ajustado:

#include<stdio.h>

int main(int argc, const char *argv[]){

    int i;
    int V;

    printf("Enter number of Materi: ");
    scanf("%d", &V);
    // remove fflush(stdin);

    //Insert materia
    char materia[V][50];
    for(i = 0; i < V; i++){
        printf("Materia %d name : ", i+1);
        // add a space to filter the newline
        // correct the array passed
        // and restrict the length to prevent buffer overflow
        scanf(" %49[^\n]", materia[i]);
        // remove fflush(stdin);
    }

    for(i = 0; i < V; i++){
        printf("Materia - %d: %s\n", i+1, materia[i]);
    }

    return 0;
}

Sobre las nuevas líneas. Las especificaciones de formato %d y %s y %f filtran automáticamente los espacios en blanco iniciales, pero %c y %[] y %n no lo hacen. Las funciones scanf se detienen en el primer carácter que no pueden convertir, que queda en el búfer de entrada. El %[^\n] le dice que se detenga en la primera línea nueva. Pero ya hay uno, desde el primer scanf %d y necesita ser eliminado, también en las iteraciones posteriores y agregar el espacio hace ese trabajo. Intentar eliminarlo después es torpe y no está garantizado para funcionar.

Idealmente, también debe probar el valor de retorno de scanf cada vez que se usa. Es la cantidad de elementos escaneados con éxito. Aquí, debería ser 1 en ambos usos.

2
Weather Vane 9 may. 2020 a las 16:12

Use fgets en lugar de scanf. El carácter de nueva línea se consume como un carácter en su scanf posterior. Por eso te enfrentas a este problema.

0
VHS 9 may. 2020 a las 15:37

En la linea:

scanf("%[^\n]", &materia[i][50]); 

Está almacenando la cadena de entrada en la dirección de materia[i][50], almacenándola efectivamente fuera de los límites de la matriz, use:

#include<stdlib.h>

//...

if(scanf(" %49[^\n]", materia[i] != 1) {
   puts("Read error");
   return EXIT_FAILURE;       
}

49 caracteres + el terminador nul para evitar el desbordamiento, un espacio al comienzo del especificador evita el consumo de caracteres en blanco que quedan en el búfer stdin. Siempre verifique scanf volver para evitar errores de lectura.

Aquí sucede algo interesante, el almacenamiento de matriz 2D es contiguo como si fuera un vector unidimensional, lo que sucede es que está almacenando la primera cadena al comienzo de la segunda línea de la matriz, la segunda en la tercera y así sucesivamente, dejando el Primero vacio. Ese es el racional para la salida que produce el programa.

Algunos otros problemas:

  • fflush(stdin) debe eliminarse ya que fflush debe llamarse en una secuencia de salida.

  • Las matrices de longitud variable pueden causar el desbordamiento de la pila si se consume suficiente memoria, en este caso no es probable, pero es algo a tener en cuenta.

1
anastaciu 9 may. 2020 a las 16:39