C 语言的计算单元转换器

发布于 2024-12-07 18:34:30 字数 941 浏览 0 评论 0原文

我正在学习 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),我会收到分段错误错误。为什么?

I'm learning C and I have written a simple program (just a tanning). On input you pass two arguments (row and column) and output you get a Calc (or Excel) code for this cell.
For example:

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

The code:

#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; 
}

But if I pass in a larger value (such as 300000000) I get a segmentation fault error. Why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七分※倦醒 2024-12-14 18:34:30

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

You're only allocating 7 bytes for kol. You're trying to write beyond the bounds of the array.

吃→可爱长大的 2024-12-14 18:34:30

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

假设递归至关重要,那么总的来说,我认为我希望使用如下解决方案:

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() 返回一个指向其数据末尾的 null 的指针格式化。理论上,我应该检查 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;
}

Are you experimenting with recursion? I don't think I'd be using a recursive solution. You should probably not be using as many global variables as you are, either.

Assuming recursion is crucial, then in outline, I think I'd expect to use a solution such as:

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;
}

Note that the revised powa() returns a pointer to the null at the end of the data it has formatted. Theoretically, I should check the return from snprintf() to ensure no buffer overflow. Since ...bogus... is not valid C, you can tell I've not compiled this, but I have now compiled this, and tested and corrected it (the correction being to replace the recursive call powa(div, buffer) with powa(div - 1, buffer), a change necessary because the calculation needs to deal with 0 versus 1 as the starting point for counting. The recursion scheme seems simpler to me (a single recursive call instead of three of them in your code).

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

Here is code to handle both scanning and formatting derived from the code above:

/*
** 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文