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

时间:2016-03-30 21:04:37

标签: c arrays file fgets scanf

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

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

我需要在并行数组中保存重复名字的姓氏,名字和年龄。 (所以我在阅读时需要丢弃逗号)。 这是我到目前为止所做的。

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

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

3 个答案:

答案 0 :(得分:0)

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

你应该怎么做?

首先抛弃你在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;
    }
}

答案 1 :(得分:0)

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

您可能希望使用fscanf的地方很少。除了每行的完全相同的格式之外,scanf系列函数都非常不灵活。通常,您需要使用面向行的输入(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;
}

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

答案 2 :(得分: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;
}

事实上,您不需要先阅读整行。而是直接扫描文件中的预期数据。