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

Я должен сделать программу, которая получает в качестве входных данных a и b, получает в качестве входных данных число "a" строк следующей формы: "studentId studentName studentPhone" и b строк ввода в виде "stId mark1 mark2 mark3 mark3". Затем программа выводит все данные из первого ввода, и если такой же идентификатор существует на входе 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;
}

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));

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

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

Как и сейчас, 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()?

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

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

С вашим кодом вы размещаете соответствующим образом.

Другие вопросы по тегам