C:新手使用 malloc 尝试文件读取和结构分配

C: Newbie attemping file reading and struct allocation using malloc

提问人:Akiyuu 提问时间:11/19/2022 更新时间:11/19/2022 访问量:39

问:

我正在尝试将存储在 details.txt 文件中的值存储到动态分配的结构中的适当位置。我是否错误地做了一些事情(应该很简单)以使其不起作用?我是否有必要使用 strtok 并按“,”进行拆分?

我的详细信息.txt如下:

米奇,8,1.78,汉堡

Murray,42,6.5,千层面

特拉维斯,64,1.85,寿司

SAM,12,1.94,培根

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFFERSIZE 256

typedef struct 
{
    char name[BUFFERSIZE];
    int favnumber;
    float height;
    char favfood[BUFFERSIZE];
} Person;

void print_person(Person *p) 
{
    printf("name: %s\n", p->name);
    printf("num: %d\nheight: %.2f\nfav. food: %s\n\n",
        p->favnumber, p->height, p->favfood);
}

int count_lines(FILE *fp) 
{
    int nlines = 0;
    char c;
    for (c = fgetc(fp); c != EOF; c = fgetc(fp)) 
    {
        if (c == '\n') 
        {
            nlines++;
        }
    }
    rewind(fp);
    return nlines;
}

int main(void) 
{
    FILE *fp = fopen("details.txt", "r");
    
    // count lines
    int nlines = count_lines(fp);
    printf("found %d lines\n\n",nlines);

    Person *people = (Person*)malloc(nlines*sizeof(Person));

    char buffer[BUFFERSIZE];
    int i = 0;
    while (fgets(buffer,BUFFERSIZE,fp) != NULL) 
    {
        sscanf(buffer,"%s%d%f%s",people[i].name,
            &(people[i].favnumber),
            &(people[i].height),people[i].favfood);
        print_person(&(people[i]));
        i++;
    }
    printf("found %d people\n",i);

    free(people);

    fclose(fp);
}

不幸的是,我的程序的当前输出是:

共找到 4 条线路

常用中文名:Mitch,8,1.78,Burgers

数量: 0

高度: 0.00

最喜欢的。食物:

...

找到 4 人

c string struct malloc

评论


答:

2赞 Allan Wind 11/19/2022 #1

问题是首先解析整行,并且需要在格式字符串中分隔字段。这里还不是问题,但我也使用了 %[^,] 作为最后一个格式字符串,所以它不会停在第一个空格处。还增加了字符串的精度,以避免缓冲区溢出:%s,

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFFERSIZE 255
#define str(s) str2(s)
#define str2(s) #s

typedef struct 
{
    char name[BUFFERSIZE+1];
    int favnumber;
    float height;
    char favfood[BUFFERSIZE+1];
} Person;

void print_person(Person *p) 
{
    printf("name: %s\n", p->name);
    printf("num: %d\nheight: %.2f\nfav. food: %s\n\n",
        p->favnumber, p->height, p->favfood);
}

int count_lines(FILE *fp) 
{
    int nlines = 0;
    char c;
    for (c = fgetc(fp); c != EOF; c = fgetc(fp)) 
{
        if (c == '\n') {
            nlines++;
        }
    }
    rewind(fp);
    return nlines;
}

int main(void) 
{
    FILE *fp = fopen("details.txt", "r");

    // count lines
    int nlines = count_lines(fp);
    printf("found %d lines\n\n",nlines);

    Person *people = (Person*)malloc(nlines*sizeof(Person));

    char buffer[BUFFERSIZE+1];
    int i = 0;
    while (fgets(buffer,BUFFERSIZE+1,fp) != NULL) 
{
// Changed line, see formatting of %s
        sscanf(buffer,
            "%" str(BUFFERSIZE) "[^,],%d,%f,%" str(BUFFERSSIZE) "[^,]",
            people[i].name,
            &(people[i].favnumber),
            &(people[i].height),people[i].favfood);
        print_person(&(people[i]));
        i++;
    }
    printf("found %d people\n",i);

    free(people);

    fclose(fp);
}

评论

0赞 chux - Reinstate Monica 11/19/2022
哦 - 串联 - 不错。#
0赞 chux - Reinstate Monica 11/19/2022
也许是最后一次?"[^\n]"
0赞 Allan Wind 11/19/2022
@chux-ReinstateMonica 由于缓冲区的大小与两个字符串相同,我认为原始代码无论如何都不会超出缓冲区。 如果添加其他字段,可能会更符合未来需求(即在代码更新之前被忽略,其中“[^\n]”会将其读取为一个字段;顺便说一句,我首先考虑了您的建议。"[^,]"
2赞 chux - Reinstate Monica 11/19/2022
公平点。只是裸体等引起了人们的注意。%s