我正在编写一个程序,它接受一对有序数字对的文件作为输入,我想拆分这些有序对并将它们转换为整数以存储在数组中。
文件可能是这样的:
0 1
1 4
9 11
12 45
我想编写一个接受该行的函数(假设已在程序的另一部分中终止为null),在该空间拆分数字,然后将它们存储在大小为2的整数数组中:
int *store = malloc(2 * sizeof(store));
我已经研究过strtok
但是我说的是它不是线程安全的,因此在这种情况下不是最好的选择吗?此外,它不会将数字转换为函数也需要的整数。
我该如何解决这个问题?
答案 0 :(得分:1)
如果要将未知数量的有序对读入有序对的数组中,有许多方法可以解决这个问题。如评论中所述,如果您可以保证每行总是有2个整数,那么可能最简单的方法是将值读取/转换为整数,而fscanf
< / p>
(当您在每一行上拥有完全相同的数据格式时,我建议fscanf
超过fgets
和sscanf
的 次之一,然后它只是为了简化例子)
如果要读取的元素数量未知,则基本方案是为某些合理预期的数字对分配内存,然后根据需要分配realloc
。由于您正在阅读有序对,因此可以通过为指向数组的二进制数组分配存储来简化该过程。例如,您的 ordered-pairs op
数组声明如下:
int (*op)[2] = NULL;
您可以使用以下内容为MXLINE
个对分配存储空间:
op = calloc (MXLINE, sizeof *op);
(您可以使用malloc
或calloc
分配)
在分配初始内存以保存有序对后,您只需使用包含两个十进制转换说明符(例如"%d %d"
)的格式字符串读取每一行,并让fscanf
执行转换。您必须验证2
次转化,然后将值存储在数组中。
保持您添加的对数的运行计数,以便在达到限制时realloc
。一个例子如下所示。不要忘记在不再需要时释放所有内存,并通过内存检查器运行代码以验证您对动态分配内存的使用。
使用您的数据文件将它们放在一个简短的示例中,您可以执行以下操作。注意:程序将从命令行中作为第一个参数给出的文件中读取(如果没有给出文件名,则默认从stdin
读取):
#include <stdio.h>
#include <stdlib.h>
#define MXLINE 2
int main (int argc, char **argv) {
int i, idx = 0, mxline = MXLINE;
int (*op)[2] = NULL;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* allocate/validate initial memory */
if (!(op = calloc (MXLINE, sizeof *op))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1;
}
/* read each ordered pair into 'op' array */
while (fscanf (fp, "%d %d", &op[idx][0], &op[idx][1]) == 2) {
if (++idx == mxline) { /* realloc when limit reached */
void *tmp = realloc (op, sizeof *op * mxline * 2);
if (!tmp) { /* validate reallocation */
fprintf (stderr, "error: realloc failed.\n");
break;
}
op = tmp; /* assign reallocated pointer to op */
mxline *= 2; /* update line allocation limit */
}
}
for (i = 0; i < idx; i++) /* show ordered pairs */
printf ("pair[%3d] %3d : %3d\n", i, op[i][0], op[i][1]);
free (op); /* free allocated memory */
if (fp != stdin) /* close file if not stdin */
fclose (fp);
return 0;
}
示例使用/输出
$ ./bin/array_ptr2array <dat/orderedpairs.txt
pair[ 0] 0 : 1
pair[ 1] 1 : 4
pair[ 2] 9 : 11
pair[ 3] 12 : 45
内存/错误检查
不要忘记验证您对动态分配的内存的使用,并在不再需要时释放所有内存:
$ valgrind ./bin/array_ptr2array <dat/orderedpairs.txt
==8107== Memcheck, a memory error detector
==8107== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8107== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==8107== Command: ./bin/array_ptr2array
==8107==
pair[ 0] 0 : 1
pair[ 1] 1 : 4
pair[ 2] 9 : 11
pair[ 3] 12 : 45
==8107==
==8107== HEAP SUMMARY:
==8107== in use at exit: 0 bytes in 0 blocks
==8107== total heap usage: 3 allocs, 3 frees, 112 bytes allocated
==8107==
==8107== All heap blocks were freed -- no leaks are possible
==8107==
==8107== For counts of detected and suppressed errors, rerun with: -v
==8107== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
(注意:初始分配是针对MXLINE
(2
)对的。故意是为了强行重新分配。在现实世界中,你会想要最小化你必须分配内存的次数。所以如果你认为你可以有20对左右,那么设置24
或32
对的初始分配,或者你对数字的最合理猜测是什么(加上一对好的措施))
仔细看看,如果您有任何问题,请告诉我。
答案 1 :(得分:0)
也许这是一个解决方案:
gets(str, 80, fp); // get a line
sscanf(str, "%d %d", &store[0], &store[1]); // read numbers from that line