基于分隔符溢出一串整数并转换为int类型?

时间:2016-03-30 04:39:55

标签: c arrays token tokenize

我正在编写一个程序,它接受一对有序数字对的文件作为输入,我想拆分这些有序对并将它们转换为整数以存储在数组中。

文件可能是这样的:

0 1
1 4
9 11
12 45

我想编写一个接受该行的函数(假设已在程序的另一部分中终止为null),在该空间拆分数字,然后将它们存储在大小为2的整数数组中:

 int *store = malloc(2 * sizeof(store));

我已经研究过strtok但是我说的是它不是线程安全的,因此在这种情况下不是最好的选择吗?此外,它不会将数字转换为函数也需要的整数。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

如果要将未知数量的有序对读入有序对的数组中,有许多方法可以解决这个问题。如评论中所述,如果您可以保证每行总是有2个整数,那么可能最简单的方法是将值读取/转换为整数,而fscanf < / p>

(当您在每一行上拥有完全相同的数据格式时,我建议fscanf超过fgetssscanf 次之一,然后它只是为了简化例子)

如果要读取的元素数量未知,则基本方案是为某些合理预期的数字对分配内存,然后根据需要分配realloc。由于您正在阅读有序对,因此可以通过为指向数组的二进制数组分配存储来简化该过程。例如,您的 ordered-pairs op数组声明如下:

    int (*op)[2] = NULL;

您可以使用以下内容为MXLINE个对分配存储空间:

    op = calloc (MXLINE, sizeof *op);

(您可以使用malloccalloc分配)

在分配初始内存以保存有序对后,您只需使用包含两个十进制转换说明符(例如"%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)

注意:初始分配是针对MXLINE2)对的。故意是为了强行重新分配。在现实世界中,你会想要最小化你必须分配内存的次数。所以如果你认为你可以有20对左右,那么设置2432对的初始分配,或者你对数字的最合理猜测是什么(加上一对好的措施))

仔细看看,如果您有任何问题,请告诉我。

答案 1 :(得分:0)

也许这是一个解决方案:

gets(str, 80, fp); // get a line
sscanf(str, "%d %d", &store[0], &store[1]); // read numbers from that line