【问题标题】:C - Read from keyboard (controlled by Ctrl+D) [closed]C - 从键盘读取(由 Ctrl+D 控制)[关闭]
【发布时间】:2016-10-28 07:16:22
【问题描述】:

我正在尝试在 C 中模拟 tail 命令,但我遇到了问题。

我需要从键盘 (STDIN) 读取一些行(我不在乎有多少行)。当按下 Ctrl+d 时,该读取将被中断。这个功能我做了,但是不行。

int tail(int N)
{
    int i, j, c;
    char ** lines;
    /* Char matrix dynamic declaration */
    lines=NULL; // Char matrix declaration
    lines=malloc(N*sizeof(char *));
    for (i=0; i<N; i++){ 
        lines[i]=malloc(80 * sizeof(char));
    }
    i=0;
    while (true){ // I tried this loop, but doesn't work
        /* This works. Lanes reading from the user's keyboard */
        if(i>=N){
            for(j=0; j<=N; j++){
                if (j<(N-1))
                    lines[j]=lines[j+1];
            }
            scanf(" %[^\n]", lines[N-1]);
        }else{
            scanf(" %[^\n]", lines[i]);
        }
        i++;
        /* ------------------------------------ */
        c=getchar(); // This doesn't work
        if(c==EOF)
        goto end;
    }
end:
    for (i=0; i<N; i++){
        printf("%s\n", lines[i]); // Showing those lanes
        free(lines[i]); // Free memory
    }    
    free(lines);
    lines = NULL;

    return 0;
}

我的问题是关于读取用户的键盘行并同时读取 ctrl+d。当我启动该功能时,它让我写了一些行,但是当我按下 Ctrl+D 时它没有检测到。我该怎么做?

编辑:

我尝试了一种捕获 Ctrl+d 的新方法,现在我的程序结束了,但是我遇到了一些问题。这是新代码:

int tail(int N)
{
    int i, j, k, c;
    char ** lines;

    lines=NULL;
    lines=malloc(N*sizeof(char *));
    for (i=0; i<N; i++){ 
        lines[i]=malloc(MAXLON * sizeof(char));
    }
    i=0;
    while (true){
        /* Read lines from keyboard. */
        if(i<N)
            scanf(" %[^\n]", lines[i]);
        else{
            for(j=0; j<N-1; j++){
                for(k=0; k<MAXLON; k++){
                    lines[j][k]=lines[j+1][k];      
                }
            }
            scanf(" %[^\n]", lines[N-1]);
        }
        /* ------------------------------------ */
        if((c=getchar())==EOF) break;
        else i++;
    }

    for (i=0; i<N; i++){
        printf("%s\n", lines[i]);
        free(lines[i]);
    }
    free(lines);
    lines= NULL;

    return 0;

}

现在,我的程序从键盘捕获 N 行,直到我按 2 次 Ctrl+d,但我现在的问题是:如果我写 5 行是(例如,带有 tail(3),它显示最后 3 行):

Line 1 
Line 2 
Line 3 
Line 4 
Line 5  
AND HERE I PRESS 2 TIMES CTRL+D

函数显示:

Line 4
Line 5
Line 5

怎么了?函数必须显示:

Line 3
Line 4
Line 5

非常感谢!

【问题讨论】:

  • 在某些情况下goto 和标签是可以接受的。将它们用于循环或循环控制并不是这些情况中的一种。如果您想跳出循环,请使用break 语句。
  • 至于你的问题,当你按下文件结尾的键盘序列时,它通常必须在一个空行上。
  • 您好!我也尝试过休息,但没有奏效。当我从键盘上写下一行并按回车然后按 Ctrl+D 时,函数没有完成...
  • 在 Ctrl+D 之后是否也按了 Enter
  • 这与您之前关于该主题的问题有何不同:Read from keyboard (controlled by Ctrl+d)?

标签: c linux stdin ctrl


【解决方案1】:

请查看以下代码作为工作示例:

#include <stdio.h>

int main(int argc, char* argvp[])
{
    char buf[1024];

    while(gets(buf))
    {
        printf("Read: %s\n", buf);
    }
    if (ferror(stdin))
        puts("I/O error when reading");
    else if (feof(stdin))
        puts("End of file reached successfully");
}

请注意

  1. 输入缓冲区的大小buf 不应硬编码
  2. gets 已弃用,您应该使用其他类似 fgets
  3. 行中间的gets 无法识别END-OF-FILE。它必须是第一行符号。在我的 RHEL 7.1 上也是如此,但在您的系统上可能会有所不同
  4. stdin 应替换为您的真实输入文件描述符

【讨论】:

  • 我已经使用你的代码(不一样,只是类似的东西)试图从 STDIN 中捕获 Ctrl+d。但现在我有另一个错误。你能修改一下我编辑过的主要帖子吗?
  • 您无需致电getc() 。您的第一个Ctrl+D 结束您对scanf 的调用,第二个Ctrl+D 退出该函数。由于最后一个scanf 被中止,lines[N-1] 的内容没有改变,你总是会看到最后输入的行两次。
  • 我可以做些什么来解决这个问题?
  • 按照我的建议使用fgets。和sscanf 处理用户输入。换句话说,将我的示例中的 printf 替换为您的 while 循环体,并相应地修改代码。
  • 非常感谢。这工作得很好。感谢您的宝贵时间。
猜你喜欢
  • 2014-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-24
  • 1970-01-01
  • 1970-01-01
  • 2014-06-02
相关资源
最近更新 更多