简体   繁体   English

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

[英]Saving data from text file to data structures in C

I have this text file with various records, each record has 4 fields, 3 strings of words and one number, for example 我有这个包含各种记录的文本文件,每个记录有4个字段,3个字符串和一个数字,例如

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

I need to sort those records according to the last number through an insertion sort algorithm, so the second record should be the first one in the list, since 2>1. 我需要通过插入排序算法根据最后一个数字对这些记录进行排序,因此第二个记录应该是列表中的第一个记录,因为2> 1。 To do that, i first need to store each record before comparing them, i'm having some problems with that. 要做到这一点,我首先需要存储每个记录,然后再比较它们,我遇到了一些问题。

I got this until now: 我到现在为止得到了这个:

#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;

}

My current problems: 我目前的问题:

1) this current program is not good for saving string of words. 1)这个当前程序不利于保存字符串。 It's good when the record is like: string; 当记录如下时,它是好的:字符串; string; 串; string; 串; 1 but it won't work with phrases (like in the first example). 1但它不适用于短语(如第一个例子中所示)。

2) I don't really understand the structure of this: i know that i'm saving each record in my array of data structures but i'm having some problems printing each record. 2)我真的不明白这个结构:我知道我在我的数据结构数组中保存每条记录但是我在打印每条记录时遇到一些问题。 Let's say i want to print the second record, how can i do that? 假设我要打印第二条记录,我该怎么做? In my current work i printed one, two, three and st but this way, it will only print the first record. 在我目前的工作中,我打印了one, two, three and st但这样,它只会打印第一个记录。

Using %s when calling any of the scanf functions just reads in text up to the next bit of whitespace, so will work fine if you have single words in your fields, but as you've discovered falls over if there phrases. 在调用任何scanf函数时使用%s只读取文本直到空白的下一位,所以如果你的字段中只有单个单词,那么它会正常工作,但是如果有短语则会发现它会被删除。 It also will read in the delimiters into your strings too, which I doubt you want. 它也会在分隔符中读入你的字符串,我怀疑你想要它。

Instead, a better solution would be to read in the entire line into a string and parse your way through it. 相反,更好的解决方案是将整行读入字符串并通过它解析。 The following bit of code reads in a line of text with fgets and then uses strtok to split it up into chunks separated by semicolons. 下面的代码用fgets读入一行文本,然后使用strtok将其拆分成由分号分隔的块。 It keeps track of how which field it is populating using field_number so if you add more fields, it's easy to expand. 它使用field_number跟踪填充的字段,因此如果添加更多字段,则可以轻松扩展。 And if there are less fields than expected it will stop and move onto the next line. 如果字段少于预期,它将停止并移动到下一行。

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
    }

In answer to your second question, elements is an array. 在回答第二个问题时, elements是一个数组。 If you do elements->one that is the same as doing elements[0].one . 如果你做elements->oneelements[0].one If you want to access the second element in your array, you'd do elements[1].one or (elements+1)->one which is what you're doing with this odd line in your original code: 如果你想访问数组中的第二个元素,你可以使用elements[1].one(elements+1)->one ,这是你在原始代码中使用这个奇数行所做的:

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

when really you should have been using elements[i] as that is a lot easier to read. 什么时候你应该使用elements[i]因为这更容易阅读。

You can use %[^;] in fscanf . 您可以在fscanf使用%[^;] fscanf will read the string until reaches ; fscanf将读取字符串直到达到; . And use ; 并使用; as delimiter for fscanf . 作为fscanf分隔符。 Your code will look like below. 您的代码如下所示。

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

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
       if (fscanf(fpointer, "%[^;];%[^;];%[^;];%d", e->one, e->two, e->three, &e->st) !=3)
            break;
    }

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

}

I think you have pretty much reached the answer to your second question. 我想你几乎已经达到了第二个问题的答案。

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);    
}

Alternatively, you can use the form elements[i].one to access element one in the i'th element. 可替换地,可以使用的形式elements[i].one访问元件one在第i个元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM