【问题标题】:Read integers into an array in C将整数读入C中的数组
【发布时间】:2021-04-06 03:46:18
【问题描述】:

我正在尝试将整数文本文件读入 C 中的数组。

我的文本文件如下所示:(12 个数字/行)

5713    6936    8764    6702    8535    8654    8710    8332    4948    7627    5472    5311    
7331    8719    6135    6672    5786    7113    5292    6923    5683    7020    8595    8606    
6837    7003    7415    8372    8429    5726    8323    6442    8672    6488    6932    5884    
6811    7785    7189    5531    6323    8561    8283    5114    6669    7217    8307    6599    
6961    8695    6026    5580    6010    4954    8725    4955    5532    7736    5372    8712    
8343    5375    5931    6449    8223    5844    5931    5307    5436    6405    8599    6302    
8617    8222    5985    8216    5044    5259    6523    7526    8702    5878    7559    5366    
5362    7393    6633    8781    6289    6470    5342    7278    5348    8677    5779    5763    
5718    8678    6406    8774    5931    7324    6819    6393    5027    7545    8385    8795    
8277    8059    6362    6980    5899    5828    6707    7149    5621    7287    5958    6506    
6517    5710    5504    7070    8797    6840    7112    6063    7014    5419    7514    7431   

实际文件总共有 1000 个数字

目前,我正在使用以下代码:

int main(void){

    FILE *my_file;
    my_file = fopen("seals.txt", "r");
    size_t size = word_conter(my_file);

    int weight = 0;
    int seals[size];

    int i;
    for(i = 0; i < size; i++){
        if(fscanf(my_file, "%1d", &weight) == 1)
            seals[i] = weight;
        else break;
    }

    for(i = 0; i < size; i++){
        printf("%d\t %d\n", i, seals[i]);
    }

    
    fclose(my_file);    
    return 0;
}

编辑:这里是word_counter

size_t word_conter(FILE *my_file){
    
    if(my_file == NULL){
        perror("Error in file");
        exit(1);
    }

    size_t counter = 0, in_word = 0;
    char ch;

    while((ch = fgetc(my_file)) != EOF){

        if(ch == ' ' || ch == '\n' || ch == '\t' || ch == '\0'){
            if(in_word){
                in_word = 0;
                counter++;
            }
        }
        else in_word = 1;
    }

    return counter;
}

不幸的是,我的输出是:

0    245589760
1    1
2    1
3    0
4    -497513808
5    32766
6    245022469
7    1
8    -497513808
9    32766
10   245022268
11   1
12   1
13   0
14   224894352
15   1
16   -497513744
17   32766
18   244994643
19   1
20   245557328
21   1
22   224894352
23   1
24   224879992
25   1
26   0
27   0
28   245584536
29   1
30   245616784
31   1
32   -497513712
33   32766
34   245024298
35   1
36   245557328
37   1
38   -799666472
39   22978
40   -497510096

等到 999。

我都试过了: fscanf(my_file, "%1d", &amp;weight)fscanf(my_file, "%d", &amp;weight) 但两者都没有工作。我已经阅读了有关 fscanf 的手册,但仍然无法正确理解。

任何帮助将不胜感激!

二次编辑

我使用了rewind() 并且成功了!

【问题讨论】:

  • 使用%1d 绝对不是你想要的,不过我认为使用%d 没有问题。
  • 查看question 及其答案。
  • 你从不检查文件是否打开成功。
  • @JohnnyMopp 我在 word_counter 方法中做的。
  • size_t size = word_conter(my_file); 未包含在您的帖子中。您确定正确返回了 size 的值吗?应该包含它以提供minimal reproducible example

标签: arrays c file scanf fopen


【解决方案1】:

简而言之,这是由于连续两次读取数据文件而没有调用rewind()造成的。

