今年我作为学位的一部分被介绍给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;
}
答案 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
在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;
}
这样,代码不会因错误处理而混乱(很多),并且根据函数执行的程度非常好地完成清理。