我想用一个从缓冲区中提取的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[]
中。每次缓冲区中将有不同数量的数字(取决于用户键入的内容)。
答案 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读取时,输入被消耗,因此您不必担心它会重复。