重启程序的问题

时间:2014-01-25 18:52:17

标签: c

今年我作为学位的一部分被介绍给C,在此期间,我必须编写简单的程序,并通过反复运行它们,将无意义的变量放入等等来测试它们以防止白痴。我有一个想法,编写一个程序,能够重新启动自己,而无需再次运行程序。

我已经尝试编写一个程序来执行这个功能(事实证明这比我想象的要难)而且我现在已经有了它,虽然使用了一个不受欢迎的goto函数。现在我唯一的问题是检查无意义输入的while循环,这似乎决定至少运行一次忽略有效输入的提示。

有人可以告诉我为什么会这样吗? (我的编译器是Dev-C ++ 4.9.9.2)

int main (void)
{
  mainprogram:
            printf("\nPROGRAM START\n");

    //code copied from an exam, to check that the program performs a function
    //when ran through again

    int i,j,k;

    printf("Please enter 7:");
    scanf("%d",&i);

    printf("Please enter 4:");
    scanf("%d",&j);

    printf("Please enter 0:");
    scanf("%d",&k);
    //this is to check that the program will take input when it is restarted
    do {
        switch (i%j) {
            case 3:
                i--;
                k*=i;
                break;
            case 2:
                i--;
                k+=i;
            default:
                i--;
                k++;
                break;
        }
        printf("i is %d k is %d\n",i,k);
    } while (i>0);
    //end of copied code

    char prompt='y';
    printf("\nRestart program?");
    scanf("%c",&prompt);

    while (prompt != 'y' && prompt != 'Y' && prompt != 'n' && prompt != 'N')
    {

    //this is the problem section, when entering nonsense input, the error messages
    //display twice before pausing for input, and when restarted, the program does 
    //run again but displays the error messages once before pausing for input

       printf("\nERROR: INVALID INPUT");
       printf("\n\nRestart program?");
       prompt='y';
       scanf("%c",&prompt);
    }


    if (prompt == 'y' || prompt == 'Y') 
    {
          goto mainprogram;
          }

    //
    return 0;
}

3 个答案:

答案 0 :(得分:0)

我刚刚重新格式化了你的代码,而且@ herohuyongtao确实是正确的,break;的{​​{1}}已移到case 2的末尾,这在那里没用。

但是你的代码中有一些令人震惊的东西,就是你使用default。请记住这条规则:无论你使用GOTO,还有更好的方法!

goto

现在代码很干净,对于完全问题,您将遇到回车问题。基本上,你所做的就是在#include <stdio.h> short int read_input (void) { printf("\nPROGRAM START\n"); //code copied from an exam, to check that the program performs a function //when ran through again int i,j,k; printf("Please enter 7:"); scanf("%d",&i); printf("Please enter 4:"); scanf("%d",&j); printf("Please enter 0:"); scanf("%d",&k); //this is to check that the program will take input when it is restarted do { switch (i%j) { case 3: i--; k*=i; break; case 2: i--; k+=i; break; // break at the right spot default: i--; k++; } printf("i is %d k is %d\n",i,k); } while (i>0); // getchar(); // could be inserted here (discards one char) // fflush(stdin); // could also do the job (discards all remaining chars in buffer) char prompt='y'; // here the design choice is to let the user input whatever // and not updated the output until the right character is given // which will hide how many wrong chars has been previously in the buffer. printf("\nRestart program? "); do { prompt = getchar(); } while (prompt != 'y' && prompt != 'Y' && prompt != 'n' && prompt != 'N'); if (prompt == 'y' || prompt == 'Y') return 1; return 0; } int main() { while (read_input() == 1); return 0; } 被击中之前获得输入,但当你点击回车时,你实际上发送了\n + CR。所以在输入缓冲区中永远不会读取一个字符,需要丢弃。

所以你应该首先阅读那些总结你问题的SO question,你可以:

  • LF评论
  • 之后添加一个getchar();
  • //end of copied code可以完成这项工作(参见SO Question以了解更多信息),但设计的目的是刷新输出缓冲区,而不是输入缓冲区,
  • 添加fflush(stdin)有点脏(且不便携)但有效,
  • 或更改您的条件以及您对fseek(stdin,0,SEEK_END);的使用,以考虑您实际上在缓冲区中有更多字符。

在我给你的代码中,我选择了最简单的解决方案,即在不打印任何内容的情况下丢弃任何错误的输入。

答案 1 :(得分:0)

while(1){    //parent

 printf("\n\nRun program?");
 scanf("%c",&prompt);

if (prompt == 'n' || prompt == `N`)
{
  printf("\nEXITINT")
  return 0;
}



int i,j,k;

printf("Please enter 7:");
scanf("%d",&i);

printf("Please enter 4:");
scanf("%d",&j);

printf("Please enter 0:");
scanf("%d",&k);

switch (i%j)
{
case 3:
i--;
k*=i;
break;
case 2:
i--;
k+=i;
break;
default:
i--;
k++;
break;
}
printf("i is %d k is %d\n",i,k);
} //end while parent 

//复制代码的结尾

答案 2 :(得分:0)

有几种方法可以重新启动程序,或者更一般地说是循环一些代码。当然,所有这些都可以使用goto来完成,但这会使代码难以理解,因此C具有处理最常见模式的等效结构:

只要条件成立,

执行代码
while (condition)
{
    /* code */
}

这意味着在执行代码之前,检查条件。如果条件成立(其值为非零),则执行代码然后循环回到顶部。这相当于:

top_of_while:
    if (!condition)
        goto done;

    /* code */
    goto top_of_while:
done:

执行代码并在条件成立时重做

do
{
    /* code */
} while (condition)

这意味着首先执行代码然后检查条件。如果条件成立,则再次执行代码。这相当于:

top_of_do_while:
    /* code */
    if (condition)
        goto top_of_do_while;

迭代

for (initialization; condition; iteration)
{
    /* code */
}

这是一种发生很多的while循环,其中有一个初始化,后跟一个while循环,它在底部更改变量以形成某种迭代。这相当于:

initialization;
while (condition)
{
    /* code */
    iteration;
}

要重新启动程序,很可能你想要do - while循环,因为你肯定知道程序必须执行一次。但是,通过正确初始化while循环的条件变量,您还可以确保始终首次输入循环。这是一个风格和你喜欢的问题。


在哪里实际使用goto

许多人会告诉你永远不要使用goto。这源于过度使用goto导致了大量过于复杂的程序,即所谓的意大利面条代码。原因是很难建立一个程序的心理模型,执行可以跳转到任何其他部分。

然而,goto在C中实际上非常有用,没有它,错误处理会成为......颈部的巨大痛苦。 goto的这种有用用法是用于处理错误和清理,它们始终位于函数的底部。一个例子是:

int *read_nums(int n)
{
    int *array, i;

    array = malloc(n * sizeof *array);
    if (array == NULL)
        goto exit_no_mem;

    for (i = 0; i < n; ++i)
        if (scanf("%d", &array[i]) != 1)
            goto exit_bad_input;

    return array;

exit_bad_input:
    free(array);
exit_no_mem:
    return NULL;
}

这样,代码不会因错误处理而混乱(很多),并且根据函数执行的程度非常好地完成清理。