C Primer Plus 第9章 第 9 题

给定下面的输出:
Please choose one of the following:

  1. copy files 2) move files
  2. remove files 4) quit
    Enter the number of your choice:
    a.编写一个函数,显示一份有4个选项的菜单,提示用户进行选择(输
    出如上所示)。
    b.编写一个函数,接受两个int类型的参数分别表示上限和下限。该函数
    从用户的输入中读取整数。如果整数超出规定上下限,函数再次打印菜单
    (使用a部分的函数)提示用户输入,然后获取一个新值。如果用户输入的
    整数在规定范围内,该函数则把该整数返回主调函数。如果用户输入一个非
    整数字符,该函数应返回4。
    c.使用本题a和b部分的函数编写一个最小型的程序。最小型的意思是,
    该程序不需要实现菜单中各选项的功能,只需显示这些选项并获取有效的响
    应即可;

以下是我的代码:

#include <stdio.h>

void aaa(void)
{

    printf("********************************************************\n"
           "!1) remove                    @2) move                  \n"
           "#3) copy                      $4) quit                  \n"
           "********************************************************\n"
           "enter your chois:");

}

int bbb(int u, int d)
{

    aaa();

    int t;

    if(scanf("%d", &t) == 1)
    {
    
        if(!(t > u || t < d))
        {
        
        return t;
        
        }

        bbb(4, 1);
    
    }

    return 4;

}

int main(void)
{

    int t;

    do
    {
    
        t = bbb(4, 1);

        printf("OK!\n");
    
    }
    while(t != 4);

    return 0;

}

Bug是当你输入3.1 时他又打印了一遍菜单, 应该立即退出

img


#include <stdio.h>
void aaa(void)
{
    printf("********************************************************\n"
        "!1) remove                    @2) move                  \n"
        "#3) copy                      $4) quit                  \n"
        "********************************************************\n"
        "enter your chois:");
}
int bbb(int u, int d)
{
    aaa();
    double t;
    scanf("%f", &t);
    if ((int)t == t)//整数
    {
        if (!(t > u || t < d))
        {
            return t;
        }
        bbb(4, 1);
    }
    return 4;

}
int main(void)
{
    int t;
    do
    {
        t = bbb(4, 1);
        printf("OK!\n");
    } while (t != 4);
    return 0;
}

其实我觉得,没必要bbb(4, 1),直接调用就行了,然后如果是小数就return。你可以把题目发我吗,我尽力帮你解决。如果对你有帮助,能先点个采纳吗,谢谢啦

采用chatgpt:
要解决输入浮点数时再次打印菜单的问题,可以进行一些修改。在函数bbb中,可以使用scanf读取用户输入的值并将其存储为浮点数类型,然后将其转换为整数进行比较。如果用户输入的是浮点数,则在判断范围时返回4,从而退出循环。以下是修改后的代码:

#include <stdio.h>

void aaa(void)
{
    printf("********************************************************\n"
           "!1) remove                    @2) move                  \n"
           "#3) copy                      $4) quit                  \n"
           "********************************************************\n"
           "enter your choice: ");
}

int bbb(int u, int d)
{
    aaa();

    float input;  // 存储用户输入的浮点数

    if (scanf("%f", &input) == 1)
    {
        int t = (int)input;  // 将浮点数转换为整数

        if (!(t > u || t < d))
        {
            return t;
        }

        bbb(4, 1);
    }

    return 4;
}

int main(void)
{
    int t;

    do
    {
        t = bbb(4, 1);
        printf("OK!\n");
    }
    while (t != 4);

    return 0;
}

这样修改后,当用户输入浮点数时,程序会将其转换为整数进行比较,并立即返回4,从而退出循环。

改动处见注释,供参考:

#include <stdio.h>
 
void aaa(void)
{
 
    printf("********************************************************\n"
           "!1) remove                    @2) move                  \n"
           "#3) copy                      $4) quit                  \n"
           "********************************************************\n"
           "enter your chois:");
 
}
 
int bbb(int u, int d)
{
 
    aaa();
 
    double t;         // 修改  int t;

    scanf("%lf", &t); // 修改

    if (t - (int)t)   // 输入的是浮点数  修改

        return 4;     // 返回4           修改

    if(!((int)t > u || (int)t < d))
    {

        return (int)t;

    }

    bbb(4, 1);
}
 
int main(void)
{
 
    int t;
 
    do
    {
    
        t = bbb(4, 1);
 
        printf("OK!\n");
    
    }
    while(t != 4);

    return 0;
 
}

因为输入3.1,函数bbb()第一次只获取了输入中的3,然后3后面的部分留在缓冲区,然后再次调用bbb()时,读取缓冲区的".3"来获取有一个整数,就失败了,scanf()返回0,bbb()返回4,程序就退出了。

可以在获取输入前,清空下缓冲区,然后把函数bbb()的流程稍微修改下即可。

修改如下:

参考链接:


#include <stdio.h>
 
void aaa(void)
{
 
    printf("********************************************************\n"
           "1) remove                    2) move                    \n"
           "3) copy                      4) quit                    \n"
           "********************************************************\n"
           "enter your chois:");
 
}
 
void remove(){
    printf("执行remove()!\n");
} 

 
void move(){
    printf("执行move()!\n");
} 
 
void copy(){
    printf("执行copy()!\n");
} 


