处理fscanf()

处理fscanf(),c,arrays,string,data-structures,scanf,C,Arrays,String,Data Structures,Scanf,我有一个结构简单的文件: {number}\# {一些带有行的文本} \# 问题是我需要一个程序来读取这个文件中的每个条目。这意味着此结构会多次出现 因此,我的第一个想法是创建一个结构数组,某种形式的struct my_struct abc[MAX]最大值是预处理器定义 我希望fscanf将{number}存储为数组的编号,将{some_text_with_line}存储为struct数组中的字符串。所以每个数组都有自己的字符串 其思想是fscan读取以下格式:%d\r\n%s\r\n\r\n,

我有一个结构简单的文件:
{number}\#
{一些带有行的文本}
\#

问题是我需要一个程序来读取这个文件中的每个条目。这意味着此结构会多次出现

因此,我的第一个想法是创建一个结构数组,某种形式的
struct my_struct abc[MAX]<代码>最大值
是预处理器定义

我希望
fscanf
将{number}存储为数组的编号,将{some_text_with_line}存储为struct数组中的字符串。所以每个数组都有自己的字符串

其思想是fscan读取以下格式:
%d\r\n%s\r\n\r\n
,并使用第一个整数%d作为数组的编号。类似于&abc[%d]。
虽然我知道它的语法是错误的,但我不知道如何读取这个数字%d并将其用作数组的数字。%s也有问题,它没有\0


因此,我需要一些帮助,提前谢谢。

做如下操作:

int index;
char array[1024][1024];               // big array :)

while(fscanf(file, "%d#\r\n", &index) == 1) {
  fscanf(file, "%s\r\n", array[index]);
  int c; 
  while ((c = fgetc(file)) != EOF && c != '\r') { }
  fgetc(file);                          // read '\n'
}

这个代码有效。它将接受文件中段落的任意列表,并且每个段落中的行集也可以具有任意长度

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

struct data
{
    int     number;
    char  **lines;
    int     num_lines;
    int     max_lines;
};

int main(void)
{
    struct data *info = 0;
    int   num_entries = 0;
    int   max_entries = 0;
    char line[4096];

    while (fgets(line, sizeof(line), stdin) != 0)
    {
        int number;
        char hash;
        if (sscanf(line, "%d%c", &number, &hash) != 2 || hash != '#')
        {
            fprintf(stderr, "Format error (number# expected): %s", line);
            return(1);
        }

        if (max_entries >= num_entries)
        {
            int new_size = (max_entries + 2) * 2;
            struct data *new_info = realloc(info, new_size * sizeof(*new_info));
            if (new_info == 0)
            {
                fprintf(stderr, "Out of memory\n");
                return(1);
            }
            info = new_info;
            max_entries = new_size;
        }

        struct data *curr = &info[num_entries];
        curr->number    = number;
        curr->lines     = 0;
        curr->max_lines = 0;
        curr->num_lines = 0;

        while (fgets(line, sizeof(line), stdin) != 0)
        {
            char *p = strchr(line, '\n');
            if (p == 0)
            {
                fprintf(stderr, "Format error: no newline? (%s)\n", line);
                return(1);
            }
            *p = '\0';
            if (strcmp(line, "#") == 0)
                break;
            if (curr->max_lines >= curr->num_lines)
            {
                int new_size = (curr->max_lines + 2) * 2;
                char **new_lines = realloc(curr->lines, new_size * sizeof(*new_lines));
                if (new_lines == 0)
                {
                    fprintf(stderr, "Out of memory\n");
                    return(1);
                }
                curr->lines = new_lines;
                curr->max_lines = new_size;
            }
            curr->lines[curr->num_lines] = strdup(line);
            if (curr->lines[curr->num_lines] == 0)
            {
                fprintf(stderr, "Out of memory\n");
                return(1);
            }
            curr->num_lines++;
        }

        num_entries++;
    }

    for (int i = 0; i < num_entries; i++)
    {
        printf("%d#\n", info[i].number);
        for (int j = 0; j < info[i].num_lines; j++)
            printf("  %d: %s\n", j, info[i].lines[j]);
    }

    return(0);
}
它给出了输出:

13#
  0: Unlucky for some
20121221#
  0: The end of the world?
  1: No, it seems that we survived yet another doomsday!
18#
  0: More lines,
  1: And more lines still.
  2: The verse is weird.
  3: The terse is worse.
19#
  0: As for one,
  1: Then another,
  2: It is still too short
  3: For comfort,
  4: But the fifth line shall trigger
  5: an extra reallocation.
20#
  0: All for one,
  1: And one for all!
  2: The Three Musketeers?
  3: Nay, D'Artagnan, the Four Musketeers.
  4: Yahoo! Bing?  Google?

毫无疑问,代码还有改进的余地,但它似乎可以工作(尽管它在退出之前不会释放内存)。它假定存在一个函数
char*strdup(const char*str)
,该函数为给定字符串的副本分配了足够的空间。

使用
&abc[%d]
您希望实现什么?您所要求的包括无效的代码段。试着把它表达清楚,分步进行。1.把电话号码给我,2。去拿绳子。或者,同时获取数字和字符串,将字符串存储在中间缓冲区中,然后将字符串复制到struct数组中。如果一次就可以完成,那么头痛就不值得了。它是否会将%s存储为\0空终止符?我的程序在加载任何%s时不断崩溃。数字是否用大括号括起来?它后面是反斜杠和散列吗?文件是以文本文件还是二进制文件打开的?结束标记是包含反斜杠和散列的行,还是仅包含散列?您似乎需要
\r\n
行结尾,这表示Windows平台以二进制模式打开文本文件。为什么不展示一些实际数据的例子呢?“带行的某些文本”中可以有多少行?跳过最后一行。我尝试了这个选项,但我意识到我们必须处理另一个问题:线路。虽然我们可以读取文件,但我们必须读取其他行,我正在努力解决这个问题。这段代码只读取模式的第一次出现。我必须阅读模式的所有外观。对I/O的检查都不正确。外部循环将在达到EOF时无限期地继续;内环也是如此。第一个条件应该是
while(fscanf(文件,“%d#\r\n”,&index)==1)
,第二个条件应该是
int c;而((c=fgetc(文件))!=EOF&&c!='\r')
。有一个论点认为,您还应该检查其他两个输入操作。
13#
  0: Unlucky for some
20121221#
  0: The end of the world?
  1: No, it seems that we survived yet another doomsday!
18#
  0: More lines,
  1: And more lines still.
  2: The verse is weird.
  3: The terse is worse.
19#
  0: As for one,
  1: Then another,
  2: It is still too short
  3: For comfort,
  4: But the fifth line shall trigger
  5: an extra reallocation.
20#
  0: All for one,
  1: And one for all!
  2: The Three Musketeers?
  3: Nay, D'Artagnan, the Four Musketeers.
  4: Yahoo! Bing?  Google?