如何解析char str并创建一个新的int数组

时间:2012-03-09 22:22:09

标签: c

我想用一个从缓冲区中提取的int值填充数组。我想做点什么:

char buffer[BUFF_MAX];
int numbers[NUM_MAX];
int i = 0;    

fgets(buffer, BUFF_MAX, stdin);
while(sscanf(buffer, "%d", &numbers[i]) == 1)
{
    ++i;
}

但是我使用这种方法遇到了各种各样的问题。也许它与缓冲区中的\ n有关?似乎为每个元素分配了相同的值,如果我输入大于130的任何值,则存储垃圾值。

用户将键入以下内容:

12 543 5 234 9

我希望这些值作为5个不同的元素存储在numbers[]中。每次缓冲区中将有不同数量的数字(取决于用户键入的内容)。

3 个答案:

答案 0 :(得分:2)

您可以使用sscanf()转换说明符找出%n在解析字符串时所处的位置,因此:

char buffer[BUFF_MAX];
int numbers[NUM_MAX];
int i = 0;
int offset = 0;
int newlen;

if (fgets(buffer, BUFF_MAX, stdin) != 0)
{
    while (sscanf(buffer + offset, "%d%n", &numbers[i], &newlen) == 1 && i < NUM_MAX)
    {
        ++i;
        offset += newlen;
    }
}

测试

#include <stdio.h>
enum { BUFF_MAX = 1024, NUM_MAX = 32 };

int main(void)
{
    char buffer[BUFF_MAX];
    int numbers[NUM_MAX];
    int i = 0;
    int offset = 0;
    int newlen;

    if (fgets(buffer, BUFF_MAX, stdin) != 0)
    {
        while (sscanf(buffer + offset, "%d%n", &numbers[i], &newlen) == 1 && i < NUM_MAX)
        {
            printf("Found: numbers[%d] = %d\n", i, numbers[i]);
            ++i;
            offset += newlen;
        }
    }
    return 0;
}

输入字符串:

123 456 789 0123456

输出:

Found: numbers[0] = 123
Found: numbers[1] = 456
Found: numbers[2] = 789
Found: numbers[3] = 123456

在C89中添加了%n修饰符,但没有多少人知道它存在。它也在printf()函数族中“起作用”,但在那里更加致命,因为人们不习惯以printf()格式字符串查看输出参数。至少在scanf()等人的情况下,你期待输入。

谨防'格式字符串漏洞',这是一个在您最喜爱的搜索引擎中使用的体面搜索词。你应该小心这些,独立于这个问题。

[已更新以检查fgets()是否表示错误或EOF。始终检查读取操作是否符合预期。好吧,几乎总是 - 如果你正在从一个错误中恢复而不关心读什么,因为你不会使用它,也许你不需要检查。如果您打算使用读取数据,则应检查您是否确实使用了数据。]

答案 1 :(得分:1)

sscanf有一个限制,因为它没有告诉你数据有多长。我使用string.h中的解决方案,即strtol。

char buffer[BUFF_MAX];
int numbers[NUM_MAX];
char* seek, *seekp;
seek = seekp = buffer;
int i = 0;    

fgets(buffer, BUFF_MAX, stdin);
while( 1 == 1)
{
    numbers[i] = strtol(seek, &seek, 10);
    if( seekp == seek || i >= NUM_MAX )
        break;
    seekp = seek;
    ++i;
}

答案 2 :(得分:0)

你总是从缓冲区的开头扫描 - 你需要下一个sscanf从前一个sscanf开始。

为什么要进入缓冲区然后进入sscanf?您可以直接从stdin一次扫描一个int。它更容易,因为当您从stdin读取时,输入被消耗,因此您不必担心它会重复。