结合使用fgets/scanf和switch来读取一个字符。

huangapple go评论57阅读模式
英文:

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 &lt;stdio.h&gt;
int main(void) {
char cmd;

do {
    printf(&quot;Enter 1 to print hello, enter 2 to print world, enter 3 to print hello world and enter q to quit\n&quot;);
    printf(&quot;Enter: &quot;);
    scanf(&quot; %c&quot;, &amp;cmd);

    switch(cmd) {
       case &#39;1&#39; : printf(&quot;hello\n&quot;); break;
       case &#39;2&#39; : printf(&quot;world\n&quot;); break;
       case &#39;3&#39; : printf(&quot;hello world\n&quot;); break;
       case &#39;q&#39; : printf(&quot;Exiting...\n&quot;); break;
       default : printf(&quot;Invalid input!\n&quot;); break; 
    }
} while(cmd!=&#39;q&#39;);

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(&quot;Enter 1 to print hello, enter 2 to print world, enter 3 to print hello world and enter q to quit\n&quot;);
    printf(&quot;Enter: &quot;);
    char *res = fgets(line, sizeof line, stdin);
    if (!res) {
        break;
    }

    cmd = line[0];
    switch(cmd) {
       case &#39;1&#39; : printf(&quot;hello\n&quot;); break;
       case &#39;2&#39; : printf(&quot;world\n&quot;); break;
       case &#39;3&#39; : printf(&quot;hello world\n&quot;); break;
       case &#39;q&#39; : printf(&quot;Exiting...\n&quot;); break;
       default : printf(&quot;Invalid input!\n&quot;); break; 
    }

} while (cmd != &#39;q&#39;);

答案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&lt;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&lt;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 &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;stdbool.h&gt;
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(
&quot;Menu:\n&quot;
&quot;Enter 1 to print hello,\n&quot;
&quot;enter 2 to print world,\n&quot;
&quot;enter 3 to print hello world,\n&quot;
&quot;or enter q to quit\n&quot;
);
//get one line of input from the user
get_line_from_user( &quot;Enter choice: &quot;, line, sizeof line );
//verify that user entered exactly one character
if ( line[0] == &#39;\0&#39; || line[1] != &#39;\0&#39; )
{
printf( &quot;Error: Please only enter a single character!\n\n&quot; );
continue;
}
switch( line[0] )
{
case &#39;1&#39;:
printf( &quot;hello\n&quot; );
break;
case &#39;2&#39;:
printf( &quot;world\n&quot; );
break;
case &#39;3&#39;:
printf( &quot;hello world\n&quot; );
break;
case &#39;q&#39;:
printf( &quot;Exiting...\n&quot; );
quit = true;
break;
default:
printf(&quot;Invalid input!\n&quot;);
}
//add spacing
printf( &quot;\n&quot; );
}
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 &quot;exit&quot; 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( &quot;Error reading from input!\n&quot; );
exit( EXIT_FAILURE );
}
//attempt to find newline character
p = strchr( buffer, &#39;\n&#39; );
//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()) != &#39;\n&#39; &amp;&amp; !feof(stdin) )
{
if ( c == EOF )
{
printf( &quot;Error reading from input!\n&quot; );
exit( EXIT_FAILURE );
}
printf( &quot;Input was too long to fit in buffer!\n&quot; );
//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( &quot;Error reading from input!\n&quot; );
exit( EXIT_FAILURE );
}
} while ( c != &#39;\n&#39; );
//reprompt user for input by restarting loop
continue;
}
}
else
{
//remove newline character by overwriting it with
//null character
*p = &#39;\0&#39;;
}
//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&lt;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&lt;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...

huangapple
  • 本文由 发表于 2023年6月15日 04:25:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76477293.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定