【问题标题】:From integer to char array of digits and printing从整数到 char 数字数组和打印
【发布时间】:2016-08-07 13:12:29
【问题描述】:

我有一个 C 语言的整数,我想创建一个 char 数组并每次使用模 10 插入最后一个数字。之后,我需要从头到尾打印数组,以便在正确的顺序。我知道这听起来很奇怪,但我需要这样做。

但是有些东西不起作用。数组创建得很好,但是字符打印不起作用。这就是我所做的:

int baseChange (int base, int newBase, int num)
{
    int baseTen = toBaseTen(base, num); //give me a number on base 10
    char finalBase[24];
    int i;
    for (i = 0; baseTen != 0; i++)
    {
        int remain = baseTen % newBase;
        finalBase[i] = (char)(remain); //insert the last digit to the array
        baseTen /= newBase;
    }
    // Print finalBase from end to beginning in order to get the final number in the correct order:
    for (i--; i >= 0; i--)
    {
        printf("i is: %d... %c", i, finalBase[i]);
    }
    return SUCCESS_EXIT;
}

如果我在第一个 for 循环期间打印 finalBase[i],我会得到正确的数字,但在那之后,第二个 for 循环不会打印任何内容。为什么?

【问题讨论】:

  • 试试finalBase[i] + '0'
  • 第一个循环后i 是什么?第一个循环开始时的baseTen 是什么? toBaseTen 是做什么的?整个算法似乎存在根本缺陷:整数只是一个整数 - 没有基数或字符,只有原始位。当您将整数表示为字符串时,您在给定的基数中这样做。事实上,你有一个函数,它接受一个整数,并返回一个整数,但声称要改变它的 base 绝对是零意义。
  • 或者把%c改成%d

标签: c arrays


【解决方案1】:

intchar 的转换保留了第一个CHAR_BIT 位,它们是整数remain 中的前8 位,因为后者将包含数字(对于模数当然低于 10),它们在施法后将保持它们的值。

您的问题在于在 ASCII 表中打印等效数字。

printf 函数中的 %c 说明符是指与 ASCII 表中的值等效的字符以及保存该变量的内容。

ASCII表中引用值09的前10个字符等价于:

但数字字符的值从 48 到 57(以 10 为底/十进制):

所以不是:

finalBase[i] = (char)remain;

你需要改成:

finalBase[i] = remain + 48;

