将数据从文本文件保存到C中的数据结构

时间:2018-08-31 13:44:49

标签: c

我有一个包含各种记录的文本文件,例如,每个记录有4个字段,3个单词字符串和一个数字

field one; field two; field three; 1
field one; field two; field three; 2

我需要通过插入排序算法根据最后一个数字对这些记录进行排序,因此第二个记录应该是列表中的第一个记录,因为2> 1。为此,在比较它们之前,我首先需要存储每条记录,对此我遇到了一些问题。

直到现在我都知道了:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 100

struct Element
   {
    char one[100];
    char two[100];
    char three[100];
    int st;
   };



int main() {

    int i;
    struct Element elements[MAXLEN];


    FILE * fpointer = fopen("clients.txt", "r");

    for (i = 0; i < MAXLEN; i++) {
       struct Element *e = elements+i;  // pointer on ith element
       fscanf(fpointer, "%99s%99s%99s%d", e->one, e->two, e->three, &e->st);
    }

    printf("%s%s%s%d", elements->one, elements->two, elements->three, elements->&st);

    fclose(fpointer);
    return 0;

}

我当前的问题:

1)此当前程序不利于保存字符串。记录如:字符串;串;串; 1,但不适用于词组(如第一个示例中一样)。

2)我不太了解这种结构:我知道我将每条记录保存在我的数据结构数组中,但是在打印每条记录时遇到了一些问题。假设我要打印第二条记录,该怎么办?在我当前的工作中,我打印了one, two, three and st,但是这样,它只会打印第一条记录。

3 个答案:

答案 0 :(得分:2)

在调用任何%s函数时使用scanf只会读取文本中的下一个空格,因此,如果您的字段中只有一个单词,则可以正常工作,但是如果发现有短语,就会跌倒。它还会把分隔符读入您的字符串中,我对此表示怀疑。

相反,更好的解决方案是将整行读入一个字符串,然后解析通过它的方式。下面的代码用fgets读取一行文本,然后使用strtok将其拆分为由分号分隔的块。它跟踪使用field_number填充字段的方式,因此,如果添加更多字段,则很容易扩展。如果字段少于预期,它将停止并移至下一行。

char buffer[1024]; // Define a really big string to hold the line of text in
char *field;
int field_number;

while(fgets(buffer,1024,fpointer))
    {
    field_number=0;
    field=strtok(buffer,";");
    while(field)
        {
        switch(field_number)
            {
        case 0:
            strcpy(elements[i].one,field);
        break;
        case 1:
            strcpy(elements[i].two,field);
        break;
        case 2:
            strcpy(elements[i].three,field);
        break;
        case 3:
            elements[i].st=atoi(field);
        break;
            }
        field=strtok(NULL,";"); // Get next field
        field_number++;
        }
    i++; // Move the index for elements to the next one
    }

为回答第二个问题,elements是一个数组。如果您执行elements->one与执行elements[0].one相同。如果要访问数组中的第二个元素,则可以执行elements[1].one(elements+1)->one,这就是在原始代码中使用此奇数行进行的操作:

   struct Element *e = elements+i;  // pointer on ith element

当您真正应该使用elements[i]时,因为它更容易阅读。

答案 1 :(得分:2)

您可以在[HttpPost] public IActionResult Post([FromForm]PostcodeVerwerking p) { int res = _postcodeRepo.AddPostcode(p); if (res != 0) { return Ok(); } return Forbid(); } 中使用%[^;]fscanf将读取字符串,直到到达fscanf。 并将;用作;的定界符。 您的代码如下所示。

fscanf

答案 2 :(得分:1)

我认为您已经基本解决了第二个问题。

for (i = 0; i < MAXLEN; i++) {
    struct Element *e = elements+i;  // pointer on ith element
    printf("%s%s%s%d", e->one, e->two, e->three, e->&st);    
}

或者,您可以使用格式elements[i].one来访问第i个元素中的元素one