【问题标题】:How to scan txt file for data and store in arrays in C?如何扫描txt文件中的数据并存储在C中的数组中?
【发布时间】:2016-03-30 21:04:37
【问题描述】:

我正在尝试读取包含字符串和数字的文本文件并保存到它们各自的数组中。这是我要阅读的内容文本文件

Ryan, Elizabeth     62
McIntyre, Osborne   84
DuMond, Kristin     18
Larson, Lois        42
Thorpe, Trinity     15
Ruiz, Pedro         35
Ali, Mohammed       60
Vashti, Indura      20

我需要将 repescitve 人的姓氏、名字和年龄保存在并行数组中。 (所以我需要在阅读时丢弃逗号)。 这是我目前所拥有的。

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

int main(int argc, char *argv[])
{
    char line[100][41];
    char junk[100];
    int i;
    FILE *file = fopen(argv[1], "r");

    if(!file) {
        printf("Could not open file. Exiting application.");
        return 1;
    }

    for(i=0; i<100; i++)
    {
        fscanf(file, "%[^\n]", line[i]); //Get text
        fscanf(file,"%[ \n\t\r]s",junk); //Remove any 'white space' characters
    }

    fclose(file);

    for (i=0; i<30; i++)
        printf("%s\n",line[i]);

    return 0;
}

我已经在 IDE 中传递了文件参数。我在输出的末尾得到了很多特殊字符。

Ryan, Elizabeth         62
McIntyre, Osborne       84
DuMond, Kristin         18
Larson, Lois            42
Thorpe, Trinity         15
Ruiz, Pedro             35
Ali, Mohammed           60
Vashti, Indura          20
┌

 t╠╠

$

M

v
9 Rì
xá

╚

±
t/╗₧8
¿≡`
   Tq töq t4≤`


