如何从C中的文件中获取未知数的字符串?

发布于 2025-02-05 15:44:21 字数 1071 浏览 3 评论 0原文

我有一个结构存储人员的名字,姓氏和薪水,但他们的名字数量是随机的。例如:

list.txt

  John Smith Green 1000 //他有两个名字
詹妮弗·威尔逊(Jennifer Wilson)2000 //她有一个名字
史蒂夫·亚当斯1500 //他有一个名字
詹姆斯·罗伯特·哈里斯(James Robert Harris)1250 //他有两个名字
罗宾·沃克(Robin Walker)1750 //他有一个名字
 

我想将他们的名字存储在person [count] .name中,他们在person [count] .surname和他们的薪水中的姓氏及其薪水在perse ] .Salary

为此,我写道:

fscanf(file, "%s %s %d", person[count].name, person[count].surname, &person[count].salary)

但是,问题是,如果一个人有两个名字,他的第二个名字存储在person [count] .surname .surname中,而我不能以姓氏为例。

我如何以person [count] .name中的两个名称的人的名字命名?

对于此文本文件:

person [0] .name ==> “约翰·史密斯”

person [1] .name ==> “詹妮弗”

person [2] .name ==> “史蒂夫”

person [3] .name ==> “詹姆斯·罗伯特”

person [4] .name ==> “罗宾”

I have a struct storing persons' names, surnames and salaries, but the number of their names is random. For example:

list.txt

John Smith Green 1000 //He has two names
Jennifer Wilson 2000 //She has one name
Steve Adams 1500 //He has one name
James Robert Harris 1250 //He has two names
Robin Walker 1750 //He has one name

I want to store their names in person[count].name, their surnames in person[count].surname and their salaries in person[count].salary.

To do that, I wrote:

fscanf(file, "%s %s %d", person[count].name, person[count].surname, &person[count].salary)

However, problem is that if a person has two names, his second name is stored in person[count].surname, and I cannot take the surname.

How can I take the name of a person with two names in person[count].name?

For this text file:

person[0].name ==> "John Smith"

person[1].name ==> "Jennifer"

person[2].name ==> "Steve"

person[3].name ==> "James Robert"

person[4].name ==> "Robin"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

囚我心虐我身 2025-02-12 15:44:21

我尝试通过行读取文件,然后将其分为令牌(单词)。我假设每行都包含在最大10个令牌(单词),最后一个令牌是薪水,最后一个是姓氏,第一个n-2令牌是人的名字。因此,我假设每个人都可以只用一个单词姓姓。这是代码,请注意,我没有注意内存泄漏或悬空指针等。

我根据 @的建议编辑了解决方案。
CHUX-恢复Monica

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

typedef struct Person
{
    char *name, *surname;
    int salary;
} Person;

int main()
{
    Person persons[10];
    FILE *file = fopen("text.txt", "r");
    if (file == NULL)
    {
        printf("Error opening file!\n");
        exit(1);
    }
    // read file line by line
    char line[256];
    int person_count = 0;
    while (fgets(line, sizeof(line), file) != NULL)
    {
        char *tokens[10];
        int i = 0;

        tokens[0] = strtok(line, " ");
        while (tokens[i] != NULL && i < 9)
        {
            tokens[++i] = strtok(NULL, " ");
        }

        char name[sizeof line];
        strcpy(name, tokens[0]);
        for (int j = 1; j < i - 2; j++)
        {
            strcat(name, " ");
            strcat(name, tokens[j]);
        }
        persons[person_count].name = strdup(name);
        persons[person_count].surname = strdup(tokens[i - 2]);
        persons[person_count].salary = atoi(tokens[i - 1]);
        person_count++;
    }
    for (int i = 0; i < person_count; i++)
    {
        printf("%s %s %d\n", persons[i].name, persons[i].surname, persons[i].salary);
    }

    fclose(file);
}

I tried reading the file line by line, then separating it into tokens (words). I am assuming each line contains at max 10 tokens (words), and the last token is salary, the one before the last is surname and first N-2 tokens are the names of the person. So, each person could have surnames with only one word, I am assuming. Here is the code, note that I did not pay attention to memory leaks or dangling pointers etc.

I edited the solution according to the suggestions from @
chux - Reinstate Monica

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

typedef struct Person
{
    char *name, *surname;
    int salary;
} Person;

