在 Unix 中使用文件重定向后,如何重新定义 stdin 以指向控制台?

Jac*_*cob 5 c unix

我在 Unix 中工作,我应该首先通过重定向读取文本,然后要求用户输入特定字符并计算它在字符数组中出现的次数。

const int MAX = 8000;
int input = 1;
int i = 0;
char text[MAX], letter;
while(input != 0)
{
    scanf("%c", &text[i]);
    if(text[i] == '0')
        input = 0;
    i++;
}
printf("\n%s",text);

printf("\nEnter a letter to search for in the text: ");
scanf("%c", &letter)
Run Code Online (Sandbox Code Playgroud)

目前,我正在通过重定向打印正确的文件,但是我的第二个文件scanf被跳过。我使用以下命令重定向文件:./a.out < filename.txt

如果我尝试打印该字符,letter那么它将不会产生任何结果。\n它必须仍然从文本文件的空行中读取。如何阻止scanf读取同一文本文件并让我在控制台中从键盘输入字母?作为一项作业,我必须使用该命令./a.out < filename.txt

Mar*_*lli 5

freopen()功能正是您所寻找的。您只需使用它来(重新)打开/dev/ttystdin. /dev/tty是一个特殊文件,指的是启动程序的终端。

手册页

freopen()函数打开名称为 by 指向的字符串的文件pathname,并将指向的流stream与其关联。原始流(如果存在)被关闭。参数mode的使用方式与函数中一样fopen()

[...]

该函数的主要用途是更改与标准文本流( 、、或)freopen()关联的文件stderrstdinstdout

这是一个例子:

// ...

FILE *tty;

tty = freopen("/dev/tty", "r", stdin);
if (tty == NULL) {
    perror("Unable to open terminal for reading");
    exit(1);
}

printf("Enter a letter to search for in the text: ");

// Now scanf will read from the console where the process started.
scanf("%c", &letter);
Run Code Online (Sandbox Code Playgroud)

顺便说一下,你的程序有一些问题。您可以读取超出数组末尾的内容text,但无法使用 NUL 字符正确终止它,并且也不检查错误。更正确的版本是:

const size_t MAX = 8000;
char text[MAX];
size_t i;
int c;

for (i = 0; i < MAX; i++)
{
    c = fgetc(stdin);

    if (c == EOF)
        break;

    text[i] = (char)c;
}

text[i] = '\0';

puts(text);
Run Code Online (Sandbox Code Playgroud)


Gra*_*eme 1

有几种方法可以做到这一点,最简单的可能就是打开/dev/tty一个特殊设备,引用附加到当前进程的终端。我不建议替换stdin,因为那样您将无法访问重定向到那里的文件。相反,只需使用不同的文件指针并使用 和 等fscanf函数fgetc。例如:

FILE *tty = fopen("/dev/tty", "r");

// fopen will return NULL if there is no attached terminal
if(NULL == tty)
{
     fputs("Failed opening /dev/tty", stderr);
}
else
{
    printf("\nEnter a letter to search for in the text: ");

    // Read a character from the terminal
    char search = fgetc(tty);

    // Now you can still read from the file on stdin and search for
    // your letter without needing an array (which may not be large
    // enough for the whole file)
    char ch;
    int count = 0;
    while(EOF != (ch = getchar())
    {
        if(ch == search)
            ++count;
    }

    printf("%d occurrences of %c\n", count, search);
}
Run Code Online (Sandbox Code Playgroud)

有关/dev/tty其他类似特殊文件的更多信息,请参阅:https://unix.stackexchange.com/questions/60641/linux-difference- Between-dev-console-dev-tty-and-dev-tty0