C中的输入validation

我正在用C编写程序。在程序中,用户必须选择一个数字,1,2或3.我想构造代码,以便当用户输入的数字不是1时, 2或3,他/她将被告知“无效选择 – 再次选择”然后他们将被带回到程序的开头:

int main() { int choice; char response, Y, N; printf("Choose a shape from the following:\n 1.Sphere\n 2.Cone\n 3.Cylinder\n"); scanf("%d",&choice); if(choice==1||choice==2||choice==3) { printf("Enter the radius, r\n"); } else printf("Invalid selection, choose again.\n"); } 

我想要的是,在“无效选择,再次选择”出现后,用户返回到程序的开头,这样他们就可以再次输入他们的选择。 我该怎么办?

这是你做的:

 int choice; char response, Y, N; for (;;) { printf("Choose a shape from the following:\n 1.Sphere\n 2.Cone\n 3.Cylinder\n"); scanf("%d",&choice); if(choice==1||choice==2||choice==3) { break; } printf("Invalid selection, choose again.\n"); } 

一旦这个循环结束,提示半径。 您几乎肯定需要另一个循环来防止输入半径的负值,所以不要在同一个循环中提示它。

为此使用while循环

 int main() { int choice; char response, Y, N; printf("Choose a shape from the following:\n 1.Sphere\n 2.Cone\n 3.Cylinder\n"); while(1) { scanf("%d",&choice); if(choice==1||choice==2||choice==3) { printf("Enter the radius, r\n"); //Maybe read the radius here scanf("%d",&radius); break; } else printf("Invalid selection, choose again.\n"); } } 

使用do-while循环,循环直到正确输入
这样做,为退出添加选项4:

  do { scanf("%d",&choice); int flag=0; if(choice==1||choice==2||choice==3) { printf("Enter the radius, r\n"); } else { printf("Invalid selection, choose again.\n"); flag=1; } } while(flag==1&& choice!=4); 

有些人会反对这一点,但我认为在这些情况下,一个简单的老goto是一种非常干净和可读的做事方式,因为它强调了“正常”控制路径的线性:

 int main(int arg, char *argv[]) { int choice; choose_shape: printf("Choose a shape from the following:\n" " 1.Sphere\n 2.Cone\n 3.Cylinder\n"); scanf("%d", &choice); if (choice < 1 || choice > 3) { printf("Invalid selection, please choose again.\n"); goto choose_shape; } printf("Enter the radius, r:\n"); ... } 

是的,人们抱怨goto所以让我再说一遍。

这是一个更复杂的版本,允许您通过字母选择形状:

  char c; shape_t shape; choose_shape: printf("Choose a shape: [s]phere, [c]one, c[y]linder:\n"); scanf("%c", &c); switch (c) { cases 's': shape = SHAPE_SPHERE; break; case 'c': shape = SHAPE_CONE; break; case 'y': shape = SHAPE_CYLINDER; break; default: printf("Not a valid shape: %c\n", c); goto choose_shape; } 

这是带goto的版本。 请注意,这引入了另一个变量flag ,其唯一目的是去除goto语句。 由于switch语句,你不能简单地在这里使用break (这是一个未标记的goto开头)。 由于附加状态,我认为这更难阅读。 这是五行更长。

  char c; shape_t shape; int flag; for (flag = 0; !flag; ) { printf("Choose a shape: [s]phere, [c]one, c[y]linder:\n"); scanf("%c", &c); switch (c) { cases 's': shape = SHAPE_SPHERE; flag = 1; break; case 'c': shape = SHAPE_CONE; flag = 1; break; case 'y': shape = SHAPE_CYLINDER; flag = 1; break; default: printf("Not a valid shape: %c\n", c); break; } } 

这是您可以考虑的替代方案。 请注意,获取用户输入被分成一个函数, main()只调用该函数并在出错时循环。 main()读者可能并不关心你如何获得输入选择,那么为什么要让它们读取呢?

还要注意我使用的是fgets ,而不是scanf 。 如果使用scanf运行版本并输入非数字,则该字符将无限期地保留在输入缓冲区中; scanf永远不会删除它,因为它正在寻找满足%d格式字符串的数字 – 因此是一个无限循环。 您可以尝试在scanf之前刷新stdin (使用fpurge ),但该函数仍然无法正确处理stdin的关闭(例如,在基于UNIX的UNIX系统上使用ctrl-d)。

 #include  #include  static int get_shape(int *shape) { char buf[10] = ""; printf("Choose a shape from the following:\n" " 1.Sphere\n 2.Cone\n 3.Cylinder\n"); if (!fgets(buf, sizeof buf, stdin)) { /* Note: fgets, not scanf */ exit(1); /* ctrl-d */ } *shape = strtol(buf, NULL, 0); if (*shape==1 || *shape==2 || *shape==3) { return 1; } printf("Invalid selection\n"); return 0; } int main(int argc, char ** argv) { int shape = 0; while (!get_shape(&shape)) { /* loop */ } printf("Choice: %d\n", shape); return 0; }