这是你要做的第一件事。scanf("%s")
除非您完全控制输入数据,否则请放弃任何使用的想法。否则,你会为缓冲区溢出敞开心扉。
这个答案显示了一种fgets
用于用户输入的安全方法,提供缓冲区溢出检测/避免和行清除,可以很容易地适应任何输入流。
一旦将行(和整行)作为字符串,并且因此知道它可能的最大大小,您可以简单地使用:
char strBuff[1000]. str1[1000]; // Ensure both big enough.
:
// Use /getLine/fgets to get the line into strBuff.
:
int numScanned = sscanf (strBuff, "%d %d %[^\n]", &int1, &int2, str1);
格式说明符的%[^\n]
作用是将任意数量的非换行符扫描成一个字符串:[]
表示一个字符类,^
意思是“匹配除了后面的字符之外的所有字符,用于(非)匹配的字符是换行符\n
。
标准引文在此答案(a)的底部。
例如,使用该功能:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
使用以下程序:
int main (void) {
int rc, numScanned, int1, int2;;
char strBuff[100], str1[100];
rc = getLine ("Yes> ", strBuff, sizeof(strBuff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", strBuff);
return 1;
}
printf ("OK [%s]\n", strBuff);
numScanned = sscanf (strBuff, "%d %d %[^\n]", &int1, &int2, str1);
printf ("numScanned = %d\n", numScanned);
printf ("int1 = %d\n", int1);
printf ("int2 = %d\n", int2);
printf ("str1 = [%s]\n", str1);
return 0;
}
给出以下输出:
Yes> 100 20 300 20 9 45 -1 blah blah blah
OK [100 20 300 20 9 45 -1 blah blah blah]
numScanned = 3
int1 = 100
int2 = 20
str1 = [300 20 9 45 -1 blah blah blah]
(a)7.20.6.2 The fscanf function
的部分C11
(尽管从 中没有改变C99
)说明了有关[
格式说明符的内容,稍作解释以删除不相关的多字节内容:
[
格式说明符匹配来自一组预期字符(扫描集)的非空字符序列。
相应的参数应该是一个指向字符数组的初始元素的指针,该元素数组的大小足以接受序列和一个终止的空字符,它将自动添加。
转换说明符包括格式字符串中的所有后续字符,直到并包括匹配的右括号 ( ]
)。
括号之间的字符(扫描列表)组成扫描集,除非左括号之后的字符是一个抑扬符 (^),在这种情况下,扫描集包含所有未出现在抑扬符和右括号之间的扫描列表中的字符。如果转换说明符以[]
or开头[^]
,则右括号字符在扫描列表中,并且下一个右括号字符是结束说明的匹配右括号;否则后面的第一个右括号字符是结束规范的字符。