文件到c中的动态数组
File to dynamic array in c
免责声明:我是 C 的新手。
将 .txt 文件(也可以是其他文件类型)中的每一行转换为动态 calloc() 数组的最佳方法是什么,反之亦然?
在我的文件中,我必须遵循:
1 Hello
2 18
3 World
4 15
etc...
我想要这样的数组:
[0] Hello
[1] 18
[2] World
[3] 15
etc...
我现在的代码:
FILE *file;
file = fopen("test.txt", "r");
int i = 0;
//make dynamic calloc array
//while line!= EOF
//put line[i] into array
//i++
//realloc array, size +1
fclose(file);
这种做法好还是有更好的?
如果有人可以在代码方面帮我一点忙,我将不胜感激。
你接近正确的解决方案,但在这里你每次有新行时都重新分配动态数组,你可以做的是在数组中提前分配 N
字节并重新分配每次使用这个大小,这将避免数组和系统调用的频繁内存移动:
FILE *file;
file = fopen("test.txt", "r");
int i = 0;
int max = 256;
int resize = 512;
char **arr = malloc(max * sizeof(*arr));
//make dynamic calloc array
//while line!= EOF
//put line[i] into array
//i++
if(i == max)
realloc array, size + reisze;
fclose(file);
我会先获取行数,然后为数组分配内存,以避免 realloc() 调用(可能分配一个新的内存块并复制内存区域)。
但我不确定这种方式是否更有效率。
这是我的示例代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static int get_nlines(FILE* fp)
{
int nlines = 0;
int ch;
while (!feof(fp)) {
ch = fgetc(fp);
if (ch == '\n') {
nlines++;
}
}
fseek(fp, 0, SEEK_SET);
return nlines;
}
static char* get_value(char* s)
{
char* pch;
pch = strtok(s, " ");
if (pch != NULL) {
pch = strtok(NULL, " ");
if (pch != NULL) {
return strdup(pch); // need to free() after use
} else {
return NULL;
}
} else {
return NULL;
}
}
int main()
{
FILE* fp = fopen("test.txt", "r");
if (fp != NULL) {
int nlines = get_nlines(fp);
printf("nlines: %d\n", nlines);
// make values..
char** values = calloc(nlines + 1, sizeof(char*)); // +1 for a sentinel
if (values != NULL) {
char line[1024];
int idx = 0;
while (fgets(line, sizeof(line), fp) != NULL) {
values[idx] = get_value(line);
idx++;
}
}
// use values..
char** p = &values[0];
while (*p != NULL) {
printf("%s\n", *p);
p++;
}
// clean values..
p = &values[0];
while (*p != NULL) {
free(*p);
p++;
}
fclose(fp);
} else {
perror("test.txt");
}
}
结果:
$ ./a.out
nlines: 4
Hello
18
World
15
免责声明:我是 C 的新手。
将 .txt 文件(也可以是其他文件类型)中的每一行转换为动态 calloc() 数组的最佳方法是什么,反之亦然?
在我的文件中,我必须遵循:
1 Hello
2 18
3 World
4 15
etc...
我想要这样的数组:
[0] Hello
[1] 18
[2] World
[3] 15
etc...
我现在的代码:
FILE *file;
file = fopen("test.txt", "r");
int i = 0;
//make dynamic calloc array
//while line!= EOF
//put line[i] into array
//i++
//realloc array, size +1
fclose(file);
这种做法好还是有更好的? 如果有人可以在代码方面帮我一点忙,我将不胜感激。
你接近正确的解决方案,但在这里你每次有新行时都重新分配动态数组,你可以做的是在数组中提前分配 N
字节并重新分配每次使用这个大小,这将避免数组和系统调用的频繁内存移动:
FILE *file;
file = fopen("test.txt", "r");
int i = 0;
int max = 256;
int resize = 512;
char **arr = malloc(max * sizeof(*arr));
//make dynamic calloc array
//while line!= EOF
//put line[i] into array
//i++
if(i == max)
realloc array, size + reisze;
fclose(file);
我会先获取行数,然后为数组分配内存,以避免 realloc() 调用(可能分配一个新的内存块并复制内存区域)。 但我不确定这种方式是否更有效率。 这是我的示例代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static int get_nlines(FILE* fp)
{
int nlines = 0;
int ch;
while (!feof(fp)) {
ch = fgetc(fp);
if (ch == '\n') {
nlines++;
}
}
fseek(fp, 0, SEEK_SET);
return nlines;
}
static char* get_value(char* s)
{
char* pch;
pch = strtok(s, " ");
if (pch != NULL) {
pch = strtok(NULL, " ");
if (pch != NULL) {
return strdup(pch); // need to free() after use
} else {
return NULL;
}
} else {
return NULL;
}
}
int main()
{
FILE* fp = fopen("test.txt", "r");
if (fp != NULL) {
int nlines = get_nlines(fp);
printf("nlines: %d\n", nlines);
// make values..
char** values = calloc(nlines + 1, sizeof(char*)); // +1 for a sentinel
if (values != NULL) {
char line[1024];
int idx = 0;
while (fgets(line, sizeof(line), fp) != NULL) {
values[idx] = get_value(line);
idx++;
}
}
// use values..
char** p = &values[0];
while (*p != NULL) {
printf("%s\n", *p);
p++;
}
// clean values..
p = &values[0];
while (*p != NULL) {
free(*p);
p++;
}
fclose(fp);
} else {
perror("test.txt");
}
}
结果:
$ ./a.out
nlines: 4
Hello
18
World
15