我已经完成了一项任务,我将编写一个程序来读取字符串,直到用户输入$
。当用户输入$
时,应该停止读取消息,然后程序应转到下一步,即对读取字符串进行一些编码操作。
附加限制:
在作业中不允许使用<conio.h>
的库函数。
使用gets
或scanf
功能有什么办法吗?
****编辑:**通过输入$ compiler应停止读取并应转到下一个命令。因此用户将无法输入任何其他文本。**
答案 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)