ÿv
h((((                  Hääääääääääüüüüüüéééééé 

我为什么要阅读所有这些特殊字符?以及如何丢弃逗号并保存到三个不同的数组中?

【问题讨论】:

  • 替代方法:使用fgets()然后解析缓冲区。
  • while ( fscanf("%s,%s%d", last, first, &amp;num) == 3 ).
  • 要解析缓冲区,请查看strtokdelims = ", \t\n";(即逗号、空格、制表符、换行符

标签: c arrays file fgets scanf


【解决方案1】:

无论文件包含多少人,都要打印出 30 个人。在您的情况下,该文件仅包含 8 个人,其余 22 行(从 line[8]line[29])保存的值是垃圾值,因为它们从未被初始化。结果打印出奇怪的字符。

这里是精炼的代码:

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

int main(int argc, char *argv[])
{
    char first[100][40], last[100][40];
    int age[100];
    size_t i = 0;
    FILE *file = fopen(argv[1], "r");

    if(!file) {
        printf("Could not open file. Exiting application.");
        return 1;
    }

    while(fscanf(file, " %[^,],%s%d", first[i], last[i], &age[i]) == 3)
    {
        i++;
    }

    size_t num = i;

    fclose(file);

    for (i = 0; i < num; i++)
        printf("%s, %s\t%d\n", first[i], last[i], age[i]);

    return 0;
}

其实,你不需要先读一整行。而是直接扫描文件中的预期数据。

【讨论】:

    【解决方案2】:

    您不会阅读那些特殊字符。它们碰巧存在于您的数组中,因为它是一个非静态持续时间的未初始化数组。因此,当您到达文件末尾时,由于您不测试输入函数的结果,您将垃圾留在缓冲区中,然后打印该垃圾。

    你应该怎么做?

    首先在 fscanf 中丢弃你奇怪的格式:第一个与 fgets 没有太大区别,第二个期望行尾后跟一个 s 字符。

    因此,如果您想逐行阅读,只需使用fgets 计算实际读取的行数:

    for(i=0; i<100; i++)
        {
            int l;
            if (NULL == fgets(line[i], sizeof(line[i]), stdin)) break;
            l = strlen(line[i]) - 1;
            while ((l>0) && (strchr(" \t\r\n", line[i][l]) != NULL) {
                line[i][l--] = '\0'; //Remove any trailing 'white space' characters
        }
    nblines = i - 1;   // number or lines actually read
    

    但是你知道行的格式,因为它很简单,你可以直接扫描:

    char name[100][41], firstname[100][41];
    int age(100);
    int i, numlig;
    
    for(numlig=0; numlig<100; numlig++) {
        if (3 != scanf("%[^,],%s%d", name[i], lastname[i], age + i)) {
            break;
        }
    }
    

    或者如果你想严格控制每一行发生的事情:

    char name[100][41], firstname[100][41], line[41];
    int age(100);
    int i, numlig;
    
    for(numlig=0; numlig<100; numlig++) {
        if (NULL == fgets(line, sizeof(line), stdin)) { break; }
        if (3 != sscanf(line, "%[^,],%s%d", name[i], lastname[i], age + i)) {
            break;
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以通过多种方式完成读取数据并将其分离为firstlastage。最有意义的是使用包含每个姓名和年龄的简单struct,然后创建一个结构数组来保存您的数据。

      很少有地方可以使用fscanfscanf 系列函数在处理除了每一行的完全相同的格式之外的任何东西时都非常不灵活。通常您会希望使用面向行的 输入(fgets,然后使用strtoksscanf 解析您的数据)。但是,这种情况是合格的。

      下面是一个简短的例子,使用结构来保存数据,fscanf 作为输入:

      #include <stdio.h>
      
      #define MAXP 20
      
      typedef struct {
          char first[20];
          char last[20];
          int age;
      } person;
      
      int main (int argc, char **argv) {
      
          size_t i, idx = 0;              /* initialize all variables */
          person p[MAXP] = {{"", "", 0}};
          FILE *fp = argc > 1 ? fopen(argv[1], "r") : stdin;
      
          if (!fp) {
              fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
              return 1;
          }
      
          while (idx < MAXP &&    /* read each line, separate first, last, age */
              fscanf (fp, "%[^,],%s%d%*c", p[idx].last, p[idx].first, &p[idx].age) == 3)
              idx++;
      
          if (fp != stdin) fclose (fp);   /* close file  */
      
          for (i = 0; i < idx; i++)       /* output data */
              printf (" p[%2zu] '%s %s' is %d years old.\n",
                      i, p[i].first, p[i].last, p[i].age);
      
          return 0;
      }
      

      输入文件

      $ cat dat/names.txt
      Ryan, Elizabeth     62
      McIntyre, Osborne   84
      DuMond, Kristin     18
      Larson, Lois        42
      Thorpe, Trinity     15
      Ruiz, Pedro         35
      Ali, Mohammed       60
      Vashti, Indura      20
      

      使用/输出示例

      $ ./bin/person <dat/names.txt
       p[ 0] 'Elizabeth Ryan' is 62 years old.
       p[ 1] 'Osborne McIntyre' is 84 years old.
       p[ 2] 'Kristin DuMond' is 18 years old.
       p[ 3] 'Lois Larson' is 42 years old.
       p[ 4] 'Trinity Thorpe' is 15 years old.
       p[ 5] 'Pedro Ruiz' is 35 years old.
       p[ 6] 'Mohammed Ali' is 60 years old.
       p[ 7] 'Indura Vashti' is 20 years old.
      

      使用 fgets/sscanf 的示例

      您基本上可以用fgetssscanf 做同样的事情。下面是一个使用该组合的简短示例:

      #include <stdio.h>
      
      enum { MAXP = 20, MAXC = 128 };
      
      typedef struct {
          char first[20];
          char last[20];
          int age;
      } person;
      
      int main (int argc, char **argv) {
      
          size_t i, idx = 0;              /* initialize all variables */
          char buf[MAXC] = "";
          person p[MAXP] = {{"", "", 0}};
          FILE *fp = argc > 1 ? fopen(argv[1], "r") : stdin;
      
          if (!fp) {
              fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
              return 1;
          }
      
          while (idx < MAXP && fgets (buf, MAXC, fp) && 
                 sscanf (buf, "%[^,],%s%d", 
                         p[idx].last, p[idx].first, &p[idx].age) == 3)
              idx++;
      
          if (fp != stdin) fclose (fp);   /* close file  */
      
          for (i = 0; i < idx; i++)       /* output data */
              printf (" p[%2zu] '%s %s' is %d years old.\n",
                      i, p[i].first, p[i].last, p[i].age);
      
          return 0;
      }
      

      查看一下,如果您有任何问题,请告诉我。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-05
        • 1970-01-01
        • 2014-06-11
        • 2013-11-05
        • 2021-10-10
        • 2019-10-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多