Изучение структур и арифметика на своих полях - PullRequest
1 голос
/ 21 марта 2019

Я сейчас изучаю структуры, и они имеют смысл в моей голове, но мне трудно работать с ними. Я читаю файл с использованием перенаправленного стандартного ввода ('<'). Я свободно работал над примером, чтобы помочь мне лучше понять его, но просто не вижу ожидаемого результата. Это всего лишь небольшой пример, который я привел, который должен моделировать час прибытия автобуса и количество людей в автобусе. Не обращая внимания на время для ясности, я пытаюсь добавить все количество людей, которые ездят по автобусу, и напечатать это. Пример входных данных: </p>

2 2
6 1
7 4
8 2
8 9

и я запускаю его через a.out < input.txt

#include <stdio.h>
#include <stdlib.h> // for malloc() and exit()

struct arrival_struct
{
    int time;       // time of arrival
    int count;      // number of passengers/seats arriving
};

int main(void) {

    struct arrival_struct arrivals;
    int *time[10]; // stores # of batches for passenger arriving at the same time
    int code;
    int totalPassenger=0;
    int i;
    int  *a; //dynamic memory base address
    int required[10]; // stores # of passenger arrive at the same time in batch
    int j=0;

    // read in code until eof
    while (scanf("%d", &code) !=EOF) {
        //load the first token into time[j]
        scanf("%d", *time[j]);
        *time[j] = arrivals.time;
        //load the second token into required[j]
        scanf("%d", required[j]);
        required[j] = arrivals.count;
        //increment totalPassenger by the count token that was read in
        totalPassenger = totalPassenger + required[j];

        a=(int *)malloc(sizeof(int)*required[j]); //required[j] should be the number of passengers for that row
        scanf("%i %i", a->time, a->count);
        j++;
    }
    printf("total passengers: %d", totalPassenger);

}

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

time: 2   count: 2   totalPassengers: 2
time: 6   count: 1   totalPassengers: 3
etc ..

Извините, если это трудно понять, я очень плохо знаком с языком и пытаюсь догнать своих сверстников. Если мой вопрос не ясен, пожалуйста, просто свяжите меня или объясните простое чтение из стандартного ввода и заполнение структуры.

РЕДАКТИРОВАТЬ:

struct arrival_struct {
    int time;
    int count;
};

int main(void) {
    int code;
    int totalPassenger=0;
    struct arrival_struct arrivals[10];
    int i=0;
    int j;
    while (scanf("%d", &code) !=EOF) {

        scanf("%d%d", arrivals[i].time, arrivals[i].count);
        totalPassenger += arrivals[i].count;
        i++;
    }
    printf("total passengers: %d", totalPassenger); //works
    for (j=0;j<5;j++)
        printf("time: %d\tcount: %d\n", arrivals[j].time, arrivals[j].count);

}

вывод: enter image description here

Ответы [ 3 ]

2 голосов
/ 21 марта 2019

Вы переопределяете значение в *time[j] значением нежелательной почты из неопределенного члена структуры.Назначьте вход, который вы собрали в структуру.*time[j] = arrivals.time; должно быть arrivals.time = *time[j];.

Также переменная a была объявлена ​​int *a, поэтому она не имеет количества членов и времени.Оператор scanf("%i %i", a->time, a->count); выдаст синтаксическую ошибку.

Более понятный способ отслеживания состоит в объявлении массива arrival_struct и определении структур при сборе ввода.

struct arrrival_struct arrivals[10];

while(...) {
scanf("%d%d", &arrivals[j].time, &arrivals[j].count);
totalPassenger += arrivals[j].count;
j++;
}

РЕДАКТИРОВАТЬ

while (scanf("%d%d", &arrivals[j].time, &arrivals[j].count) != EOF){
totalPassenger += arrivals[j++].count;
}

Если произойдет сбой одного входа, тело цикла не будет выполнено.Вы можете проверить наличие ошибок вне цикла.

0 голосов
/ 21 марта 2019

Хотя у вас уже есть хороший ответ, в своем стремлении понять использование структур вы, возможно, упускаете большую часть их пользы и использования.Вы объявляете свою структуру, например,

struct arrival_struct {
    int time;       // time of arrival
    int count;      // number of passengers/seats arriving
};

Затем вы можете просто объявить массив структуры для хранения каждого компонента, прочитанного из каждой строки из файла, и обойтись без множества дополнительных переменных.Например, вы можете просто объявить:

 #define MAXS 10     /* if you need a constant, #define one (or more) */
 ...
    struct arrival_struct arrivals[MAXS] = {{ .time = 0 }};

, который объявит массив 10 struct arrival_struct и инициализирует все значения на ноль.

Тогда, вместо того, чтобы рискнуть попасть во многие ловушкиscanf, гораздо лучше читать по одной строке данных за раз с помощью строчно-ориентированного ввода , например fgets (или POSIX getline), а затем анализировать информацию из заполненного буферав необходимые значения.Таким образом, то, что остается в вашем входном потоке, не зависит от спецификатора преобразования пользователя или от сбоя совпадения .

Просто объявите буфер символов достаточного размераудерживать каждую строку ( Не экономьте на размере буфера! ) и считывайте каждую строку в буфер.Затем проанализируйте необходимые значения в строке с помощью sscanf, например,

#define MAXC 1024
...
    size_t n = 0;
    char buf[MAXC];

    /* while array space remains, read each line from file into struct */
    while (n < MAXS && fgets (buf, sizeof buf, stdin))
        if (sscanf (buf, "%d %d", &arrivals[n].time, &arrivals[n].count) == 2)
            n++;

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

size_t getpassengercount (struct arrival_struct *s, size_t n)
{
    size_t count = 0, i;
    for (i = 0; i < n; i++)
        count += s[i].count;

    return count;
}

Поместить их в краткий краткий пример чтения вашего файла данных вы можетеdo:

#include <stdio.h>

#define MAXS 10     /* if you need a constant, #define one (or more) */
#define MAXC 1024

struct arrival_struct {
    int time;       // time of arrival
    int count;      // number of passengers/seats arriving
};

size_t getpassengercount (struct arrival_struct *s, size_t n)
{
    size_t count = 0, i;
    for (i = 0; i < n; i++)
        count += s[i].count;

    return count;
}

int main(void) {

    struct arrival_struct arrivals[MAXS] = {{ .time = 0 }};
    size_t n = 0;
    char buf[MAXC];

    /* while array space remains, read each line from file into struct */
    while (n < MAXS && fgets (buf, sizeof buf, stdin))
        if (sscanf (buf, "%d %d", &arrivals[n].time, &arrivals[n].count) == 2)
            n++;

    printf ("total passengers: %zu\n", getpassengercount (arrivals, n));
}

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

$ ./bin/passengercnt <dat/passengers.txt
total passengers: 18

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

0 голосов
/ 21 марта 2019

Вообще говоря, мы делаем что-то подобное. Мне не нравится scanf для ввода, но это другая тема. Неправильный ввод не обрабатывается, потому что я не исправлю scanf обработку ввода.

/* dynamically allocated array of structs */
struct arrival_struct *arrivals = NULL;
size_t narrivals = 0; /* number of elements used */
size_t aarraivals = 0; /* number of elements allocated */

while (...)
{
    if (narrivals == aarrivals) {
        /* If we're out of space in the array, double the size. Initial size is 16 */
        arrivals = realloc(arrivals,
            sizeof(*arrivals) * (
                aarrivals = (aarrivals == 0) ? 16 : (aarrivals << 1)
            )
        );
    }
    /* read input */
    scanf("%d", &arrivals[narrivals].time);
    scanf("%d", &arrivals[narrivals].count);
    // ...
    ++narrivals; /* one more usable element in array */
}
...