如何在用户按下C中的特定键之前读取字符串?

时间:2015-11-27 08:28:48

标签: c string

我已经完成了一项任务,我将编写一个程序来读取字符串,直到用户输入$。当用户输入$时,应该停止读取消息,然后程序应转到下一步,即对读取字符串进行一些编码操作。
附加限制:

在作业中不允许使用<conio.h>的库函数。

使用getsscanf功能有什么办法吗?

****编辑:**通过输入$ compiler应停止读取并应转到下一个命令。因此用户将无法输入任何其他文本。**

4 个答案:

答案 0 :(得分:3)

我不认为ISO C提供了将stdin从缓冲行更改为无缓冲(在操作系统tty级别not the C stdio buffering level)的工具,因此仅当用户按下返回时输入才可用

如果您可以使用POSIX功能,那么您可以change the terminal to raw mode。然后它成为特定于操作系统的问题,而不是C问题。当然,Windows将与POSIX OS不同,除非你使用cygwin或者mingw。

除此之外,您可以执行David Rankin在评论中建议的内容,并循环阅读一个字符。

答案 1 :(得分:1)

处于raw-unbufferd模式的键盘

正如彼得所指出的那样,你可以完成你所希望的,即在没有'$'的{​​{1}}的按键时立即停止输入,但它需要设置终端在raw-unbuffered模式下。实质上,您正在改变终端响应按键的方式。

在原始无缓冲模式下,不是在conio.h中缓冲字符,而是在原始无缓冲模式下,每个字符都可立即用于测试,这样您就可以检查每个字符的哨兵角色在阅读时继续。由于您正在更改终端响应每个按键的方式,因此您必须在完成收集输入后重置正常行为。

有几种方法可以检查stdin中字符的可用性。最简单的方法之一是使用stdin来测试文件描述符,并在字符可用时返回一个字符。 A(相对短)的例子是:

select

使用/输出

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

#include <sys/time.h>
#include <termios.h>
#include <errno.h>   /* for errno */
#include <unistd.h>  /* for EINTR */

#define MAXC 256

static struct termios g_old_kbd_mode;

/* kbhit uses select to check for input on stdin. */
static int kbhit (void){
    struct timeval timeout;
    fd_set read_handles;
    int status;

    /* check stdin (fd 0) for activity */
    FD_ZERO (&read_handles);
    FD_SET (0, &read_handles);

    timeout.tv_sec = 0;   /* timeout 0 forces select to return immediately, if  */
    timeout.tv_usec = 0;  /* NULL, select blocks indefinitely.                  */

    do {
        status = select (0 + 1, &read_handles, NULL, NULL, &timeout);
    } while (status == -1 && errno == EINTR);
    return status;
}

/* restore original keyboard attributes */
static void kbd_old_attr (void){
    tcsetattr (0, TCSANOW, &g_old_kbd_mode);
}

int main (void) {

    char buf[MAXC] = {0};
    char *p = buf;
    int c;
    static char init;
    struct termios new_kbd_mode;

    if (init) return 1;

    /* put keyboard (stdin, actually) in raw, unbuffered mode */
    tcgetattr (0, &g_old_kbd_mode);
    memcpy (&new_kbd_mode, &g_old_kbd_mode, sizeof(struct termios));

    new_kbd_mode.c_lflag &= ~(ICANON);
    new_kbd_mode.c_cc[VTIME] = 0;
    new_kbd_mode.c_cc[VMIN] = 1;
    tcsetattr (0, TCSANOW, &new_kbd_mode);

    printf ("\n enter text ('$' ends): ");
    while (!kbhit()) {          /* this only works with timeout 0   */
        c = getchar();          /* get keypress from user */
        if (c == '$') break;    /* test kepress for '$'   */
        *p++ = c;               /* assign char to buf     */
        if (p-buf >= MAXC-1) {  /* check against limit    */
            fprintf (stderr, "warning: character limit reached.\n");
            break;
        }
    }
    *p = 0;             /* null-terminate */
    kbd_old_attr ();    /* restore original attributes  */

    printf ("\n text entered : %s\n\n", buf);

    return 0;
}

注意:在此示例中,$ ./bin/keypress_dollar enter text ('$' ends): abcdefgjik$ text entered : abcdefgjik 要求select返回0.使用0的超时强制选择立即返回fd0中可用的字符while (!kbhit) 剩余文件描述符。由于select的返回值是集合中剩余的描述符的数量 - 它适用于这种有限的情况。要使用超时或NULL,您必须修改调用者,使其不在0范围内。

原创 - 需要用户按Enter键

您可以使用while (...)getchar来读取字符串,直到您到达哨兵角色,例如scanf。使用'$'的一种方法是:

getchar

示例/输出

#include <stdio.h>

#define MAXC 256

int main (void) {

    char buf[MAXC] = {0};
    int i = 0, c;

    printf ("\n enter string  : ");
    while (i + 1 < MAXC && (c = getchar()) != '$' && c != '\n' && c != EOF)
        buf[i++] = c;
    buf[i] = 0;     /* null-terminate */

    printf (" string entered: %s\n\n", buf);

    return 0;
}

注意: $ ./bin/getchar_dollar enter string : a quick brown fox jumps over$ the lazy dog. string entered: a quick brown fox jumps over 后面的所有字符都保留在输入缓冲区中(例如'$'),因此您需要清空{{ 1}}在您下一次输入/读取操作之前,或者您将读取留下作为输入的字符。

答案 2 :(得分:0)

以此为出发点:

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

    void read_input(char buffer[]) 
    {
        char character;
        int i = 0;
        do
        {
            character = getchar(); 
            buffer[i] = character; 
            ++i;
        }
        while ( '$' != character );
        buffer[i - 1] = '\0'; 
    }

    int main (void)
    {
        char input[100] = "";
        printf("Input message: ");
        read_input(input);
        printf("Input = %s\n", input); 
        return 0;
    } 

答案 3 :(得分:0)

试试这个逻辑。它不是一个完整的C代码。但是我希望你能从中得到这个概念。

#define BUF_SIZE 1024
/*=====================*/
char msg[BUF_SIZE], ch;
int count = 0;
do
{
    scanf("%c", &ch);
    if(ch == '$' || count == BUF_SIZE - 1)
    {
         msg[count] = '\0';
         break;
    }
    else
    {
         msg[count] = ch;
    }
    count++;   
}
while(1)