如何扫描txt文件中的数据并存储在C中的数组中?

How to scan txt file for data and store in arrays in C?

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

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ääääääääääüüüüüüéééééé 

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

你不看那些特殊字符。它们恰好存在于你的数组中,因为它是一个非静态持续时间的未初始化数组。因此,当您到达文件末尾时,因为您没有测试输入函数的结果,所以您将垃圾留在缓冲区中,稍后打印该垃圾。

你该怎么办?

首先丢弃 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--] = '[=10=]'; //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;
    }
}

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

很少有地方需要使用 fscanfscanf 系列函数在处理除每行 完全相同格式 之外的任何内容时非常不灵活。通常你会想要使用 line-oriented 输入(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

例子Use/Output

$ ./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;
}

仔细阅读,如果您有任何问题,请告诉我。

不管这个文件有多少人,都要打印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;
}

事实上,你不需要先读一整行。相反,直接从文件中扫描预期数据。