C - 有没有办法用 'Enter' 以外的键终止字符串输入?

C - Is there a way to terminate string input with a key other than 'Enter'?

我正在为我的学校开发一个作业调度程序,下面的代码是一个模块的一部分,用于为新作业输入数据,然后将该数据写入文件。由于作业描述可能是一个冗长的段落,我决定允许用户在按下 Enter 键时移动到一个新行以便于输入。到目前为止,我的代码可以按预期工作。 描述是单个字符串,但通常以回车键结束。是否可以用另一个键终止字符串?例如逃生键?如果是这样,我该怎么做?

我正在考虑使用转义 'Esc' 键来终止字符串输入,但我不确定用哪个代码或转义序列来表示该键。

typedef struct {
    char title[60];
    Time duration;
    Date deadline;
    char descrptn[10000];
} Project;

void setStudioProject() {
    Project newProj;
    FILE *fpProj;

    system("cls");
    printf("-----PROJECT SETUP-----\n\n\n");
    //Prompt for project information
    printf("Title: ");
    fgets(newProj.title, 60, stdin);
    fflush(stdin);
    printf("\n\nDescription: \n");
    printf("(No more than 1000 words)\n");

    //loop of concern
    while (fgets(newProj.descrptn, 10000, stdin)) {
        if (getchar() == '\r') { //Whenever the user presses the enter key
            printf("\n"); //...move to a new line
        }
    }
    fflush(stdin);
    //...
}

我希望在按下转义键时读取字符串,以便继续执行。

默认情况下输入是行缓冲的。您可以使用 ncurses(不会这样做)或手动禁用:

#include <stdio.h>
#include <unistd.h>
#include <termios.h>
...
//ensure stdin is a terminal before modifying
if (isatty(STDIN_FILENO)) {
    struct termios t;
    tcgetattr(STDOUT_FILENO, &t);//get current params

    int linebufd = ((t.c_lflag & ICANON) > 0);//check if line-buffered
    if (linebufd) {
        t.c_lflag ^= ICANON;//disable canonical line-buffering
        tcsetattr(STDOUT_FILENO, TCSANOW, &t);//update attributes and enable immediate feedback
    }
}
setvbuf(stdin, NULL, _IONBF, 1);//make stdin stream unbuffered

阅读更多关于:

在评论中,我向提问者建议,通过使用双换行符(空行)而不是 ESC 来指示输入结束,可以更好地解决他的问题。

他要求实现,这里是一个实现。 fgets_until_blankline函数会读取多行,按两次回车返回。

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

char *fgets_until_blankline(char *var, int varsize, FILE *file) {

    int inlen = 0;
    char *rc;

    var[0] = 0;
    while(rc = fgets(var+inlen, varsize-inlen, file)) {
        if(var[inlen] == '\n') {
            var[inlen] = 0;
            break;
        }
        inlen = strlen(var);
    }
    return rc;
}

int main() {

    char var[10000];

    fgets_until_blankline(var, sizeof(var), stdin);
    printf("%s", var);

}