什么可能导致程序忽略用户的输入

时间:2017-01-28 01:05:20

标签: c

无论我选择什么选项,我总是会提示输入一个新的移位值(好像我输入1作为我的选择)。为什么这段代码会忽略我选择的选项?

#include <stdio.h>
#include <string.h>
#define SIZE 500
int getUserChoice()
{
    int decision = 0;

    printf("-------------------------------\n");
    printf("| 1) Change Shift (default 3) |\n");
    printf("| 2) Encrypt a message        |\n");
    printf("| 3) Decrypt a message        |\n");
    printf("| 4) Quit                     |\n");
    printf("-------------------------------\n");
    printf("Option: ");
    scanf("%d", &decision);
    if(decision == 0 || decision >= 4)
    {
        return 0;
    }

    return decision;
}
int getShift()
{
    int key = 3;
    printf("Enter new shift value: ");
    scanf("%d", &key);
   return 0;
}
void getString(char buf[])
{
    int act;
    act = SIZE - 1;
    int count[26] = {0};
    fgets(buf, act, stdin);
    return;
}
void encrypt(char buf[], int shift)
{
    int i = 0;
    for(i = 0; i < strlen(buf);++i)
    {
        buf[i] = buf[i] + shift;
    }
    return;
}
void decrypt(char buf[], int shift)
{
    int i = 0;
    for(i = 0; i < strlen(buf); ++i)
    {
        buf[i] = buf[i] - shift;
    }
    return;
}
int main()
{
    char userStr[SIZE];
    int number = 0;
    getUserChoice();
    int shift = 0;
    if(number = 1)
    {
        getShift();

    }
    if (number = 2)
   {
        getString(userStr);
        encrypt(userStr, shift);
    }
    if (number = 3)
    {
        getString(userStr);
        decrypt(userStr, shift);
    }


    return 0;

}

2 个答案:

答案 0 :(得分:1)

这看起来很像家庭作业,你似乎没有花很多精力去寻找问题,但是我们走了......代码上有几个缺陷:

1)忽略返回值:

您的某些函数getUserChoicegetShift应该返回一个值,但这些值在代码中完全被忽略。您没有将它分配给任何局部变量,并且它们不会修改其范围之外的任何内容,因此返回的任何值都会丢失。

代码:

if(number = 1){
    getShift();
}

应该是:

if(number == 1){
    shift = getShift();
}

这让我有了另一个大错误,当C无意中发生时,很多人头疼的原因是:

2)错误地写作赋值运算符&#39; =&#39;比较运算符&#39; ==&#39;是必需的:

赋值运算符返回一个值:赋值后的左操作数值。因此表达式if(number = 1)是有效的,并且每次都会计算为true,因为赋值的返回值始终为1. if(number == 1)但是,只有当number等于时才会求值为true 1.我觉得进行比较&#34; Yoda-Style&#34;,像if(1 == number)这样可以避免那些错误(很容易发生在错字上)。它们很难跟踪,因为代码是有效的,但行为不是预期的。使用&#34; Yoda-Style&#34;比较,如果您输入错误if(1 = number),则会出现编译错误,因为这是一项无效的分配。

3)未正确过滤用户输入:

在函数getUserChoice上,您有以下条件语句来检查输入是否有效(当无效时,它默认为&#34;退出&#34;选项):

if(decision == 0 || decision >= 4)
{
    return 0;
}

但是,由于决策是signed int,因此负值有效。你没有考虑到这些。以下内容涉及:

if(decision <= 0 || decision >= 4)
{
    return 0;
}

4)getShift不返回班次值:

您在scanf函数上使用getShift来获取移位值,但返回0.您应该返回key值。

5)getString上的未使用变量+ fgets上错误的大小参数:

你在getString上声明了一个0到0的数组,它没有任何用处。另外,来自fgets手册页:

  

