如何在while循环中转换此goto循环?

时间:2017-11-03 09:37:46

标签: c while-loop goto

我有一个程序,提示用户输入三个浮点数,如果这些数字不是正数或不是数字,则打印出"Invalid number"这是用goto循环完成的程序的一部分我想摆脱它。

float array[n][3];
int i;
for(i = 0;i<n;i++){
    one:
    printf( "Please enter first number: ");
    scanf("%f", &array[i][0]);
    while(array[i][0]<0){
        printf("Invalid number: ");
        goto one;
    }
    two:
    printf("Please enter second number: ");
    scanf("%f", &array[i][1]);
    while(array[i][1]<0){
        printf("Invalid number: ");
        goto two;
    }
    three:
    printf("Please enter third number: ");
    scanf("%f", &array[i][2]);
    while(array[i][1]<0){
        printf("Invalid number: ");
        goto three;
     }
}

如何转换循环goto onegoto twogoto three;在一个while循环,或某种循环?

4 个答案:

答案 0 :(得分:1)

查看我的更改。我不仅修改了goto案例:

double array[n][3];
int i, j;
char * fst[] = { "first", "second", "third" };

for( i = 0; i < n; i++ )
{
    for ( j = 0; j < 3; j++ )
    {
        while ( 1 )
        {
            printf( "Please enter %s number: ", fst[j] );
            scanf( "%lf", &array[i][j] );
            if ( array[i][j] < 0 )
                printf("Invalid number.\n");
            else break;
        }
    }
}

类似的块与循环和单词数组相结合。 double优于float,除非RAM很低(嵌入式系统)。 goto已转换为while循环和break。我想你对负数说“无效数字”,而不是scanf失败。如果检查失败scanf,则可将其修改为if ( scanf( "%lf", &array[i][j] ) < 1 ) ...

答案 1 :(得分:1)

您可以将其转换为do { ... } while(...);

示例:

one:
printf( "Please enter first number: ");
scanf("%f", &array[i][0]);
while(array[i][0]<0){
    printf("Invalid number: ");
    goto one;
}

do
{
    printf ("Please enter first number: ");
    scanf ("%f", &array[i][0]);
    if (array[i][0] < 0)
    {
        printf ("Invalid number: ");
    }
}
while (array[i][0] < 0);

答案 2 :(得分:0)

你可以这样做

for(i = 0;i<n;i++){
    while(printf( "Please enter first number: ")>0 && scanf("%f", &array[i][0])==1 && array[i][0]<0 && printf("Invalid number: ") );
    while(printf( "Please enter second number: ")>0  && scanf("%f", &array[i][1])==1 && array[i][1]<0 && printf("Invalid number: "));
    while(printf( "Please enter third number: ")>0  && scanf("%f", &array[i][2])==1 && array[i][2]<0 && printf("Invalid number: ") );
}

Short circuit evaluation在这里受益。

printf()将返回打印的字符数,如果成功则返回大于零。

如果printf()成功,则执行scanf(),返回成功分配的数量。在这种情况下,如果成功则应为1

如果printf()scanf()都成功且array[i][j]小于零,则显示错误消息printf()并重复循环。

您可以将这些while循环设为

while(printf( "Please enter third number: ")>0  && scanf("%f", &array[i][2])==1 && array[i][2]<0)
{
    printf("Invalid number: ")
}

使其更具可读性。

编辑: 如果输入不是有效数字,scanf()将不会读入变量,因为格式说明符为%f

这可能会导致问题,因为无效输入将在输入缓冲区中保持未使用状态。您需要清除输入缓冲区。

这样的东西
int ch;
while( (ch=getch())!=EOF && ch!='\n' );

可能用于从输入缓冲区消耗直到换行符。有关详情,请参阅here

错误时,

getchar()会返回EOF。请注意,getchar()返回转换为int 的无符号字符。

要包含此功能,您可以将这些while循环修改为

int ch;
while(printf( "Please enter third number: ")>0  && scanf("%f", &array[i][2])==1 && array[i][2]<0)
{
    printf("Invalid number: ")
    while( (ch=getch())!=EOF && ch!='\n' );
}

答案 3 :(得分:0)

避免goto通常是一个好主意(尽管存在一些可接受的用途)。其他要避免的事情:

  • 代码重复。 (危险)
  • 在值有效之前将值存储到最终数据容器中。 (危险)
  • 迭代2D数组的最左侧维度而不是最右侧的维度。 (低效)

解决上述所有问题的一种可能解决方案:

#include <stdio.h>

float enter_float (size_t n)
{
  const char* STR_NUMBER[] = { "first", "second", "third" };
  float result;

  printf("Please enter %s number: ", STR_NUMBER[n]);
  scanf("%f", &result);

  return result;
}


int main (void)
{
  size_t n=3;
  float array[n];

  for(size_t i=0; i<n; i++)
  {
    float input;
    while( (input = enter_float(i)) < 0.0f)
    {
      printf("Invalid number\n");
    }
    array[i] = input;
  }
}

(理想情况下,代码还应检查scanf的结果,并通过指定scanf应读取的项目数来确保没有缓冲区溢出。)