简体   繁体   English

c中的逐行输入

[英]Line wise input in c

how can I enforce following input restriction in c? 如何在c中执行以下输入限制?

First line contains float , Second line contains float , Third line int, 第一行包含float,第二行包含float,第三行int,

after pressing enter three times in console, program should be able to read each line and put the contents in respective int,int,float variables. 在控制台中按Enter三次后,程序应该能够读取每一行并将内容分别放入int,int,float变量中。

After three enter key press program should not wait for user input and start validation. 三按Enter键后,程序不应等待用户输入并开始验证。

some test cases 一些测试用例

line1: 34
line2:4
line3:12
result: ok

line1: 
line2:4
line3:12
result: not ok 

line1: Hi
line2:4
line3:12
result:  not ok 

so far I used the basics 到目前为止,我已经使用了基础知识

    scanf("%f",&p);
    scanf("%f",&r);
    scanf("%d",&t);

it works fine for test case 1 and 3, but fails when I leave an empty line. 它适用于测试用例1和3,但当我留空行时失败。

You should always check the return value of scanf . 您应该始终检查scanf的返回值。

The reason is that the return value is what scanf uses to communicate conversion errors, among other errors. 原因是,返回值是scanf用于传达转换错误以及其他错误的内容。 For example, if your program tells scanf to expect a sequence of decimal digits, and scanf encounters something that doesn't match that pattern, the return value will indicate this failure. 例如,如果您的程序告诉scanf期望使用十进制数字序列,并且scanf遇到与该模式不匹配的内容,则返回值将指示此失败。

The value returned will be the number of items that are successfully assigned to. 返回的值将是成功分配的项目数。 For example, 例如,

char str[128];
int x, y = scanf("%d %127s", &x, str);

If y is 1, then it should be assumed that x is safe to use. 如果y为1,则应假定x是可以安全使用的。 If y is 2, then it should be assumed that both x and str are safe to use. 如果y为2,则应假定xstr都可以安全使用。

This answers part of your question. 这回答了部分问题。 The next part is how you can go about ensuring that the input is in the form of lines . 下一部分是如何确保输入采用线的形式。 scanf doesn't strictly deal with lines ; scanf并不严格处理 it deals with other units, such as %d being an int encoded as a sequence of decimal digits (and a sign); 它处理其他单位,例如%d是编码为十进制数字序列(和符号)的int it'll return once the decimal digit sequence ends... There's no guarantee that the decimal digits will occupy the entirety of the line . 十进制数字序列结束后,它将返回...无法保证十进制数字将占据整个行

There are actually two problems here: leading and trailing whitespace. 实际上,这里存在两个问题:前导空格尾随空格。 All format specifiers, with the exception of [ , c , C , and n , will cause leading whitespace to be discarded. [cCn之外,所有格式说明符都将导致前导空白被丢弃。 If you want to handle leading whitespace differently, you'll need to codify how you expect leading whitespace to be handled. 如果要以不同的方式处理前导空格,则需要整理一下如何处理前导空格。

Consider that discarding user input is almost always (if not always) a bad idea. 考虑到丢弃用户输入几乎总是(如果不总是这样)一个坏主意。 If you don't care what the remainder of the line contains, you could use something like scanf("%*[^\\n]"); getchar(); 如果您不在乎该行的其余部分,则可以使用诸如scanf("%*[^\\n]"); getchar(); scanf("%*[^\\n]"); getchar(); to discard everything trailing up to and including the '\\n' newline character... The first statement would attempt to read as many non-newline characters as possible, and the second would discard the terminating newline character. 舍弃所有尾随的'\\n'换行符...第一个语句将尝试读取尽可能多的非换行符,第二个语句将舍弃终止的换行符。 However, if you want to ensure that the input occupies the entirety of the line, then you need to test the value returned by getchar . 但是,如果要确保输入占据整个行,则需要测试getchar返回的值。

An example using all of these considerations: 使用所有这些注意事项的示例:

/* Test for leading whitespace (including newlines) */
int c = getchar();
if (c != '-' && !isdigit(c)) {
    /* Leading whitespace found */
}
ungetc(c);

/* Test for correct data conversion */
int x, y = scanf("%d", &x);
if (y != 1) {
    /* Something non-numeric was entered */
}

/* Test for trailing newline */
c = getchar();
if (c != '\n') {
    /* Trailing newline found */
}

Armed with this information, perhaps you can come up with an attempt and update your question with some code if you have any problems... 有了这些信息,如果您有任何问题,也许您可​​以尝试并用一些代码更新您的问题...

PS I noticed in the code you wrote, you seem to have %f and %d confused; PS:我在您编写的代码中注意到,您似乎对%f%d感到困惑; %f is for reading into float s, and %d is for reading into int s, not the other way around... %f用于读取float%d用于读取int ,而不是相反...

As soon as I read line wise input , I know that fgets + sscanf must be used instead of direct scanf . 阅读行明智的输入后 ,我知道必须使用fgets + sscanf而不是直接scanf Of course you can use getc / getchar as a workaround, but you can get corner cases, where I find fgets + sscanf cleaner. 当然,您可以使用getc / getchar作为解决方法,但是您可以得到一些极端的案例,在这些案例中我可以找到fgets + sscanf Example to get a float alone on a line: 单独在一行上获得浮点数的示例:

char line[80], dummy[2];
float val;
if (fgets(line, sizeof(line), stdin) == NULL)... 
if (sscanf(line, "%f%1s", &val, dummy) != 1)...
// Ok val was alone on the line with optional ignored blanks before and/or after

You could also add a test for loooong lines : 您还可以添加对loooong行的测试:

if ((line[0] != 0) && (line[strlen(line)-1 != '\n'))...

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

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