【问题标题】:Learning structures and arithmetic on their fields在他们的领域学习结构和算术
【发布时间】:2019-08-11 20:18:24
【问题描述】:

我现在正在学习结构,它们在我的脑海中很有意义,但我很难与它们一起工作。我正在使用重定向的标准输入('

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

}

输出:

【问题讨论】:

  • 我不明白这个问题。
  • @Joshua 我的问题是如何从标准输入读取结构,然后我可以对其进行一些操作,例如求和。我知道这不是很清楚抱歉!

标签: c struct scanf


【解决方案1】:

您正在使用来自结构的未定义成员的垃圾值覆盖*time[j] 中的值。将您收集的输入分配到结构中。 *time[j] = arrivals.time; 应该是 arrivals.time = *time[j];

变量a 也被声明为int *a,因此它没有成员计数和时间。语句scanf("%i %i", a-&gt;time, a-&gt;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;
}

如果一个输入失败,while 循环体将不会执行。您可以在循环外检查错误。

【讨论】:

  • 一旦你离开了这个while循环,你将如何访问和打印结构数组?带有 for 循环之类的东西 printf("arrival time: %d\tarrival count: %d ", arrival[j].time, arrival[j].count); ?
  • 就是这样。只要索引中有一个有效的arrival_struct 对象,它就应该可以工作。
  • 我似乎不断收到分段错误错误。你能检查我上面的编辑并可能指出我正确的方向吗?我认为是因为我在结构数组的某个地方超出了界限。
  • scanf 接受指针。使用&amp; 为结构成员添加前缀以将地址传递给scanf&amp;arrivals[i].count 和时间一样。
  • 请注意,用于 while 循环条件的数字未使用,这将导致奇怪的副作用。
【解决方案2】:

一般来说,我们会做这样的事情。我不喜欢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 */
}

【讨论】:

  • 您介意在上面的代码中添加一些 cmets 来解释一下吗? :)
  • @Mikel:应该会有帮助。
【解决方案3】:

虽然您已经有了一个很好的答案,但在您寻求了解结构的使用时,您可能会错过它们的大部分好处和用途。你声明你的结构,例如

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

虽然您可以在读取文件时简单地获取乘客人数,但您可能会在程序中的某个时间点读取数据,然后根据需要使用这些信息。因此,在将所有文件数据读入结构数组后,返回乘客数量的简单函数可以很简单:

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

将其完全放入一个简短的示例中,读取您可以执行的数据文件:

#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

如果您还有其他问题,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-18
    • 2019-07-29
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多