【问题标题】:Calc cell convertor in CC中的计算单元格转换
【发布时间】:2011-10-04 16:56:50
【问题描述】:

我正在学习 C 并且我编写了一个简单的程序(只是晒黑)。在输入时,您传递两个参数(行和列)并在输出时获得该单元格的 Calc(或 Excel)代码。 例如:

Input: 3 1     Output: A3
Input: 1 27    Output: AA1

代码:

#include <stdio.h>

char kol[7] = "";
unsigned int passes=0, nr;

int powa(unsigned int lv)
{
  if(passes < nr)
  {
    if(kol[lv] == '\0')
    {
      kol[lv] = 'A';
      kol[lv+1] = '\0';
    } else
    {
      kol[lv]++;
      if(kol[lv] == 'Z'+1)
      {
        kol[lv] = 'A';
        powa(lv+1);
        return 0;
      }

    }
    passes++;
    if(lv != 0)
    {
      powa(lv-1);
    } else
    {
      powa(lv);
    }

  }
}

int main(void)
{
  unsigned int wier;
  int i, len=0;
  scanf("%u %u", &wier, &nr);
  powa(0);
  while(kol[len] != '\0')
  {
    len++;
  }

  for(i=len-1;i>=0;i--)
  {
    putchar(kol[i]);
  }
  printf("%u", wier);
  return 0; 
}

但如果我传入一个更大的值(例如 300000000),我会收到分段错误错误。为什么?

【问题讨论】:

  • 可能我遗漏了什么,但是如果kol只有7个字符的空间,你怎么能输出3亿的答案?
  • Base 26 中的 300,000,000 对应于 YFLRYN 或附近。所以 7 的长度刚好够 300,000,000 的字母转换。

标签: c segmentation-fault


【解决方案1】:

您只为 kol 分配了 7 个字节。您正在尝试写入超出数组的范围。

【讨论】:

    【解决方案2】:

    你在尝试递归吗?我不认为我会使用递归解决方案。您可能也不应该使用尽可能多的全局变量。

    假设递归至关重要,那么概括地说,我想我希望使用以下解决方案:

    char *powa(unsigned int code, char *buffer)
    {
        unsigned int div = code / 26;
        unsigned int rem = code % 26;
        if (div > 0)
            buffer = powa(div - 1, buffer);
        *buffer++ = rem + 'A';
        *buffer = '\0';
        return buffer;
    }
    
    int main(void)
    {
        char buffer[32];
        unsigned int col, row;
    
        printf("Enter column and row numbers: ");
        if (scanf("%u %u", &col, &row) == 2)
        {
            if (col == 0 || row == 0)
                fprintf(stderr, "Both row and column must be larger than zero"
                                " (row = %u, col = %u)\n", row, col);
            else
            {
                char *end = powa(col-1, buffer);
                snprintf(end, sizeof(buffer) - (end - buffer), "%u", row);
                printf("Col %u, Row %u, Cell %s\n", col, row, buffer);
            }
        }
        return 0;
    }
    

    请注意,修改后的powa() 在其已格式化的数据末尾返回一个指向空值的指针。理论上,我应该检查来自snprintf() 的返回以确保没有缓冲区溢出。 由于...bogus... 不是有效的C,你可以说我没有编译这个,但是我现在已经编译了这个,并测试并更正了它(更正是替换递归调用powa(div, buffer)使用powa(div - 1, buffer),需要进行更改,因为计算需要处理 0 与 1 作为计数的起点。递归方案对我来说似乎更简单(一个递归调用,而不是代码中的三个)。

    Enter column and row numbers: 13 27
    Col 13, Row 27, Cell M27
    
    Enter column and row numbers: 27 13
    Col 27, Row 13, Cell AA13
    
    Enter column and row numbers: 30000000 128
    Col 30000000, Row 128, Cell BMPVRD128
    
    Enter column and row numbers: 300000000 128
    Col 300000000, Row 128, Cell YFLRYN128
    

    以下是从上述代码派生的用于处理扫描和格式化的代码:

    /*
    ** Convert column and row number into Excel (Spreadsheet) alphanumeric reference
    ** 1,1     => A1
    ** 27,1    => AA1
    ** 37,21   => AK21
    ** 491,321 => RW321
    ** 3941,87 => EUO87
    ** From StackOverflow question 7651397 on 2011-10-04:
    ** http://stackoverflow.com/questions/7651397/calc-cell-convertor-in-c
    */
    
    #include <ctype.h>
    #include <stdio.h>
    #include <string.h>
    
    extern unsigned xl_row_decode(const char *code);
    extern char *xl_row_encode(unsigned row, char *buffer);
    
    static char *xl_encode(unsigned row, char *buffer)
    {
        unsigned div = row / 26;
        unsigned rem = row % 26;
        if (div > 0)
            buffer = xl_encode(div-1, buffer);
        *buffer++ = rem + 'A';
        *buffer = '\0';
        return buffer;
    }
    
    char *xl_row_encode(unsigned row, char *buffer)
    {
        return(xl_encode(row-1, buffer));
    }
    
    unsigned xl_row_decode(const char *code)
    {
        unsigned char c;
        unsigned r = 0;
        while ((c = *code++) != '\0')
        {
            if (!isalpha(c))
                break;
            c = toupper(c);
            r = r * 26 + c - 'A' + 1;
        }
        return r;
    }
    
    static const struct
    {
        unsigned col;
        unsigned row;
        char     cell[10];
    } tests[] =
    {
        {     1,     1, "A1"       },
        {    26,     2, "Z2"       },
        {    27,     3, "AA3"      },
        {    52,     4, "AZ4"      },
        {    53,     5, "BA5"      },
        {   676,     6, "YZ6"      },
        {   702,     7, "ZZ7"      },
        {   703,     8, "AAA8"     },
        {   728,     9, "AAZ9"     },
    };
    enum { NUM_TESTS = sizeof(tests) / sizeof(tests[0]) };
    
    int main(void)
    {
        char buffer[32];
        int pass = 0;
    
        for (int i = 0; i < NUM_TESTS; i++)
        {
            char *end = xl_row_encode(tests[i].col, buffer);
            snprintf(end, sizeof(buffer) - (end - buffer), "%u", tests[i].row);
            unsigned n = xl_row_decode(buffer);
            const char *pf = "FAIL";
    
            if (tests[i].col == n && strcmp(tests[i].cell, buffer) == 0)
            {
                pf = "PASS";
                pass++;
            }
            printf("%s: Col %3u, Row %3u, Cell (wanted: %-8s vs actual: %-8s) Col = %3u\n",
                   pf, tests[i].col, tests[i].row, tests[i].cell, buffer, n);
        }
        if (pass == NUM_TESTS)
            printf("== PASS == %d tests OK\n", pass);
        else
            printf("!! FAIL !! %d out of %d failed\n", (NUM_TESTS - pass), NUM_TESTS);
    
        return (pass == NUM_TESTS) ? 0 : 1;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-06
      • 1970-01-01
      • 1970-01-01
      • 2023-02-05
      • 2013-03-28
      • 2022-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多