int main()
{
    Person persons[10];
    FILE *file = fopen("text.txt", "r");
    if (file == NULL)
    {
        printf("Error opening file!\n");
        exit(1);
    }
    // read file line by line
    char line[256];
    int person_count = 0;
    while (fgets(line, sizeof(line), file) != NULL)
    {
        char *tokens[10];
        int i = 0;

        tokens[0] = strtok(line, " ");
        while (tokens[i] != NULL && i < 9)
        {
            tokens[++i] = strtok(NULL, " ");
        }

        char name[sizeof line];
        strcpy(name, tokens[0]);
        for (int j = 1; j < i - 2; j++)
        {
            strcat(name, " ");
            strcat(name, tokens[j]);
        }
        persons[person_count].name = strdup(name);
        persons[person_count].surname = strdup(tokens[i - 2]);
        persons[person_count].salary = atoi(tokens[i - 1]);
        person_count++;
    }
    for (int i = 0; i < person_count; i++)
    {
        printf("%s %s %d\n", persons[i].name, persons[i].surname, persons[i].salary);
    }

    fclose(file);
}
ζ澈沫 2025-02-12 15:44:21

您不能将fscanf()用于此问题。这是一种简单的方法,一次阅读一行,并用strrchr()

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

struct Person {
    char *name, *surname;
    int salary;
};

int main() {
    const char *filename = "list.txt";
    FILE *file = fopen(filename, "r");
    if (file == NULL) {
        fprintf(stderr, "Cannot open %s: %s\n", filename, strerror(errno));
        return 1;
    }
    // read file line by line
    char line[256];
    struct Person *persons = NULL;
    int count = 0;
    while (fgets(line, sizeof line, file) != NULL) {
        char *last = strrchr(line, ' ');
        if (!last)  // invalid format
            continue;
        *last++ = '\0';
        int salary;
        if (sscanf(last, "%d", &salary) != 1)
            continue;
        const char *name = line;
        char *surname = strrchr(line, ' ');
        if (surname) {
            *surname++ = '\0';
        } else {
            name = "";  // handle Superman: no first name
            surname = line;
        }
        persons = realloc(persons, (count + 1) * sizeof(*persons));
        if (persons == NULL) {
            fprintf(stderr, "out of memory\n");
            return 1;
        }
        persons[count].name = strdup(name);
        persons[count].surname = strdup(lastname);
        persons[count].salary = salary;
        count++;
    }
    fclose(file);

    // dump the database
    for (int i = 0; i < count; i++) {
        printf("%s %s %d\n", persons[i].name, persons[i].surname, persons[i].salary);
    }

    // free the database
    for (int i = 0; i < count; i++) {
        free(persons[i].name);
        free(persons[i].surname);
    }
    free(persons);
    return 0;
}

You cannot use fscanf() for this problem. Here is a simple approach reading one line at a time and parsing it explicitly with strrchr():

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

struct Person {
    char *name, *surname;
    int salary;
};

int main() {
    const char *filename = "list.txt";
    FILE *file = fopen(filename, "r");
    if (file == NULL) {
        fprintf(stderr, "Cannot open %s: %s\n", filename, strerror(errno));
        return 1;
    }
    // read file line by line
    char line[256];
    struct Person *persons = NULL;
    int count = 0;
    while (fgets(line, sizeof line, file) != NULL) {
        char *last = strrchr(line, ' ');
        if (!last)  // invalid format
            continue;
        *last++ = '\0';
        int salary;
        if (sscanf(last, "%d", &salary) != 1)
            continue;
        const char *name = line;
        char *surname = strrchr(line, ' ');
        if (surname) {
            *surname++ = '\0';
        } else {
            name = "";  // handle Superman: no first name
            surname = line;
        }
        persons = realloc(persons, (count + 1) * sizeof(*persons));
        if (persons == NULL) {
            fprintf(stderr, "out of memory\n");
            return 1;
        }
        persons[count].name = strdup(name);
        persons[count].surname = strdup(lastname);
        persons[count].salary = salary;
        count++;
    }
    fclose(file);

    // dump the database
    for (int i = 0; i < count; i++) {
        printf("%s %s %d\n", persons[i].name, persons[i].surname, persons[i].salary);
    }

    // free the database
    for (int i = 0; i < count; i++) {
        free(persons[i].name);
        free(persons[i].surname);
    }
    free(persons);
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文