【讨论】:

    【解决方案2】:

    对于初学者来说这个循环

    for (i = 0; baseTen != 0; i++)
    {
        int remain = baseTen % newBase;
        finalBase[i] = (char)(remain); //insert the last digit to the array
        baseTen /= newBase;
    }
    

    不正确,因为通常变量baseTen 的值最初可能等于0。在这种情况下,不会在数组中写入任何内容。

    正确的循环可能是这样的

    int i = 0;
    do
    {
        finalBase[i++] = baseTen % newBase;
    } while ( baseTen /= newBase );
    

    至于应该显示数字的第二个循环,那么您需要将数字的相应表示形式输出为字符。

    例如

    while ( i-- )
    {
        printf( "i is: %d... %c\n", i,  finalBase[i] + '0' );
                                        ^^^^^^^^^^^^^^^^^^^^^               
    }
    

    考虑到int 类型的值可能是负数。请注意在数组中记下负值。

    '0''9' 的字符具有顺序代码。例如,如果将1 添加到字符'0',您将得到字符'1'

    或者您可以将数字输出为整数。例如

    while ( i-- )
    {
        printf( "i is: %d... %d\n", i,  finalBase[i] );
                             ^^               
    }
    

    或者最初您可以将数组中的数字存储为字符

    int i = 0;
    do
    {
        finalBase[i++] = '0' + baseTen % newBase;
    } while ( baseTen /= newBase );
    

    【讨论】:

      【解决方案3】:

      当您执行finalBase[i] = (char)(remain); 时,您并没有将您的remain 转换为它的ASCII code

      如果您的newBase<=10,那么您的余数始终在0-9 范围内,因此要将这些数字转换为它们的ASCII 代码,您可以这样做:

      finalBase[i] = remain + '0'; // convert remain into its ASCII code
      

      但是,如果您的 newBase 大于 10,比如十六进制,其中余数可以达到 15,那么您需要更多代码。

      此外,您的循环不会检查您是否向大小为 24 的数组插入超过 24 的元素。因此,您需要进行更改:

      /* Issue: You are not checking if you are going out ot bounds */
      /* for (i = 0; baseTen != 0; i++) */
      
      /* Confirm that you are in bounds, i.e. i < 24 */
      for (i = 0; baseTen != 0 && i < 24 ; i++) 
      {
          int remain = baseTen % newBase;
          finalBase[i] = remain + '0'; //insert the last digit to the array
          baseTen /= newBase;
      }
      
      /* To check if you went out of bound,
         And also for case when your number is 0 */
      if (i < 24) 
          finalBase[i++] = baseTen + '0';
      /* Number too big to store in 24 characters */
      else if (baseTen != 0) {
          printf("Error: Number too large to store\n");
          return;
      }
      

      【讨论】:

        【解决方案4】:

        需要关于编码的假设总是麻烦的根源。为什么不使用简单的地图?无需对编码进行假设,您甚至可以对数字使用完整的 Unicode 范围(这会变得有点复杂,虽然不是那么那么多)。

        #include <stdio.h>
        #include <stdlib.h>
        
        #define BC_OK         0
        #define BC_ERROR_OB   1
        #define BC_ERROR_NB   2
        
        int baseChange(int, int, int);
        
        int baseChange(int base, int newBase, int num)
        {
          // ASCII allows for up to base 64 without starting to get in trouble
          // with characters used by others as special characters
          // you can reuse this map for the inverse function, too.
          const char *digits =
              "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
          int baseTen = num;        //toBaseTen(base, num);
          // 24 were not enough (max would be 2^64 in base two)
          char finalBase[64];
          int i, remain;
          // always check the input
          if (base < 2 || base > 64) {
            return BC_ERROR_OB;
          }
          if (newBase < 2 || newBase > 64) {
            return BC_ERROR_NB;
          }
          // Ignore sign?
          // use shortcuts
          if(num == 0){
             i = 0;
             finalBase[0] = '0';
          } else {
             for (i = 0; baseTen != 0; i++) {
               remain = baseTen % newBase;
               // cutting the two bytes off should not be necessary, just in case
               finalBase[i] = digits[remain & 0xff];
               baseTen /= newBase;
             }
             i--;
          }
          for (; i >= 0; i--) {
            printf("i is: %d... %c\n", i, finalBase[i]);
          }
          return BC_OK;
        }
        
        // ALL CHECKS OMMITTED!
        
        int main(int argc, char **argv)
        {
          int input;
          int newbase;
          int ret;
          if (argc < 3) {
            fprintf(stderr, "Usage: %s integer new_base\n", argv[0]);
            exit(EXIT_FAILURE);
          }
        
          input = atoi(argv[1]);
          newbase = atoi(argv[2]);
        
          ret = baseChange(10, newbase, input);
          if (ret != BC_OK) {
            fprintf(stderr, "baseChange() failed with error number %d\n", ret);
            exit(EXIT_FAILURE);
          }
          exit(EXIT_SUCCESS);
        }
        

        【讨论】:

          【解决方案5】:

          您正在将 Integer 类型转换为 Character,因此它会将您的 int 视为某个字符的 ASCII 值。它会将该字符而不是您的号码添加到您的数组中。所以请尝试以下操作:

          int baseChange (int base, int newBase, int num)
          {
              int baseTen = toBaseTen(base, num); //give me a number on base 10
              char finalBase[24];
              int i;
              for (i = 0; baseTen != 0; i++)
              {
                  int remain = baseTen % newBase;
                  finalBase[i] = (char)(remain+48); //insert the last digit to the array
                  baseTen /= newBase;
              }
              // Print finalBase from end to beginning in order to get the final number in the correct order:
              for (i--; i >= 0; i--)
              {
                  printf("i is: %d... %c", i, finalBase[i]);
              }
              return SUCCESS_EXIT;
          }
          

          我已将 finalBase[i] = (char)(remain); 更改为 finalBase[i] = (char)(remain+48);

          因为 ASCII 中的数字以 48 开头,所以将 48 添加到循环中的每个数字,以便可以将其转换为 0-9。就是这样!

          第二个循环没有打印任何东西为什么?

          因为 0-9 的 ASCII 是不可打印的或者是空格和制表符。

          希望对您有所帮助!

          【讨论】:

          • 很高兴来到这里 :) @Vipasana
          • 这个问题可以在不明确提到“ASCII”的情况下得到更好的回答。 C 不依赖于 ASCII 排序。 C 编译器唯一需要知道的是所有十位数字都是连续编号的(因为规范是这样说的)。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-29
          • 1970-01-01
          • 2020-12-17
          • 2012-10-02
          • 1970-01-01
          相关资源
          最近更新 更多