在C中检测新行

时间:2017-10-06 04:57:06

标签: c

我的代码是这样的:

char k[1000];
while(1){
scanf("%s",&k);
    if(k[0] == '\n'){
    exit(0);}
/* Do some processing on k */
memset(k,0,1000);
}

我的目的是按正常方式处理用户输入,并在用户输入空字符串或新行时终止。这似乎不起作用。

你们可以帮忙解决问题吗?

相关说明,我也想终止,如果它是文件的结尾,我应该如何为EoF做?

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

首先关闭 - 不要使用scanf进行用户输入。这是一个微妙问题的雷区,等待咬新C程序员,而是使用面向行的输入函数,如fgets或POSIX getline。每次都读取(包括)尾随'\n'(只要你为fgets提供足够大小的缓冲区 - 否则它只是继续读取缓冲区大小的字符块,直到它遇到'\n'EOF

因此,要读取用户输入,直到遇到空字符串EOF,您可以执行以下操作:

#include <stdio.h>
#include <string.h>

#define MAXC 1000

int main (void) {

    char k[MAXC] = "";

    for (;;) {                          /* loop until empty-string of EOF */
        printf ("input: ");             /* prompt for input */
        if (fgets (k, MAXC, stdin)) {   /* read line (MAXC chars max) */
            if (*k == '\n') {           /* test for empty-string */
                fprintf (stderr, "empty-string! bye.\n");
                break;
            }
            size_t l = strlen (k);      /* get length of string */
            if (l && k[l - 1] == '\n')  /* check if last char is '\n' */
                k[--l] = 0;             /* overwrite with nul-terminator */
            printf ("got input: %s\n", k);
        }
        else {  /* got EOF */
            fprintf (stderr, "EOF -- bye.\n");
            break;
        }
    }

    return 0;
}

示例使用/输出

>bin\fgets_user_input.exe
input: this
got input: this
input: is some
got input: is some
input: input
got input: input
input:
empty-string! bye.

>bin\fgets_user_input.exe
input: this is more
got input: this is more
input: ^Z
EOF -- bye. 

>bin\fgets_user_input_cl.exe
input: it works the same
got input: it works the same
input: compiled by gcc
got input: compiled by gcc
input: or by cl.exe (VS)
got input: or by cl.exe (VS)
input:
empty-string! bye.

注意:对于Linux Ctrl + d 生成EOF,我恰好在上面的windoze上)

答案 1 :(得分:1)

与往常一样,这里的问题是scanf()的使用不当。 scanf()不是读取输入,而是解析,而格式字符串告诉它如何解析。

在你的情况下,%s正在寻找一系列非空白字符(IOW,一个单词),它会跳过任何前导空格。 \n(换行符)只是一个空白字符,因此总是会被跳过 - 您的scanf()只会等待更多输入,直到它可以解析%s

有关scanf()陷阱的更多信息,我建议你beginners' guide away from scanf()。根据经验,使用交互式输入(这是默认设置),scanf()几乎总是错误的。

scanf("%s", ...)还有一个很大的问题:只要输入包含非空白字符,就会像gets()那样溢出你提供的任何缓冲区。因为这个原因,甚至从C中删除了:缓冲区溢出是非常危险的!因此,请始终使用字段宽度scanf("%999s", ...)。这将解析最多999个字符,其中一个字符用于终止字符串的必要0字节。

但现在关于如何正确地做到这一点:C中有几个功能确实用于读取输入,其中一个用于读取输入的fgets()。在您的代码中,它看起来像这样:

char k[1000];
while(fgets(k, 1000, stdin)){
    if(k[0] == '\n'){
        exit(0);
    }
    /* Do some processing on k */
    memset(k,0,1000);
}

我在这里使用了您的原始代码,还有一些进一步的评论:

  • 最好定义一个宏而不是使用幻数1000,例如#define INPUTSIZE 1000并使用此代码,例如char k[INPUTSIZE];fgets(k, INPUTSIZE, stdin)等。

  • 不需要清除整个数组,因此为了避免不必要的工作,请将memset()替换为k[0] = '\0';或类似内容。 C字符串以第一个0字节结束,因此这足以使k保持空字符串。如果你的程序没有比这里显示的更多,你甚至可以完全摆脱这一点,因为下一个fgets()调用会反正覆盖数组(或者在出错时返回NULL,这将停止循环)。

另请注意,fgets()会在结尾处读取整行包括换行符,因此在处理k的内容时请记住这一点。

答案 2 :(得分:-1)

这个保证为你提供除换行(和EOF)之外的所有内容:

char k[1000];
scanf("%[^\n]", k);

当它返回时,保证下一个字符是换行符,或者根本不存在(达到EOF)。得到它:

int next_char = getcgar();
if (next_char == EOF){
    your_eof_process();
}
else if (nexr_char == '\n'){
    your_newline_process();
}

就个人而言,我只会使用getchar()

char k[1000];
int ind, tempc;
for (ind = 0; ind < sizeof k; ind ++){
    tempc = getchar();
    if (tempc == '\n'){
        // Some stuff
    }
    else if (tempc == EOF){
        // Other stuff
    }
    else {
        k[ind] = tempc;
    }
}
k[sizeof(k)-1] = '\0';