Ошибка Сегментации из-за добавления одного маленького 2d массива - PullRequest
1 голос
/ 04 октября 2019

Я создал небольшую тестовую программу, потому что та же проблема возникала в моей более крупной программе. Я новичок в c, так что, может быть, я чего-то не понимаю. моя программа просит пользователя ввести количество студентов и количество курсов, которые они хотели бы добавить. Затем я создаю двумерный массив с размером, равным количеству студентов по количеству курсов. этот 2d массив вызывает ошибку сегментации, когда я тестирую программу, в которой участвуют только 4 студента и 4 курса, то есть должно быть только 16 элементов. Я не уверен, почему это вызывает ошибку сегмента.

int registry[][] - это рассматриваемый массив

Я протестировал программу с массивом 2d и без него, и он прекрасно работает без него.

int main (void) {

    int numOfStds;
    int numOfCrs;
    int stdNum;

    printf("How many students would you like to register:");
    scanf("%d", &numOfStds );

    printf("How many courses are in the program?:");
    scanf("%d", &numOfCrs);

    int students[numOfStds];
    char courses[numOfCrs][8];
    for(int i; i < numOfStds; i++){
        printf("Please enter student %d's number:", i);
        scanf("%d", &stdNum);
        students[i] = stdNum;
    }

    for(int i; i < numOfCrs; i++){
        printf("Please enter course %d's code (must be 7 characters long):", i);
        scanf("%s", courses[i]);

    }
    int registry[numOfStds][numOfCrs];

    for(int i; i< numOfCrs; i++){
        printf("%s\n", courses[i]);
    }

    for(int i; i < numOfStds; i++){
        printf("%d\n", students[i]);
    }
}

Ответы [ 2 ]

0 голосов
/ 04 октября 2019

Как отмечено в моих комментариях, у вас есть две основные проблемы. Строка формата scanf ("%d/n", ...) является неправильной, если пользователь фактически не вводит "/n" после каждого ввода и секунды, ваша переменная цикла неинициализируется в каждом цикле for.

Но еще большее беспокойство вызывает неудача проверить возвращение scanf при каждом вызове, поэтому один неверный символ может привести к тому, что ваше целочисленное преобразование завершится неудачно, и вы продолжите, как будто ничего не случилось. Например, если при достижении 3 ваш пользователь случайно нажмет 'e', то произойдет сопоставление-сбой , извлечение символа из stdin остановится в этой точке, и если вы зацикливаете сбор целочисленного вводаВы только что завернули в бесконечный цикл.

Всегда проверяйте каждый вход

Требуется всего лишь простая проверка, чтобы спасти себя от себя. Чтобы проверить введенные вами данные, вы можете сделать:

    printf("How many students would you like to register: ");
    if (scanf ("%d", &numOfStds) != 1) {
        fputs ("error: invalid integer input - numOfStds.\n", stderr);
        return 1;
    }

и для другого примера:

    for(int i = 0; i < numOfStds; i++){
        printf ("Please enter student %d's number: ", i+1);
        if (scanf("%d", &stdNum) != 1) {
            fputs ("error: invalid integer input - stdNum.\n", stderr);
            return 1;
        }
        students[i] = stdNum;
    }

Собрать все вместе в полном примере, а затем вывести собранные значения, которые вы можете сделать:

#include <stdio.h>

int main (void) {

    int numOfStds;
    int numOfCrs;
    int stdNum;

    printf("How many students would you like to register: ");
    if (scanf ("%d", &numOfStds) != 1) {
        fputs ("error: invalid integer input - numOfStds.\n", stderr);
        return 1;
    }

    printf("How many courses are in the program?: ");
    if (scanf ("%d", &numOfCrs) != 1) {
        fputs ("error: invalid integer input - numOfCrs.\n", stderr);
        return 1;
    }

    int students[numOfStds];
    char courses[numOfCrs][8];

    for(int i = 0; i < numOfStds; i++){
        printf ("Please enter student %d's number: ", i+1);
        if (scanf("%d", &stdNum) != 1) {
            fputs ("error: invalid integer input - stdNum.\n", stderr);
            return 1;
        }
        students[i] = stdNum;
    }

    for(int i = 0; i < numOfCrs; i++){
        printf("Please enter course %d's code (must be 7 characters long): ",
                i+1);
        if (scanf ("%7s", courses[i]) != 1) {
            fputs ("error: invalid integer input - numOfCrs.\n", stderr);
            return 1;
        }
    }

    /* example output */
    // int registry[numOfStds][numOfCrs];
    puts ("\nStudents:");
    for (int i = 0; i < numOfStds; i++)
        printf ("student: %d\n", students[i]);
    puts ("\nCourses:");
    for (int i = 0; i < numOfCrs; i++)
        printf ("course: %s\n", courses[i]);
}

( примечание: выше защиты границ вашего массива с if (scanf ("%7s", courses[i]) != 1), если вы не включили 7 в качестве поля модификатор ширины , ваш пользователь может ввести столько символов, сколько пожелает, что приведет к неопределенному поведению)

Пример использования / Вывод

$ ./bin/numofstds
How many students would you like to register: 3
How many courses are in the program?: 2
Please enter student 1's number: 301
Please enter student 2's number: 302
Please enter student 3's number: 303
Please enter course 1's code (must be 7 characters long): abcdefg
Please enter course 2's code (must be 7 characters long): bcdefgh

Students:
student: 301
student: 302
student: 303

Courses:
course: abcdefg
course: bcdefgh

Просмотрите всеи дайте мне знать, если у вас есть дополнительные вопросы.

0 голосов
/ 04 октября 2019

Во всех ваших циклах for вы используете индексную переменную i неинициализированной. Это может вызвать неопределенное поведение. Поскольку поведение не определено, наличие или отсутствие массива registry может изменить поведение.

Вы должны инициализировать i в каждом цикле for следующим образом:

    for(int i = 0; i < numOfStds; i++){

Я также повторю обеспокоенность, высказанную в ответе Дэвида . Если вы вызываете функцию, которая возвращает статус, вы всегда должны проверять статус, чтобы убедиться, что это то, что вы ожидаете. Всегда лучше обрабатывать ошибки, как только они возникают. Ваш код в том виде, в котором он написан, не допускает ошибок при вводе, что в общем случае недопустимо. Это не теоретическая проблема. Практические приложения всегда могут столкнуться с неверным или искаженным вводом.

...