C:读取文件并将其存储到数据结构中

C:读取文件并将其存储到数据结构中,c,C,因此,我有一个包含以下信息的.txt文档(可以是多行,但在本例中是3行) 我想创建一个读取文件的“read”函数,然后创建一个将文件写入数据结构的“write”函数 #include<stdio.h> #include<string.h> #define MAXLENGTH 200 typedef struct node{ char query[MAXLENGTH]; }DATA; typedef struct stack{ DATA data[MAX

因此,我有一个包含以下信息的.txt文档(可以是多行,但在本例中是3行)

我想创建一个读取文件的“read”函数,然后创建一个将文件写入数据结构的“write”函数

#include<stdio.h>
#include<string.h>
#define MAXLENGTH 200 
typedef struct node{
    char query[MAXLENGTH];
}DATA;

typedef struct stack{
    DATA data[MAXLENGTH];
    int top;
}Stack;

void write(FILE *file,Stack* st)
{   
    while(!feof(file)){  //Check EOF
        st->top++; 
        fgets(st->data[st->top].query,MAXLENGTH,file); //Scan data line by line and put into data structure
        //printf("%s",st->data[st->top].query); 
    }
}

void read(Stack* st)
{
    FILE *file;
    file = fopen("h.txt", "r");
    write(file,st);
}

int main(){
    int i;
    Stack st;
    st.top = -1;

    read(&st);

    for(i = 0; i<= st.top; i++){  //DISPLAY DATA
        printf("%s\n",st.data[i].query); 
    } 
    fflush(stdin);getchar();
    return 0;
}
到目前为止,我有:

void read()
{
    FILE *file;
    file = fopen("fileName", "r");
    write(file);
}

void write(FILE *file)
 {

 }
我想知道如何将每一行存储到数据结构中,因为C不支持向量。我希望能够创建一个打印功能,在其中可以打印:

  1 //line #1 info here
  2 //etc
  3 //etc

首先,使用
open
fopen
功能打开文档文件

例如:
fp=fopen(文件名,“r”)

然后使用
fgets
逐行读取

例如:
while(fgets(array,BUFSIZ,fp)!=NULL)

读取每行后,使用
sscanf
功能将数据存储在结构中

例如:
sscanf(数组,“%d%s
”,&var[i].id,var[i].name)`

文件中的数据将加载到结构中。

\include
#include<stdio.h>
#include<string.h>
#define MAXLENGTH 200 
typedef struct node{
    char query[MAXLENGTH];
}DATA;

typedef struct stack{
    DATA data[MAXLENGTH];
    int top;
}Stack;

void write(FILE *file,Stack* st)
{   
    while(!feof(file)){  //Check EOF
        st->top++; 
        fgets(st->data[st->top].query,MAXLENGTH,file); //Scan data line by line and put into data structure
        //printf("%s",st->data[st->top].query); 
    }
}

void read(Stack* st)
{
    FILE *file;
    file = fopen("h.txt", "r");
    write(file,st);
}

int main(){
    int i;
    Stack st;
    st.top = -1;

    read(&st);

    for(i = 0; i<= st.top; i++){  //DISPLAY DATA
        printf("%s\n",st.data[i].query); 
    } 
    fflush(stdin);getchar();
    return 0;
}
#包括 #定义MAXLENGTH 200 类型定义结构节点{ 字符查询[MAXLENGTH]; }数据; typedef结构堆栈{ 数据数据[MAXLENGTH]; int top; }堆叠; 无效写入(文件*FILE,堆栈*st) { 而(!feof(file)){//检查EOF st->top++; fgets(st->data[st->top].query,MAXLENGTH,file);//逐行扫描数据并放入数据结构 //printf(“%s”,st->data[st->top].query); } } 无效读取(堆栈*st) { 文件*文件; file=fopen(“h.txt”、“r”); 写入(文件,st); } int main(){ int i; 斯塔克街; st.top=-1; read&st;
for(i=0;i,因为您试图解析包含空格的字符串,而空格又被更多的空格与其他字段隔开(例如
name
address
),则无法读取该行,然后使用
sscanf
解析字符串。这是不可能的。使用
scanf/sscanf
时,字符串的匹配在第一个
空格
处终止(除非指定了
宽度
说明符),使其无法解析包含空格的不同长度字符串。例如:

Jane Smith    123 lala land    123-222-1231
尝试使用
%s
进行分析时,将读取
Jane
而不是更多。除非保证有固定宽度的列,
sscanf
在这种情况下不起作用

使问题更加复杂的是,不仅字符串包含空格,而且分隔符由多个空格组成。因此,不幸的是,在这种情况下,必须使用指针来解析字符串。如何处理?从已知的信息开始

唯一可以做到这一点的是假定电话号码不包含空格。因此,使用
strrchr
(或在字符串末尾设置指针并备份),您只需找到电话号码开头之前的空格。设置
结束指针(ep)
在此空格之前,将原始指针向前移动
1
,然后将电话号码复制到结构中

#include<stdio.h>
#include<string.h>
#define MAXLENGTH 200 
typedef struct node{
    char query[MAXLENGTH];
}DATA;

typedef struct stack{
    DATA data[MAXLENGTH];
    int top;
}Stack;

void write(FILE *file,Stack* st)
{   
    while(!feof(file)){  //Check EOF
        st->top++; 
        fgets(st->data[st->top].query,MAXLENGTH,file); //Scan data line by line and put into data structure
        //printf("%s",st->data[st->top].query); 
    }
}

void read(Stack* st)
{
    FILE *file;
    file = fopen("h.txt", "r");
    write(file,st);
}

int main(){
    int i;
    Stack st;
    st.top = -1;

    read(&st);

    for(i = 0; i<= st.top; i++){  //DISPLAY DATA
        printf("%s\n",st.data[i].query); 
    } 
    fflush(stdin);getchar();
    return 0;
}
ep
开始,向后操作,直到找到第一个非空格字符(地址字段的末尾),并在那里设置一个
null终止
字符

下一个已知点是字符串的开头。从那里开始,找到第一个
双空格
(假设姓名、地址和电话字段都至少用两个空格隔开)。您知道双空格中的第一个是名称字段的结尾,请在此处设置一个以
结尾的
null字符。(此时,您可以通过读取字符串的开头将名称读取/复制到结构中)

最后,继续工作,直到找到下一个非空格字符。这是地址的开始。将地址复制到结构,就完成了。(对每行重复此过程)

有时,在没有合理分隔符的情况下,您必须退回到使用指针单步遍历字符串并逐段处理。这就是其中的一种情况。请查看以下内容,如果您有问题,请告诉我:

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

#define EMAX 128

typedef struct entry {
    char name[32];
    char address[32];
    char phone[16];
} entry;

size_t readtxtfile (char *fn, entry *array);
void prn_entries (entry *array);

int main (int argc, char **argv) {

    /* validate number of arguments */
    if (argc < 2 ) {
        fprintf (stderr, "error: insufficient input, usage: %s <filename1>\n", argv[0]);
        return 1;
    }

    /* initialize all variables */
    size_t index = 0;
    entry contacts[EMAX] = {{{0}, {0}, {0}}};

    /* read file into an array of entries,
    number of entries, returned to index */
    index = readtxtfile (argv[1], contacts);

    /* simple print function */
    if (index > 0)
    {
        printf ("\nNumber of entries in contacts : %zu\n\n", index);
        prn_entries (contacts);
    }
    else
        fprintf (stderr, "error: no entries read from file '%s'\n.", argv[1]);

    return 0;
}

size_t readtxtfile (char *fn, entry *array)
{
    if (!fn) return 0;              /* validate filename provided       */

    char *ln = NULL;                /* NULL forces getline to allocate  */
    size_t n = 0;                   /* max chars to read (0 - no limit) */
    ssize_t nchr = 0;               /* number of chars actually read    */
    size_t idx = 0;                 /* couner for number of entries     */
    FILE *fp = NULL;                /* file pointer to open file fn     */

    /* open / validate file */
    if (!(fp = fopen (fn, "r"))) {
        fprintf (stderr, "%s() error: file open failed '%s'.", __func__, fn);
        return 0;
    }

    /* read each line from file */
    while ((nchr = getline (&ln, &n, fp)) != -1)
    {
        /* strip newline or carriage rtn    */
        while (nchr > 0 && (ln[nchr-1] == '\n' || ln[nchr-1] == '\r'))
            ln[--nchr] = 0;

        /* create a copy of ln to preserve start address */
        char *lcpy = strdup (ln);
        if (!lcpy) {
            fprintf (stderr, "%s() error: memory allocation failed.\n", __func__);
            continue;
        }

        char *p = strrchr (lcpy, ' ');                  /* find last space in line      */
        char *ep = p - 1;                               /* set end pointer 1 before     */

        p++;                                            /* advance to next char         */
        strncpy (array[idx].phone, p, strlen (p));      /* copy p to phone              */

        while (ep > lcpy && *ep == ' ') ep--;           /* find first space after addr  */
        *(++ep) = 0;                                    /* null-terminat at that space  */

        p = lcpy;           /* start at beginning of string and find first double-space */
        while (*(p + 1) && !(*(p + 1) == ' ' && *p == ' ')) p++;

        *p = 0;                     /* null-terminate at first space    */

        while (*(++p) == ' ');      /* find first char in addr          */

        strncpy (array[idx].address, p, strlen (p));    /* copy p to address            */
        strncpy (array[idx].name, lcpy, strlen (lcpy)); /* copy lcpy to name            */

        free (lcpy);                /* free memory allocated by strdup  */
        lcpy = NULL;                /* reset pointer NULL               */

        idx++;                      /* increment entry index            */
        if (idx == EMAX)            /* check if EMAX reached & return   */
        {
            fprintf (stderr, "%s() warning: maximun number of entries read\n", __func__);
            break;
        }
    }

    if (ln) free (ln);              /* free memory allocated by getline */
    if (fp) fclose (fp);            /* close open file descriptor       */

    return idx;
}

/* print an array of character pointers. */
void prn_entries (entry *array)
{
    register size_t n = 0;
    while (strlen (array[n].name) > 0)
    {
        printf (" (%2zu.)  %-32s %-32s %s\n", n, array[n].name, array[n].address, array[n].phone);
        n++;
    }
}
注意:使用
getline
或任何时候动态为字符串分配空间时,在使用不保留字符串原始开头的函数(如
strtok
或使用字符串变量手动迭代字符串)更改内存块之前,需要进行复制.
getline
为您分配
ln
的内存(如果最初设置为NULL)因此,
getline
负责释放它。如果您更改字符串的起始地址,或使部分字符串无法访问,那么当
getline
尝试
realloc
释放该内存块时,将发生内存错误。复制将为您节省大量的麻烦


在上面的示例中,创建了由
getline
分配的
ln
的副本。根据需要分配字符指针,以保留
lcpy
的起始地址,而不是使用第二个指针,原始起始地址将丢失。当您(或退出时的程序)尝试释放
lcpy
大量错误(或分段错误)时可能发生。

您可以使用hastable来存储和查询记录。数据结构是什么意思?您能提供一个示例吗?您需要读取整行数据,并根据多个相邻空格拆分字段。您还没有向我们展示您的结构。您有一个名为
write()
的函数(首先不是一个好的名称选择)从文件中读取数据并以某种方式将数据存储在您的结构数组中。
read()
函数(同样不是一个好的名称选择)打开一个文件,但在返回之前不会检查它是否成功或关闭它。您需要花更多的时间充实它