简体   繁体   English

如何在C中读取输入

[英]How to read input in C

I'm trying to read a line with scanf("%[^\\n]") ; 我正在尝试用scanf("%[^\\n]")读取一行scanf("%[^\\n]") ; right before it I'm reading an integer with "%d", was told to me that scanf doesn't erase the '\\n' after reading, so I have to call fflush() to avoid it, but even doing that I still have the same problems, so here is my code: 就在它之前,我正在读一个带有“%d”的整数,有人告诉我,scanf在阅读后不会删除'\\ n',所以我必须调用fflush()来避免它,但即便这样做我仍然有同样的问题,所以这是我的代码:

scanf("%d", &n);
fflush(stdin);

lines = (char**)malloc(sizeof(char*)*n);

for(i = 0; i < n; i++){
    lines[i] = (char*)malloc(sizeof(char)*1001);
}

for(i = 0;i < n;i++){
    scanf("%[^\n]", linhes[i]);
}

I read an integer and then the scanf doesn't wait, it starts reading the input — doesn't matter what the integer value is, whether 5 or 10, the scanf reads all the strings to empty. 我读取一个整数,然后scanf不等待,它开始读取输入 - 无论整数值是什么,无论是5还是10,scanf都会读取所有字符串为空。 Already tried with fgets and the result is almost the same, except that it reads some of the strings and skips others. 已经尝试了fgets,结果几乎相同,只是它读取了一些字符串并跳过其他字符串。

Let us look at this step by step: 让我们一步一步地看一下:

"... read a line with scanf("%[^\\n]");". “...用scanf读取一行(”%[^ \\ n]“);”。

scanf("%[^\\n]", buf) does not read a line. scanf("%[^\\n]", buf)不读取一行。 It almost does - sometimes. 它几乎 - 有时 - 。 "%[^\\n]" directs scanf() to read any number of non- '\\n' char until one is encountered (that '\\n' is then put back into stdin ) or EOF occurs. "%[^\\n]"指示scanf()读取任意数量的非'\\n' char直到遇到一个(然后将'\\n'放回到stdin )或发生EOF。

This approach has some problems: 这种方法有一些问题:

  1. If the first char is '\\n' , scanf() puts it back into stdin without changing buf in anyway! 如果第一个char'\\n' ,则scanf()会将其放回stdin而不会改变buf buf is left as is - perhaps uninitialized . buf保持原样 - 也许是未初始化的 scanf() then returns 0. scanf()然后返回0。
  2. If at least one non- '\\n' is read, it is saved into buf and more char until a '\\n' occurs. 如果读取至少一个非'\\n' ,则将其保存到buf和更多char直到出现'\\n' A '\\0' is appended to buf and the '\\n' is put back into stdin and scanf() returns 1. This unlimited-ness can easily overfill buf . 一个'\\0'被附加到buf并且'\\n'被放回到stdinscanf()返回1.这个无限制可以很容易地溢出 buf If no char was saved and EOF or input error occurs, scanf() returns EOF . 如果没有保存char并且发生EOF或输入错误,则scanf()返回EOF
  3. Always check the return value of scanf() / fgets() , etc. functions . 始终检查scanf() / fgets()等函数的返回值 If your code does not check it, the state of buf is unknown. 如果您的代码没有检查它,则buf的状态是未知的。

In any case, a '\\n' is still usually left in stdin , thus the line was not fully read. 在任何情况下, '\\n'仍然通常留在stdin ,因此该未被完全读取。 This '\\n' often is an issue for the next input function. 这个'\\n'通常是下一个输入函数的问题。

... scanf doesn't erase the '\\n' after reading ... scanf在读取后不会删除'\\ n'

Another common misconception. 另一个常见的误解。 scanf() reads a '\\n' , or not, depending on the supplied format. scanf()读取'\\n'或不读取,具体取决于提供的格式。 Some formats consume '\\n' , others do not. 有些格式消耗'\\n' ,有些则不消耗。

... call fflush() to avoid it ...调用fflush()来避免它

fflush(stdin) is well defined in some compilers but is not in the C standard. fflush(stdin)在某些编译器中定义明确,但不符合C标准。 The usual problem is code wants to eliminate any remaining data in stdin . 通常的问题是代码想要消除stdin任何剩余数据。 A common alternative, when the end of the line had not yet occurred, is to read and dispose until '\\n' is found: 当线路末端尚未发生时,常见的替代方案是读取并处置,直到找到'\\n'

int ch;  // Use int
while ((ch = fgetc(stdin)) != '\n' && ch != EOF);

I still have the same problems 我仍然有同样的问题

The best solution, IMO, is to read a line of user input and then scan it. 最好的解决方案IMO是读取一行用户输入然后扫描它。

char buf[sizeof lines[i]];
if (fgets(buf, sizeof buf, stdin) == NULL) return NoMoreInput();

// If desired, remove a _potential_ trailing \n
buf[strcspn(buf, "\n")] = 0;

strcpy(lines[i], buf);

I recommend that a buffer should be about 2x the size of expected input for typical code. 我建议缓冲区大小应该是典型代码预期输入大小的2倍。 Robust code, not this snippet, would detect if more of the line needs to be read. 强大的代码,而不是此代码段,将检测是否需要读取更多行。 IMO, such excessively long lines are more often a sign of hackers and not legitimate use. 国际海事组织,这种过长的线路往往是黑客的标志,而不是合法使用。

BLUEPIXY in the comment answered my question: 评论中的BLUEPIXY回答了我的问题:

try "%[^\\n]" change to " %[^\\n]" 尝试"%[^\\n]"更改为" %[^\\n]"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM