C 中的 Calc 单元格转换器 [英] Calc cell convertor in C
问题描述
我正在学习 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()
的返回以确保没有缓冲区溢出.由于 我现在已经编译了这个,并且测试并更正了它(更正是将递归调用 ...bogus...
不是有效的 C,你可以说我没有编译这个,但是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. Since I have now compiled this, and tested and corrected it (the correction being to replace the recursive call ...bogus...
is not valid C, you can tell I've not compiled this, butpowa(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 单元格转换器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!