fscanf()第二次读取文件而不回退时,就会出现问题。 (第一次读取在word_conter()函数中):

        if(fscanf(my_file, "%d", &weight) == 1)//2nd read on one file descriptor
             seals[i] = weight;//program flow never gets here
        else break;

这导致执行流程直接跳转到else break;,然后继续在printf()上循环并输出未初始化的数组:int seals[size];

此外,函数word_conter 容易受到其正在读取的文件中可能存在的各种不一致数据格式的影响。建议在调试器中单步执行代码,以准确描述这可能导致问题的原因。

我的建议是在word_counter 中分别调用fopen()fclose 一次,然后在主函数中再次调用它们。 size_t word_conter(FILE *my_file) 的这个重构版本支持这种方法。 (编写以容纳每行包含 12 个数字的文件,如 cmets 中所述):

size_t word_counter(char *filename)
{
    char line[260] = {0};
    char *tok = NULL;
    int count = 0;
    FILE *fp = fopen(filename, "r");
    if(fp)
    {
        while(fgets(line, sizeof(line), fp))
        {
            tok = strtok(line, " \n");
            while(tok)
            {
                count++;
                tok = strtok(NULL, " \n");
            }
            memset(line, 0, sizeof(line));
        }
        fclose(fp);
    }
    return count;
}

在 main 中调用为:

size_t size = word_counter("seals.txt");

还有一个使用不正确format specifier的实例可以调用undefined behavior

为:

int weight = 0;

正确的格式说明符是"%d"。要么改变:

if(fscanf(my_file, "%1d", &weight) == 1)

到:

if(fscanf(my_file, "%d", &weight) == 1)    

或改变:

   int weight = 0;
   int seals[size];

到:

   long weight = 0;
   long seals[size];

%ld 仅用于long。)

解决这些问题可能会解决您遇到的问题。 (不过因为word_conter()没有详细展示,可能还有其他问题。)

【讨论】:

  • @Davide - 是的,抱歉,我还在编辑。鉴于所示代码中的其他遗漏和错误,OP 尝试了正确的格式说明符这一事实可能没有帮助。
  • @ryyker 感谢您的详细回答!不幸的是,这仍然不能解决问题。我已经编辑了我的问题,所以你们可以看到 word_counter 方法。另外,我被要求澄清,文本文件包含多行数字,而不是显示的单行。
  • @TalZichlinsky - 现在看看。谢谢。是每行一个数字,还是多个。每行有多少个数字? (请具体。)
  • @ryyker 每行 12 个数字。无论如何,问题解决了,使用```rewind```完成了工作。非常感谢您的帮助!
  • @TalZichlinsky - 欢迎您。我刚刚得出rewind 的结论,或者建议两次打开文件。 Chux 打败了我。 :)
【解决方案2】:

字数计数器在边缘情况下会出错。

寻找从空间到非空间的过渡。不要忘记rewind()

size_t counter = 0;
bool in_word = false;
// char ch;
int ch;

while((ch = fgetc(my_file)) != EOF){
   if (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\0') {  // better: if (isspace(ch)) {
     in_word = false;
   } else {
     if (!in_word) counter++;
     in_word = true;
   }
}
rewind(my_file); // reset to the beginning

return counter;

更好的是,只需以 same 格式浏览文件两次。

size_t counter = 0;
while (fscanf(my_file, "%d", &weight) == 1) {
  counter++;
}
rewind(my_file); // reset to the beginning

【讨论】:

  • 非常感谢! rewind() 完成工作!
  • @TalZichlinsky rewind() 是一个重要部分,但存在其他问题(如此处和其他问题的回答)。希望现在都解决了。
【解决方案3】:

尝试用if(fscanf(my_file, "%d", &amp;weight) != EOF)替换if(fscanf(my_file, "%1d", &amp;weight) == 1)

【讨论】:

  • 比较想要的 ==1 比不想要的 !=EOF 要好。使用!= EOF,非数字输入为fscanf() 的无限循环返回0。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-14
  • 1970-01-01
相关资源
最近更新 更多