如何读取文件并解析它

How to read from a file and parse it

提问人:al366io 提问时间:4/22/2022 最后编辑:anastaciual366io 更新时间:4/24/2022 访问量:218

问:

我有一个文件.txt包含一些格式如下的值:

0,30,25,10

现在,我打开文件并将其存储到一个数组中

char imposta_tratt[300]; 
FILE *fp;
fp = fopen("/home/pi/Documents/imposta_trattamento.txt", "r");
if (fp == 0) return;
fread(imposta_tratt, sizeof(imposta_tratt), 1, fp);
fclose(fp);

现在我希望数组中填满我的数据。我有用 a 分隔的值,所以我继续解析它:,

const char delim[2] = ",";
int t=0;
char *token = strtok(imposta_tratt, delim);
    while (token!=NULL){
    
        strcpy(tratt[t],token);
        token = strtok(NULL, delim);
        tratt[t]=token;
        t++;
    }

在这里,参考文件.txt中的内容,我希望有等等,但似乎我遗漏了一些东西,因为它不是这样的。tratt[0]=0; tratt[1]=30; tratt[2]=25;

我想要的只是将 txt 文件的值存储在单个变量中。有人可以帮忙吗?

数组 C 解析 IO Fread

评论

1赞 Weather Vane 4/22/2022
如果要将数据传递给字符串处理函数,则需要将其终止为字符串。所以。我已经切换了 的大小和 count 参数,因为它的返回值是读取的元素数。但是,你为什么不使用一个文本函数,而不是用于二进制数据呢?size_t len = fread(imposta_tratt, 1, sizeof(imposta_tratt) - 1, fp); imposta_tratt[len] = 0;freadfgets()fread()
0赞 al366io 4/22/2022
@WeatherVane因为我完全忘记了.我会立即尝试使用该功能,似乎更合适。fgets
0赞 Weather Vane 4/22/2022
您将需要 的分隔符字符串中的换行符: 请注意,我没有更改,而是删除了它,因为它根本不需要存在:它只会给程序增加自重和更多的维护负载。strtokconst char delim[] = ",\n";delim[2]delim[3]
0赞 Gerhardh 4/22/2022
对于其他问题,请记住,“因为它不是这样的”不是很有用。相反,您应该添加发生的事情。除了数组不能包含等事实之外,而只能在处理字符串时使用。0"0"

答:

0赞 OTheDev 4/22/2022 #1

假设有内容"in.txt"

0,30,25,10

下面的程序用于将整数逐个读入数组。当我们使用 读取整数时,我们确保它的返回值符合预期。如果没有,我们将关闭文件并退出。如果返回值与预期不符,程序还会打印发生的错误类型。目前,如果发生任何错误,程序将停止。但是,如果您愿意,您可以根据发生的错误使程序的行为有所不同。fscanftrattfscanffscanf

作为输出,程序将读取到数组中的所有整数打印出来。输出为tratt

0
30
25
10

现在这个程序假设我们知道要读入的元素的数量。如果我们不这样做,我们可以允许在数组需要更多元素时动态分配更多内存,或者可能包含一个数据结构,例如,在文件的开头/结尾记录有关文件的信息,例如文件中的数字数和数据类型(二进制文件最适合此)。这些只是其中的几种可能性。tratt"in.txt"

更好的方法可能是逐个读取字符(例如,使用 )并使用将字符数字序列转换为字符数字(我会采用类似的方法)。getcstrtollong int

然而,这种方法更简洁,应该就足够了。

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

#define FILE_NAME "in.txt"
#define MAX_LEN 4

int main(void) {

    int i, tratt[MAX_LEN];
    FILE *fp = fopen(FILE_NAME, "r");      /* open file for reading */

    /* if cannot open file */
    if (fp == NULL) {

        printf("Cannot open %s\n", FILE_NAME);
        exit(EXIT_FAILURE);

    }

    /* read integer, checking return value of scanf as expected */
    if (fscanf(fp, "%d", &tratt[0]) != 1) {
        if (ferror(fp))
            printf("fscanf: read error\n");
        else if (feof(fp))
            printf("fscanf: end of file\n");
        else
            printf("fscanf: matching failure\n");

        fclose(fp);
        exit(EXIT_FAILURE);
    }

    for (i = 1; i < MAX_LEN; i++)
        /* read comma plus integer, checking return value of scanf */
        if (fscanf(fp, ",%d", &tratt[i]) != 1) {
            if (ferror(fp))
                printf("fscanf: read error\n");
            else if (feof(fp))
                printf("fscanf: end of file\n");
            else
                printf("fscanf: matching failure\n");

            fclose(fp);
            exit(EXIT_FAILURE);

        }
    fclose(fp);    /* close file */

    /* print integers stored in tratt */
    for (i = 0; i < MAX_LEN; i++)
        printf("%d\n", tratt[i]);

    return 0;

}
1赞 Zakk 4/22/2022 #2

您要实现的目标可以简单地使用以下方法完成:fgets()

bool read_file_content(const char *filename, const size_t tsizemax, int tratt[tsizemax], size_t *tsize, const char *delim)
{
    // Attempt to open filename.
    FILE *fp = fopen(filename, "r");
    if (!fp) return false; // Return false upon failure.
    
    // Try to read one line. If you have more, you need a while loop.
    char imposta_tratt[300];
    if (!fgets(imposta_tratt, sizeof imposta_tratt, fp)) {
        fclose(fp);
        return false;
    }
    
    *tsize = 0;
    char tmp[300]; // Temporary buffer. Used for conversion into int.
    char *token = strtok(imposta_tratt, delim);
    
    while (token && *tsize < tsizemax) {
        strncpy(tmp, token, sizeof tmp);
        tratt[(*tsize)++] = atoi(tmp);
        
        token = strtok(NULL, delim);
    }
    
    fclose(fp);
    return true;
}
  • const char *filename:要解析的文件。
  • const size_t tsizemax:阵列的最大大小。控制大小很重要,否则代码将出现缓冲区溢出(例如,当文件包含超过 100 个标记时)。tratt
  • int tratt[tsizemax]:将保存值的数组。
  • size_t *tsize:读取的令牌数(与 )。tsizemax
  • const char *delim:分隔符,在您的例子中为 a .,

这是你的:main()

int main(void)
{
    int tratt[100];
    size_t size = 0;
    
    if (!read_file_content("in.txt", 100, tratt, &size, ",")) {
        puts("Failed");
        return 1;
    }
    
    for (size_t i = 0; i < size; ++i)
        printf("%d\n", tratt[i]);
}

输出:

0
30
25
10