fgets()从流和中读取最多一个小于字符的字符          将它们存储到s指向的缓冲区中。读后停止了          EOF或换行符。如果读取换行符,则将其存储到缓冲区中。          终止空字节(&#39; \ 0&#39;)存储在最后一个字符之后          缓冲区。

所以你真的不需要从SIZE中减去1,因为它已经考虑了空字符。

6)在调用stdin之前不清除fgets

致电scanf("%d",...);后,您的stdin中会有一个挂起的换行符。这是因为解析为scanf的格式字符串只指示它读取任意数量的十进制数字,不包括跟随它们的换行符。

挂起的换行符会导致您的fgets在获得任何用户输入之前退出。您需要通过阅读之前stdin来电中的悬挂字符来清除scanf。在这个例子中,这是由这个循环完成的:

int c;
while((c = getchar()) != '\n' && c != EOF){
    //Clearing Stdin
}

另一种方法是使用:

scanf("%*[^\n]"); scanf("%*c"); //Consume all characters up to \n (if present) then consume exactly one char ('\n' itself)

7)不使用main中的循环重复提示用户:

您只需提示用户一次,执行询问并退出,而不是在他要求退出之前反复询问用户选项。

8)return返回函数结束时不必要的void语句:

void返回函数将在它们结束时返回,因此除非您在函数体结束之前返回,否则无需添加return语句。

编辑以下代码以解决上述问题:

#include <stdio.h>
#include <string.h>
#define SIZE 500
int getUserChoice()
{
    int decision = 0;

    printf("-------------------------------\n");
    printf("| 1) Change Shift (default 3) |\n");
    printf("| 2) Encrypt a message        |\n");
    printf("| 3) Decrypt a message        |\n");
    printf("| 4) Quit                     |\n");
    printf("-------------------------------\n");
    printf("Option: ");
    scanf("%d", &decision);
    int c;
    while((c = getchar()) != '\n' && c != EOF){
        //Clearing Stdin
    }
    if(decision <= 0 || decision >= 4)
    {
        return 0;
    }

    return decision;
}

int getShift()
{
    int key = 3;
    printf("Enter new shift value: ");
    scanf("%d", &key);
    int c;
    while((c = getchar()) != '\n' && c != EOF){
        //Clearing Stdin
    }
    return key;
}
void getString(char *buf)
{
    fgets(buf, SIZE, stdin);
    return;
}
void encrypt(char *buf, int shift)
{
    int i = 0;
    for(i = 0; i <= (strlen(buf)-1);++i)
    {
        buf[i] = buf[i] + shift;
    }
    return;
}
void decrypt(char *buf, int shift)
{
    int i = 0;
    for(i = 0; i <= (strlen(buf)-1); ++i)
    {
        buf[i] = buf[i] - shift;
    }
    return;
}
int main()
{
    char userStr[SIZE];
    int shift = 3;

    while(1){
        int number = getUserChoice();
        if(number == 1)
        {
            shift = getShift();

        }
        if (number == 2)
        {
            getString(userStr);
            printf("Message: %s\n", userStr);
            encrypt(userStr, shift);
            printf("Shifted Message: %s\n", userStr);
        }
        if (number == 3)
        {
            getString(userStr);
            printf("Shifted Message: %s\n", userStr);
            decrypt(userStr, shift);
            printf("Message: %s\n", userStr);
        }
        if (number == 0){
            break;
        }
    }
    return 0;
}

答案 1 :(得分:0)

代码中的两件事导致它忽略用户输入。

首先,getUserChoice函数返回一个值,但main不存储或使用返回值。函数调用应如下所示:

number = getUserChoice();

其次,单个等号if(number = 1)充当任务。它将number设置为值1。要将number1进行比较,请使用相等运算符,例如

if ( number == 1 )

请注意,当您错误地将赋值放在if语句中时,任何体面的编译器都会生成警告。您应确保启用所有警告(使用带有gcc或clang的-Wall,使用带有Microsoft的/W4),并修复所有警告。如果忽略编译器警告,那么你将无处可去。

您的代码中还有其他问题,但这些问题导致用户输入被忽略。