c- Странное поведение после получения входных данных

Я должен сделать программу, которая получает на вход a и b, получает на вход число "a" строк следующего вида: "studentId studentName studentPhone" и b строк ввода в виде "stId mark1 mark2 mark3". Затем программа выводит все stid из первого ввода, и если такой же идентификатор существует во вводе b, программа выводит оценки учащихся помимо своего идентификатора.

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

Это мой код: (здесь я пытаюсь ввести только идентификаторы учащихся. http://ideone.com/dBYzwe )

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>


void chomp(char *s);

struct listA{
    int stId;
    char stName[19];
    char stPhone[12];

    };

struct listB{
    int stId;
    char marks[11];

};


int main(void) {
    int i, j, m, n;

    scanf("%d%d", &m, &n);

struct listA *a = malloc(sizeof(m * sizeof(struct listA)));
    struct listB *b = malloc(sizeof(n * sizeof(struct listB)));

    for(i = 0; i < m; i++)
    {
        scanf("%d", &a[i].stId);
        fgets(a[i].stName, 19, stdin);
        fgets(a[i].stPhone, 11, stdin);
        chomp(a[i].stName);
        chomp(a[i].stPhone);

    }
    for(i = 0; i < m; i++)
            printf("%d ", a[i].stId);


    for(i = 0; i < n; i++)
    {
        scanf("%d ", &b[i].stId);
        fgets(b[i].marks, 12, stdin);
        fflush(stdin);
    }

    printf("\n");


        for(i = 0; i < n; i++)
    {
        printf("%d ", b[i].stId);
    }


    printf("\n");

    for(i = 0; i < m; i++)
            printf("%d ", a[i].stId);




    return 0;









}
void chomp(char *s) {
    while(*s && *s != '\n' && *s != '\r') s++;

    *s = 0;
}

person Arlind    schedule 11.11.2013    source источник
comment
a не является массивом, тогда почему вы используете a[i]?   -  person Shubham    schedule 11.11.2013
comment
Вы на MS Windows? И какой компилятор вы используете?   -  person haccks    schedule 11.11.2013
comment
Я забыл умножить sizeof на m и n, чтобы они оба были массивами. Я только что сделал это, и он все еще меняет значения первого ввода после того, как я получу второй ввод.   -  person Arlind    schedule 11.11.2013
comment
@hackks У меня Windows, но я запустил его на ideone.com (проверьте ссылку)   -  person Arlind    schedule 11.11.2013
comment
использование fflush(stdin); (кроме MS DOS) приведет к неопределенному поведению.   -  person haccks    schedule 11.11.2013
comment
Неопределенное поведение: Приложение J The stream for the fflush function points to an input stream or to an update stream in which the most recent operation was input (7.21.5.2).   -  person haccks    schedule 12.11.2013


Ответы (3)


Проблема в

struct listA *a = malloc(sizeof(m * sizeof(struct listA)));
struct listB *b = malloc(sizeof(n * sizeof(struct listB)));

Результатом m * sizeof(struct listA) является целое число, поэтому, когда вы помещаете его в sizeof, вы получаете размер целого числа, а не число, которое вы хотите. Вы должны изменить это на:

struct listA *a = malloc(m * sizeof(struct listA));
struct listB *b = malloc(n * sizeof(struct listB));
person Dan    schedule 11.11.2013

Первая проблема заключается в том, что у вас неправильное распределение памяти (это может быть решением вашей проблемы, а может и нет, но это определенно то, что вы должны исправить).

Malloc принимает в качестве параметра количество байтов памяти для выделения и возвращает указатель на выделенную память или нуль, если это не удалось.

Как и сейчас, struct listA *a = malloc(sizeof(*a));, вы выделяете место для объекта (вы объявили a как указатель на объект и выделяете размер объекта a в байтах). Вам нужно выделить память для массива объектов, который имеет n*sizeof(*a) байт, сохраняя то, как вы его написали. Вы должны проверить, возвращает ли malloc значение null.

Кроме того, будьте осторожны, так как вы можете превысить размер stPhone/stName/marks.

Не рекомендуется использовать fflush, если он вам действительно не нужен, особенно для входных потоков: http://www.gidnetwork.com/b-57.html

fgets(b[i].marks, 12, stdin);

Вы уверены, что строка с метками имеет не более 12 символов? Я бы рекомендовал использовать другой способ чтения ввода, как описано здесь: Как читать из ввода, пока не будет найдена новая строка с помощью scanf()?

person Paul92    schedule 11.11.2013
comment
Не может быть более 12 символов, потому что максимальное количество отметок 3 может быть не более 100, включая пробелы, оно не может превышать 12. То же самое касается stPhone и stName. - person Arlind; 12.11.2013

Вы должны выделить достаточно памяти для a и b как

struct listA *a = malloc(sizeof(*a)* m);
struct listB *b = malloc(sizeof(*b) * n);

С вашим кодом вы правильно распределяете.

person Rohan    schedule 11.11.2013