英文:
combining fgets/scanf and switch to read a character
问题
我想创建一种菜单。我将输入一个字符,根据输入的字符打印相应的文本。对我来说,问题在于下面的代码中的默认选项。我希望它能识别不仅是字符,还包括字符串在内的所有不是1、2、3或q的内容。如果输入是“sf<ssad”,我不希望它打印“Invalid input”七次,只希望打印一次。另外,如果我输入“qf<<dsc”,即使第一个字符是有效的,我也希望将整个输入视为无效,因为它不止一个字符。类似地,输入“1sd<j”不应该打印“hello”,而应该打印“Invalid input”。
我想要一个可靠的代码,最好不包括scanf,并且易于阅读。我尝试了以下代码:
#include <stdio.h>
int main(void) {
char cmd;
do {
printf("Enter 1 to print hello, enter 2 to print world, enter 3 to print hello world, and enter q to quit\n");
printf("Enter: ");
scanf(" %c", &cmd);
switch(cmd) {
case '1' : printf("hello\n"); break;
case '2' : printf("world\n"); break;
case '3' : printf("hello world\n"); break;
case 'q' : printf("Exiting...\n"); break;
default : printf("Invalid input!\n"); break;
}
} while(cmd!='q');
return 0;
}
这仍然不足够,因为如果我输入"sf<ssad",将会打印"Invalid input"七次。我尝试了一些其他版本,但它们有类似的问题。我有一个想法是使用fgets,然后取第一个字符,然后使用atoi,尽管我不确定会是什么样子。提前感谢您的帮助。
英文:
I would like to create a kind of menu. I will enter a character and depending on what character some text will be printed. The problem for me lies in the default option in the code bellow. I want it to recognize everything that is not 1, 2, 3 or q. Not just characters, but strings as well. If the input is "sf<ssad", I do not want it to print "Invalid input" 7 times, only once. Additionally, if I enter "qf<<dsc", even though the first character is valid, I want to count the whole input as invalid since it is more than one character. Similarly, an input like "1sd<j" should not print the result "hello". Instead it should print it as "Invalid input".
I want a reliable code that preferably does not include scanf and is easy on the eyes. I tried the following:
#include <stdio.h>
int main(void) {
char cmd;
do {
printf("Enter 1 to print hello, enter 2 to print world, enter 3 to print hello world and enter q to quit\n");
printf("Enter: ");
scanf(" %c", &cmd);
switch(cmd) {
case '1' : printf("hello\n"); break;
case '2' : printf("world\n"); break;
case '3' : printf("hello world\n"); break;
case 'q' : printf("Exiting...\n"); break;
default : printf("Invalid input!\n"); break;
}
} while(cmd!='q');
return 0;
}
This is not sufficient since if I enter "sf<ssad", "Invalid input" will be printed 7 times. I tried some other versions but they had similar problems. One idea I have is to use fgets, and then take the first character and then use atoi, although I am not sure what it would look like. Thanks in advance.
答案1
得分: 1
Call fgets()
, check for error, and then set cmd
to the first character of the line. Then the rest of your code is the same.
英文:
Call fgets()
, check for error, and then set cmd
to the first character of the line. Then the rest of your code is the same.
char line[100];
char cmd;
do {
printf("Enter 1 to print hello, enter 2 to print world, enter 3 to print hello world and enter q to quit\n");
printf("Enter: ");
char *res = fgets(line, sizeof line, stdin);
if (!res) {
break;
}
cmd = line[0];
switch(cmd) {
case '1' : printf("hello\n"); break;
case '2' : printf("world\n"); break;
case '3' : printf("hello world\n"); break;
case 'q' : printf("Exiting...\n"); break;
default : printf("Invalid input!\n"); break;
}
} while (cmd != 'q');
答案2
得分: 0
以下是翻译好的部分:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
void get_line_from_user(const char prompt[], char buffer[], int buffer_size);
int main(void)
{
bool quit = false;
while (!quit)
{
char line[200];
// 打印菜单
printf(
"Menu:\n"
"Enter 1 to print hello,\n"
"enter 2 to print world,\n"
"enter 3 to print hello world,\n"
"or enter q to quit\n"
);
// 从用户获取一行输入
get_line_from_user("Enter choice: ", line, sizeof line);
// 验证用户是否输入了一个字符
if (line[0] == '\0' || line[1] != '\0')
{
printf("Error: Please only enter a single character!\n\n");
continue;
}
switch (line[0])
{
case '1':
printf("hello\n");
break;
case '2':
printf("world\n");
break;
case '3':
printf("hello world\n");
break;
case 'q':
printf("Exiting...\n");
quit = true;
break;
default:
printf("Invalid input!\n");
}
// 添加空行
printf("\n");
}
return EXIT_SUCCESS;
}
// 这个函数将从用户那里读取精确的一行输入。
// 它会删除换行符(如果存在的话)。
// 如果行太长而无法放入缓冲区,则函数将自动重新提示用户输入。
// 失败时,该函数将不会返回,而是会打印错误消息并调用 "exit"。
void get_line_from_user(const char prompt[], char buffer[], int buffer_size)
{
for (;;)
{
char *p;
// 提示用户输入
fputs(prompt, stdout);
// 尝试读取一行输入
if (fgets(buffer, buffer_size, stdin) == NULL)
{
printf("Error reading from input!\n");
exit(EXIT_FAILURE);
}
// 尝试找到换行符
p = strchr(buffer, '\n');
// 确保完整行都被读入(即缓冲区不够大以存储整行)
if (p == NULL)
{
int c;
// 如果下一个字符不是换行符,或者我们达到了文件末尾(例如,如果输入来自文件或用户在终端中输入文件末尾),
// 则缺少换行符是可以接受的
if ((c = getchar()) != '\n' && !feof(stdin))
{
if (c == EOF)
{
printf("Error reading from input!\n");
exit(EXIT_FAILURE);
}
printf("Input was too long to fit in buffer!\n");
// 丢弃剩余的行
do
{
c = getchar();
if (c == EOF)
{
printf("Error reading from input!\n");
exit(EXIT_FAILURE);
}
} while (c != '\n');
// 通过重新启动循环来重新提示用户输入
continue;
}
}
else
{
// 通过用空字符覆盖它来删除换行符
*p = '\0';
}
// 输入正常,跳出循环
break;
}
}
这是程序的行为:
Menu:
Enter 1 to print hello,
enter 2 to print world,
enter 3 to print hello world,
or enter q to quit
Enter choice: sf<ssad
Error: Please only enter a single character!
Menu:
Enter 1 to print hello,
enter 2 to print world,
enter 3 to print hello world,
or enter q to quit
Enter choice: qsf<dsf
Error: Please only enter a single character!
Menu:
Enter 1 to print hello,
enter 2 to print world,
enter 3 to print hello world,
or enter q to quit
Enter choice: 1
hello
Menu:
Enter 1 to print hello,
enter 2 to print world,
enter 3 to print hello world,
or enter q to quit
Enter choice: 2
world
Menu:
Enter 1 to print hello,
enter 2 to print world,
enter 3 to print hello world,
or enter q to quit
Enter choice: 3
hello world
Menu:
Enter 1 to print hello,
enter 2 to print world,
enter 3 to print hello world,
or enter q to quit
Enter choice: q
Exiting...
英文:
> If the input is "sf<ssad", I do not want it to print "Invalid input" 7 times, only once.
In that case, you should read an entire line of input at once, instead of one character at once. For this, I recommend that you use the function fgets
instead of scanf
.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
void get_line_from_user( const char prompt[], char buffer[], int buffer_size );
int main( void )
{
bool quit = false;
while ( !quit )
{
char line[200];
//print menu
printf(
"Menu:\n"
"Enter 1 to print hello,\n"
"enter 2 to print world,\n"
"enter 3 to print hello world,\n"
"or enter q to quit\n"
);
//get one line of input from the user
get_line_from_user( "Enter choice: ", line, sizeof line );
//verify that user entered exactly one character
if ( line[0] == '\0' || line[1] != '\0' )
{
printf( "Error: Please only enter a single character!\n\n" );
continue;
}
switch( line[0] )
{
case '1':
printf( "hello\n" );
break;
case '2':
printf( "world\n" );
break;
case '3':
printf( "hello world\n" );
break;
case 'q':
printf( "Exiting...\n" );
quit = true;
break;
default:
printf("Invalid input!\n");
}
//add spacing
printf( "\n" );
}
return EXIT_SUCCESS;
}
//This function will read exactly one line of input from the
//user. It will remove the newline character, if it exists. If
//the line is too long to fit in the buffer, then the function
//will automatically reprompt the user for input. On failure,
//the function will never return, but will print an error
//message and call "exit" instead.
void get_line_from_user( const char prompt[], char buffer[], int buffer_size )
{
for (;;) //infinite loop, equivalent to while(1)
{
char *p;
//prompt user for input
fputs( prompt, stdout );
//attempt to read one line of input
if ( fgets( buffer, buffer_size, stdin ) == NULL )
{
printf( "Error reading from input!\n" );
exit( EXIT_FAILURE );
}
//attempt to find newline character
p = strchr( buffer, '\n' );
//make sure that entire line was read in (i.e. that
//the buffer was not too small to store the entire line)
if ( p == NULL )
{
int c;
//a missing newline character is ok if the next
//character is a newline character or if we have
//reached end-of-file (for example if the input is
//being piped from a file or if the user enters
//end-of-file in the terminal itself)
if ( (c=getchar()) != '\n' && !feof(stdin) )
{
if ( c == EOF )
{
printf( "Error reading from input!\n" );
exit( EXIT_FAILURE );
}
printf( "Input was too long to fit in buffer!\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
//this error message will be printed if either
//a stream error or an unexpected end-of-file
//is encountered
printf( "Error reading from input!\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
//reprompt user for input by restarting loop
continue;
}
}
else
{
//remove newline character by overwriting it with
//null character
*p = '\0';
}
//input was ok, so break out of loop
break;
}
}
This program has the following behavior:
Menu:
Enter 1 to print hello,
enter 2 to print world,
enter 3 to print hello world,
or enter q to quit
Enter choice: sf<ssad
Error: Please only enter a single character!
Menu:
Enter 1 to print hello,
enter 2 to print world,
enter 3 to print hello world,
or enter q to quit
Enter choice: qsf<dsf
Error: Please only enter a single character!
Menu:
Enter 1 to print hello,
enter 2 to print world,
enter 3 to print hello world,
or enter q to quit
Enter choice: 1
hello
Menu:
Enter 1 to print hello,
enter 2 to print world,
enter 3 to print hello world,
or enter q to quit
Enter choice: 2
world
Menu:
Enter 1 to print hello,
enter 2 to print world,
enter 3 to print hello world,
or enter q to quit
Enter choice: 3
hello world
Menu:
Enter 1 to print hello,
enter 2 to print world,
enter 3 to print hello world,
or enter q to quit
Enter choice: q
Exiting...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论