int bbb(int u, int d)
{
 
    aaa();
        
    int t;
 

     fflush(stdin);  //  清空缓冲区,以免上次输入的数据影响本次输入 
      // https://baike.baidu.com/item/scanf/10773316
      if(scanf("%d", &t) == 1)  
    {
    
        if(!(t > u || t < d))
        {
        
               return t;
        
        }else{  // 如果输入的数字超出指定区间,则再次调用bbb()来获取输入序号 
            bbb(u,d);    
        }
 
      //  bbb(4, 1);
    

    }else{  // 如果输入的不是整数,则返回4 
        return 4;
    }
    
 
   
 
}
 
int main(void)
{
 
    int t;
 
    do
    {
    
        t = bbb(4, 1);
 
        //printf("OK!\n");
        // https://www.runoob.com/cprogramming/c-switch.html 
        // 简单 显示执行输入序号对应的操作 
        switch (t)
        {
            case 1: remove();break;
            case 2: move();break;
            case 3: copy();break;
            default :printf("OK!\n");break;         
        }
            
            
        
    
    }
    while(t != 4);
 
    return 0;
 
}


img

bbb函数判断条件改一下,if(scanf("%d", &t) != 0)改成这个

要解决你提到的问题,在读取用户输入时,你可以使用 scanf() 函数的返回值来判断是否成功读取一个整数。如果读取失败,你可以清除输入缓冲区中的无效字符,并返回一个特定的值(例如4),以指示非整数输入。

以下是修改后的代码:

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

void printMenu(void) {
    printf("********************************************************\n");
    printf("!1) remove                    @2) move                  \n");
    printf("#3) copy                      $4) quit                  \n");
    printf("********************************************************\n");
    printf("Enter the number of your choice: ");
}

int getUserChoice(int upperLimit, int lowerLimit) {
    printMenu();

    int choice;
    while (scanf("%d", &choice) != 1 || choice < lowerLimit || choice > upperLimit) {
        printf("Invalid input. Please try again.\n");
        while (getchar() != '\n');  // 清除输入缓冲区中的无效字符
        printMenu();
    }

    return choice;
}

int main(void) {
    int choice;

    do {
        choice = getUserChoice(4, 1);
        printf("OK!\n");
    } while (choice != 4);

    return 0;
}

现在,当用户输入一个非整数时,程序会显示错误消息并要求重新输入,而不会再次打印菜单。

希望这可以帮助到你!如果有任何进一步的问题,请随时问。

http://t.csdn.cn/j0Ztn,参考这个

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 帮你找了个相似的问题, 你可以看下: https://ask.csdn.net/questions/7753779
  • 除此之外, 这篇博客: C Primer Plus 第四章 复习题&编程练习 答案中的 8. 编写一个程序,提示用户输入旅行的里程和消耗的汽油量。然后计算并显示消耗每加仑汽油行驶的英里数,显示小数点后面一位数字。接下来,使用1加仑大约3.785升,1英里大约为1.609千米,把单位是英里/加仑的值转换为升/100公里(欧洲通用的燃料消耗表示法),并显示结果,显示小数点后面 1 位数字。注意,美国采用的方案测量消耗单位燃料的行程(值越大越好),而欧洲则采用单位距离消耗的燃料测量方案(值越低越好)。使用#define 创建符号常量或使用 const 限定符创建变量来表示两个转换系数。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
    #include <stdio.h>
    #define distance_CONVERT  1.609
    #define Gasoline_CONVERT  3.785
    int main(void)
    {
    	float distance, Gasoline_quantity; 
    	printf("请输入旅行的里程(英里)和消耗的汽油量(加仑):");
    	scanf("%f %f",&distance,&Gasoline_quantity);
    	printf("显示消耗每加仑汽油行驶的英里数:%.1f\n",distance/Gasoline_quantity);
    	printf("把单位是英里/加仑的值转换为升/100公里:%.1f\n",(Gasoline_quantity*Gasoline_CONVERT)/(distance*distance_CONVERT)*100);
    	
    	return 0;
    }
    

    运行结果:
    在这里插入图片描述
    在单位转换软件上,验证了一下运行结果:
    在这里插入图片描述

  • 以下回答来自chatgpt:

    需要在 get_integer(int lower_limit, int upper_limit) 函数中进行优化,特别是在发现非整数字符的情况下立即退出。可以使用 fgets 函数接收用户输入的字符串,然后使用 sscanf 函数尝试将其转换为整数。如果转换成功,再进行上下限的判断,否则立即退出并返回4。

    以下是优化后的代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    void display_menu() {
        printf("Menu:\n");
        printf("1. Option 1\n");
        printf("2. Option 2\n");
        printf("3. Option 3\n");
        printf("4. Option 4\n");
    }
    
    int get_integer(int lower_limit, int upper_limit) {
        char input[100];
        int num;
    
        while (1) {
            printf("Enter an integer between %d and %d: ", lower_limit, upper_limit);
    
            if (fgets(input, sizeof(input), stdin) == NULL) {
                exit(1);
            }
    
            if (sscanf(input, "%d", &num) != 1) {
                return 4;
            }
    
            if (num < lower_limit || num > upper_limit) {
                display_menu();
            } else {
                return num;
            }
        }
    }
    
    int main() {
        display_menu();
        int response = get_integer(1, 4);
        printf("You entered %d\n", response);
        return 0;
    }
    

    在优化后的代码中,使用了 fgets 函数来接收用户输入的字符串,并且限制了输入字符串的长度为 100。然后使用 sscanf 函数尝试将输入字符串转换为整数。如果转换成功,再进行上下限的判断。如果转换失败或者超出上下限,则立即返回4。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

删除第31行bbb(4,1)就可以解决