C:读取文件并将其存储到数据结构中
因此,我有一个包含以下信息的.txt文档(可以是多行,但在本例中是3行) 我想创建一个读取文件的“read”函数,然后创建一个将文件写入数据结构的“write”函数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
#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()
函数(同样不是一个好的名称选择)打开一个文件,但在返回之前不会检查它是否成功或关闭它。您需要花更多的时间充实它