【问题标题】:Do-while loop - what's wrong with the terminating condition?Do-while 循环 - 终止条件有什么问题?
【发布时间】:2016-09-29 21:30:38
【问题描述】:

所以我最近开始学习 Steven Kochan 的“Programming in C”一书,目前正在学习第 8 章 - “函数”。 我对练习 8.16 有疑问: “修改程序 8.14 使用户可以转换任意数量的整数。使 规定程序在输入零作为值时终止 要转换的数字。”

程序 8.14 的代码如下:

#include <stdio.h>
#include <stdlib.h>

int convertedNumber[64];
long int numberToConvert;
int base;
int digit = 0;

void getNumberAndBase(void)
{
  printf("Number to be converted? ");
  scanf("%li", &numberToConvert);

  printf("Base? ");
  scanf("%i", &base);

  if ( base < 2 || base > 16)
  {
    printf("Bad base - must be between 2 and 16\n");
    base = 10;
  }
}

void convertNumber(void)
{
  do
  {
    convertedNumber[digit] = numberToConvert % base;
    digit++;
    numberToConvert /= base;
  }
  while ( numberToConvert != 0);
}

void displayConvertedNumber (void)
{
  const char baseDigits[16] =
    { '0', '1', '2', '3', '4', '5', '6', '7',
        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

  int nextDigit;

  printf ("Converted number =");

  for (--digit; digit >= 0; digit--)
  {
    nextDigit = convertedNumber[digit];
    printf("%c", baseDigits[nextDigit]);
  }
  printf("\n");
}

int main (void)
{
  void getNumberAndBase (void), convertNumber(void),
  displayConvertedNumber (void);

  getNumberAndBase();
  convertNumber ();
  displayConvertedNumber ();

  return 0;
}

我最初的想法是在主函数中围绕三个函数使用 do-while 循环,如下所示:

do
{
getNumberAndBase();
convertNumber ();
displayConvertedNumber ();
}
while ( numberToConvert != 0);

但显然它不起作用。这是本章的最后一个练习,我设法完成了其余的练习,但我无法弄清楚这里出了什么问题。 可能我只是错过了一些明显的东西。

【问题讨论】:

  • 定义“显然它不起作用”。怎么了?您是否收到错误、崩溃、错误结果……?
  • 函数的章节没教你使用参数和返回值?郁闷。

标签: c function loops do-while


【解决方案1】:

当您的do-while 条件被测试时,它始终为零。方法convertNumber() 有它自己的do-while,它一直持续到numberToConvert 为零。

do
{
    getNumberAndBase();
    convertNumber (); // Sets numberToConvert to zero before returning
    displayConvertedNumber ();
}
while ( numberToConvert != 0);

void convertNumber(void)
{
  do {
   ...
  } while ( numberToConvert != 0);
}

部分问题是成员变量被用于传递方法的返回值。这些方法的副作用并不明显。

考虑改为从方法中返回值。

long int numberToConvert = 0;
do
{
    numberToConvert = getNumberAndBase();
    long int convertedNumber = convertNumber( numberToConvert ); 
    displayConvertedNumber ( convertedNumber );
}
while ( numberToConvert != 0);

现在局部变量 numberToConvert 不受 convertNumber() 方法的影响,您可以从局部上下文中确定循环行为。

【讨论】:

  • 假设“convertNumber 的后置条件是numberToConvert 为零”。
  • @EugeneSh。 ——也是真的。更大的问题是不必要地使用成员变量来传达函数结果。
【解决方案2】:

numberToConvert 已被convertNumber() 使用,因此请不要打扰。

放整块

getNumberAndBase();
convertNumber (); // Sets numberToConvert to zero before returning
displayConvertedNumber ();

while(1) 循环中检查getNumberAndBase() 函数中的numberToConvert 值。一旦你得到 0 值就跳出循环。

当然,您可以使用另一个do...while 循环,但不知何故您需要使用numberToConvert 扫描值来满足条件

"...为程序在输入零作为要转换的数字的值时终止。"

也就是说,

  • 始终检查scanf() 的返回值以确保成功。
  • 不要简单地使用全局变量,一旦程序开始变大,它们会带来隐患。定义局部变量并尽可能长时间地传递它们(或指向它们的指针)。

我们只需要更高级别的封装。 :)

【讨论】:

    【解决方案3】:

    这个练习很困难,因为它需要使用全局变量——这不利于正确使用函数。

    无论如何,这是我的解决方案。请注意,每次转换数字时,gDigit 必须设置为 0。

    /* Exercise 7.16
       Modify Program 7.15 so that the user can convert any number of integers.
       Make provision for the program to terminate when a zero is typed in as
       the value of the number to be converted.
    
       notes: includes the modified version of Program 7.15 from Exercise 7.15
    
       the statement gDigit = 0 has been moved from the start of the program to
       the start of the convertNumber() function -- gDigit must be set to 0 each
       time a number is to be converted
    */
    
    #include <stdio.h>
    
    int gConvertedNumber[64];
    long int gNumberToConvert;
    int gBase;
    int gDigit;
    
    void getNumber (void)
    {
        printf ("\nNumber to be converted (0 to exit)? ");
        scanf ("%li", &gNumberToConvert);
    }
    
    void getBase (void)
    {    
        do {
            printf ("Base (between 2 and 16)? ");
            scanf ("%i", &gBase);
        }
        while ( gBase < 2 || gBase > 16 );
    }
    
    void convertNumber (void)
    {
        gDigit = 0;
    
        do {
            gConvertedNumber[gDigit] = gNumberToConvert % gBase;
            ++gDigit;
            gNumberToConvert /= gBase;
        }
        while ( gNumberToConvert != 0 );
    }
    
    void displayConvertedNumber (void)
    {
        const char baseDigits[16] =
            { '0', '1', '2', '3', '4', '5', '6', '7',
              '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
    
        printf ("Converted number = ");
    
        for ( --gDigit; gDigit >= 0; --gDigit )
            printf ("%c", baseDigits[gConvertedNumber[gDigit]]);
    
        printf ("\n");
    }
    
    int main (void)
    {
        void getNumber (void);
        void getBase (void);
        void convertNumber (void);
        void displayConvertedNumber (void);
    
        while (1) {
            getNumber ();
            if ( gNumberToConvert == 0 )
                break;
            getBase ();
            convertNumber ();
            displayConvertedNumber ();
        }
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-03-10
      • 2013-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多