如何从文件中获取 int 和 string 并将其保存在结构中?
How to get int and string from file and save it in structure?
假设我们的文件包含:
1 John
2 Alex
3 Michael
我们可以使用 fscanf()
函数获取一行,但如何将其保存到以下结构:
typedef struct entry {
int n;
char *name;
} entry_t;
我想创建结构数组并将文件中的值保存到其中,并动态执行。我试过这样做
entry_t *prt = malloc ( size * sizof(entry_t) );
//opening file
prt[0].name = malloc ( sizeof("John") );
fscanf (fp,"%d %s", prt[0].n, prt[0].name);
好的,它可以工作,但是如何在从文本文件中获取之前为每个名称分配内存?
我决定使用结构数组,因为我将用它来实现哈希 table.
sizeof("John")
适用于 字符串文字 ,但文件中的名称事先未知,因此必须动态确定大小。
使用fgets()
读一行。
使用sscanf()
、strtol()
、strtok()
解析该行。
示例:
int read_entry(FILE *istream, struct entry *record) {
char buf[200];
if (fgets(buf, sizeof buf, istream) == NULL) return -1; // EOF
buf[strcspn(buf, "\n")] = 0; // lop off potential trailing \n
int start;
int end = 0;
sscanf(buf, "%d %n%*s%n", &record->n, &start, &end);
if (end == 0) {
return 0; // failed to parse
}
record->name = strdup(&buf[start]);
return 1; // Success
}
用法
struct entry record;
while (read_entry(stdin, &record) == 1) {
printf("%d '%s'\n", record.n, record.name);
...
// when done with the record,
free(record.name);
}
strdup()
是 "duplicate" 字符串的常用方法,但它不是标准 C 库的一部分。足够容易编码:
正在将评论转化为答案。
您至少有两个选择。
最便携:
char buffer[1024];
if (fscanf(fp, "%d %1023s", &prt[0].n, buffer) != 2)
…handle I/O (format?) error…
else if ((prt[0].name = strdup(buffer)) == 0)
…handle out-of-memory error…
else
{
…use values, or continue loop…
}
这使用一个大缓冲区来读取值,然后分配适当的内存以供之后的结构使用。注意参数中的溢出保护(并且有必要相差一个)。请注意,strdup()
是 POSIX 的一部分,而不是标准 C 的一部分。它很容易编写,但是:
char *strdup(const char *str)
{
size_t len = strlen(str) + 1;
char *copy = malloc(len);
if (copy != 0)
memmove(copy, str, len);
return copy;
}
通常会有 memmove()
vs memcpy()
的辩论;两者都在这种情况下工作,但 memmove()
无处不在,而 memcpy()
不。
使用 fscanf()
的 POSIX 功能:
if (fscanf(fp, "%d %ms", &prt.n, &prt[0].name) != 2)
…handle I/O (format?) error…
else
{
…use values, or continue loop…
}
请注意,在这种情况下,您确实传递了指针 prt[0].name
的地址,因为 fscanf()
为您分配了必要的内存。
您以后需要释放为每个名称分配的内存,当然,无论您使用哪种解决方案。
假设我们的文件包含:
1 John
2 Alex
3 Michael
我们可以使用 fscanf()
函数获取一行,但如何将其保存到以下结构:
typedef struct entry {
int n;
char *name;
} entry_t;
我想创建结构数组并将文件中的值保存到其中,并动态执行。我试过这样做
entry_t *prt = malloc ( size * sizof(entry_t) );
//opening file
prt[0].name = malloc ( sizeof("John") );
fscanf (fp,"%d %s", prt[0].n, prt[0].name);
好的,它可以工作,但是如何在从文本文件中获取之前为每个名称分配内存? 我决定使用结构数组,因为我将用它来实现哈希 table.
sizeof("John")
适用于 字符串文字 ,但文件中的名称事先未知,因此必须动态确定大小。
使用
fgets()
读一行。使用
sscanf()
、strtol()
、strtok()
解析该行。
示例:
int read_entry(FILE *istream, struct entry *record) {
char buf[200];
if (fgets(buf, sizeof buf, istream) == NULL) return -1; // EOF
buf[strcspn(buf, "\n")] = 0; // lop off potential trailing \n
int start;
int end = 0;
sscanf(buf, "%d %n%*s%n", &record->n, &start, &end);
if (end == 0) {
return 0; // failed to parse
}
record->name = strdup(&buf[start]);
return 1; // Success
}
用法
struct entry record;
while (read_entry(stdin, &record) == 1) {
printf("%d '%s'\n", record.n, record.name);
...
// when done with the record,
free(record.name);
}
strdup()
是 "duplicate" 字符串的常用方法,但它不是标准 C 库的一部分。足够容易编码:
正在将评论转化为答案。
您至少有两个选择。
最便携:
char buffer[1024]; if (fscanf(fp, "%d %1023s", &prt[0].n, buffer) != 2) …handle I/O (format?) error… else if ((prt[0].name = strdup(buffer)) == 0) …handle out-of-memory error… else { …use values, or continue loop… }
这使用一个大缓冲区来读取值,然后分配适当的内存以供之后的结构使用。注意参数中的溢出保护(并且有必要相差一个)。请注意,
strdup()
是 POSIX 的一部分,而不是标准 C 的一部分。它很容易编写,但是:char *strdup(const char *str) { size_t len = strlen(str) + 1; char *copy = malloc(len); if (copy != 0) memmove(copy, str, len); return copy; }
通常会有
memmove()
vsmemcpy()
的辩论;两者都在这种情况下工作,但memmove()
无处不在,而memcpy()
不。使用
fscanf()
的 POSIX 功能:if (fscanf(fp, "%d %ms", &prt.n, &prt[0].name) != 2) …handle I/O (format?) error… else { …use values, or continue loop… }
请注意,在这种情况下,您确实传递了指针
prt[0].name
的地址,因为fscanf()
为您分配了必要的内存。
您以后需要释放为每个名称分配的内存,当然,无论您使用哪种解决方案。