获取scanf在读取换行符时退出?

Mat*_*att 7 c scanf

如果我5 5在终端输入,按回车键,然后再次按回车键,我想退出循环.

int readCoefficents(double complex *c){
    int i = 0;
    double real;
    double img;
    while(scanf("%f %f", &real, &img) == 2)
        c[i++] = real + img * I;


    c[i++] = 1 + 0*I; // most significant coefficient is assumed to be 1
    return i;
}
Run Code Online (Sandbox Code Playgroud)

显然,该代码并没有为我完成工作(是的,我知道有一个缓冲区溢出等待发生).

scanf除非我输入一个字母(或一些非数字,而不是空白字符串),否则不会退出.读取空行后如何让scanf退出?

pax*_*blo 10

您遇到的具体问题是scanf格式字符串%f将跳过空格(包括换行符),直到找到要扫描的实际字符.从c99标准:

A转换规范在下面的步骤执行:
   -输入的空白字符(由指定的isspace功能)被跳过,除非本说明书包括一个'[','c''n'说明符.

并在其他地方描述isspace():

标准的空格字符如下:空格' ',换页'\f',换行符'\n',回车符'\r',水平制表符'\t'和垂直制表符'\v'.

最好的办法是使用fgets获取线路(这可以很容易地防止缓冲区溢出),然后sscanf在结果线上使用.

scanf功能是您应该非常谨慎地看待的功能之一.以下代码是我经常用来处理行输入的代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

 

// Test program for getLine().

int main (void) {
    int rc;
    char buff[10];

    rc = getLine ("Enter string> ", buff, sizeof(buff));
    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", buff);
        return 1;
    }

    printf ("OK [%s]\n", buff);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用各种组合进行测试:

pax> ./prog
Enter string>[CTRL-D]
No input

pax> ./prog
Enter string> a
OK [a]

pax> ./prog
Enter string> hello
OK [hello]

pax> ./prog
Enter string> hello there
Input too long [hello the]

pax> ./prog
Enter string> i am pax
OK [i am pax]
Run Code Online (Sandbox Code Playgroud)

我要做的是使用此函数安全地获取一行,然后简单地使用:

sscanf (buffer, "%f %f", &real, &img)
Run Code Online (Sandbox Code Playgroud)

获取实际值(并检查计数).


事实上,这是一个更接近你想要的完整程序:

#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;
}
Run Code Online (Sandbox Code Playgroud)

 

int main (void) {
    int i = 1, rc;
    char prompt[50], buff[50];
    float real, imag;

    while (1) {
        sprintf (prompt, "\nEnter real and imaginary for #%3d: ", i);
        rc = getLine (prompt, buff, sizeof(buff));
        if (rc == NO_INPUT) break;
        if (*buff == '\0') break;

        if (rc == TOO_LONG) {
            printf ("** Input too long [%s]...\n", buff);
        }

        if (sscanf (buff, "%f %f", &real, &imag) == 2) {
            printf ("Values were %f and %f\n", real, imag);
            i++;
        } else {
            printf ("** Invalid input [%s]\n", buff);
        }
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

以及测试运行:

pax> ./testprog

Enter real and imaginary for #  1: hello
** Invalid input [hello]

Enter real and imaginary for #  1: hello there
** Invalid input [hello there]

Enter real and imaginary for #  1: 1
** Invalid input [1]

Enter real and imaginary for #  1: 1.23 4.56
Values were 1.230000 and 4.560000

Enter real and imaginary for #  2:

pax> _
Run Code Online (Sandbox Code Playgroud)


Mat*_*ith 9

使用fgets读取控制台输入:

   int res = 2;
   while (res == 2) {
       char buf[100];
       fgets(buf, sizeof(buf), stdin);
       res = sscanf(buf, "%f %f", &real, &img);
       if (res == 2)
           c[i++] = real + img * I;
   }
   c[i++] = 1 + 0*I; // most significant coefficient is assumed to be 1
   return i;
Run Code Online (Sandbox Code Playgroud)

  • 那个宣言完全没问题. (2认同)