0

在我的程序的一个函数中,我试图将文件中的数据加载到这个结构数组中:

/* database struct */
typedef struct node {
    char       name[MAX];
    char       address[MAX];
    long int   number;
}record_type;

record_type record[100];

功能如下:

/* load database from disk */
void load_database() {
    char line[128];

    /* Set up database */
    database = fopen("database.txt", "r+w+a+");
    if(database == NULL) {
        printf("\n\tWARNING: No database found.");
        exit(1);
    }

    /* Get database file from disk */
    while(fgets(line, sizeof(line), database) != NULL) {
        sscanf(line, "%s %s %lu", record[rec_num].name,
            record[rec_num].address, &record[rec_num].number);

        /* keeps track of array size */
        rec_num++;
    }
}

我遇到的问题是与 sscanf 不一致。如果我包含名字和姓氏,我不能在它们之间放置空格,或者它将名字放在 name[] 中,将姓氏放在 address[] 中。

这是我尝试输入的数据示例:

1.  Name: james manes       Address: 220 test addr      Number: 5558889999

我需要将“james manes”放入 name[] 字段,将 220 test addr 放入 address[] 字段,将 5558889999 放入结构的 number 字段。这可能吗?

有没有更有效的方法来管理这种类型的输入?

4

2 回答 2

1

scanf("%s"...解析输入中的空格分隔字符串,因此如果要解析的字符串中有空格,它将不起作用。

虽然您可以使用正则表达式来获得您想要的东西,但由于您使用固定字符串作为标记,您可以改为使用strstr拉出字符串:

while(fgets(line, sizeof(line), database) != NULL) {
    char *Name = strstr(line, "Name:");
    char *Address = strstr(line, "Address:");
    char *Number = strstr(line, "Number:");
    if (Name && Address && Number) {
        Name += strlen("Name:");
        *Address = '\0';
        Address += strlen("Address");
        *Number = '\0';
        Number += strlen("Number:");
        strcpy(record[rec_num].name, Name);
        strcpy(record[rec_num].address, Address);
        sscanf(Number, "%lu", &record[rec_num].number);
        rec_num++; } }

请注意,这还将拉入名称和地址周围的所有空格 - 如果您希望它更清晰,您可以修剪前导和尾随空格。

于 2012-12-06T05:03:25.367 回答
-2

首先,您可能想再看看http://www.cplusplus.com/reference/cstdio/fgets/。在这里,您将看到str参数是指向缓冲区的指针(您正确提供),然后num是您要读取的字节数max,您没有正确提供。

在您的代码中传递给 fgets 的字节数的问题是sizeof运算符的不正确使用。如您所知, sizeof 运算符“返回”给定类型的大小。您传递给 sizeof 的类型是指针类型(因为 C 中的数组 99% 与指针相同)。指针的大小取决于您运行的系统(Intel x86 上为 32 位,AMD64 上为 64 位,ATmega AVR 上为 16 位等)。因此,假设您有一台 64 位机器,您将允许 fgets '获取' 64 位(即 8 字节)的数据,这不是您想要的。那么正确的说法是什么?

while(fgets(line, sizeof(*line)*128, database) != NULL) {
    ...

我在这里所做的是将char 指针取消引用到char并乘以该数组的大小。

然后,其次,您关于这是否可能的问题:是的。我现在也想问自己一个问题。是否有必要在 C 中执行此操作(即平台不支持任何不同的学习目的等),或者您也可以在 C#、Java、Python 中实现它。如果是这样,我强烈建议你这样做。

最后但并非最不重要的是,您正在向我们询问您的代码的有用性。这个答案很简单:不。不在当前或固定状态。使用“真实”数据库(如 MySQL)+ 其 API 可以解决您遇到的更复杂的问题。

于 2012-12-06T03:02:32.960 回答