问题描述
我正在学习 C 并且我编写了一个简单的程序(只是晒黑).在输入时传递两个参数(行和列)并在输出时获得该单元格的 Calc(或 Excel)代码.例如:
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
代码:
#include <stdio.h>
char kol[7] = "";
unsigned int passes=0, nr;
int powa(unsigned int lv)
{
if(passes < nr)
{
if(kol[lv] == '')
{
kol[lv] = 'A';
kol[lv+1] = '';
} 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] != '')
{
len++;
}
for(i=len-1;i>=0;i--)
{
putchar(kol[i]);
}
printf("%u", wier);
return 0;
}
但如果我传入一个更大的值(例如 300000000),我会收到分段错误错误.为什么?
But if I pass in a larger value (such as 300000000) I get a segmentation fault error. Why?
推荐答案
你在尝试递归吗?我不认为我会使用递归解决方案.您可能也不应该使用尽可能多的全局变量.
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 = '';
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)
", row, col);
else
{
char *end = powa(col-1, buffer);
snprintf(end, sizeof(buffer) - (end - buffer), "%u", row);
printf("Col %u, Row %u, Cell %s
", col, row, buffer);
}
}
return 0;
}
请注意,修改后的 powa()
在已格式化的数据末尾返回一个指向 null 的指针.理论上,我应该检查 snprintf()
的返回以确保没有缓冲区溢出.我现在已经编译了这个,并且测试并更正了它(更正是将递归调用 powa(div, buffer)
替换为 powa(div - 1, buffer)
,这是必要的更改,因为计算需要处理 0 与1 作为计数的起点.递归方案对我来说似乎更简单(一个递归调用,而不是代码中的三个).
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. 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 = '';
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++) != '')
{
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
",
pf, tests[i].col, tests[i].row, tests[i].cell, buffer, n);
}
if (pass == NUM_TESTS)
printf("== PASS == %d tests OK
", pass);
else
printf("!! FAIL !! %d out of %d failed
", (NUM_TESTS - pass), NUM_TESTS);
return (pass == NUM_TESTS) ? 0 : 1;
}
这篇关于C 中的 Calc 单元格转换器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!