如何增加字母组合超越'z'的c + +?

我正在制作一个Excel电子表格,而且我只能使用一种types的公式来处理大量的数据。 由于在公式中只有必要的变化涉及字母,我想知道是否有办法让一个程序,增加他们的Excel列顺序(A,B,C … Z; AA,AB,AC … AZ; BA,BB,BC … BZ)。

在我的情况下,我需要每次增加五个字母,所以这里是我试图获得的代码types:

#include <iostream> using namespace std; int main() { char x = 'B'; char y = 'E'; for (int z = 1; z < 2255; z++) { cout << "=SUMPRODUCT(SUBTOTAL(4,OFFSET(" << x << "1:" << y << "1,ROW(" << x << "1:" << x << "100)-ROW(" << x << "1),)))" << endl; x = x + 5; y= y + 5; } return 0; } 

当然,它不会工作,因为它超过了'z',但是,仍然有办法做到这一点?

一般的解决scheme

解决scheme1:创buildbase-26系统本身:

假设你有26个字母。 所以先让我们制作26号码系统。 我们使用每个数字1个字节。 我们创build一个数字数组,然后当添加超过26时,我们需要调整。

假设你现在的数字是25,我们加上7,然后我们需要处理溢出,假设256(1字节)为最大值,我们的数字限制是26.因此调整将是256-26=230 。 (我们在短(16位)上进行计算,所以在26+7=33 -> 33+230=263溢出,所以高字节为1,低字节为7)

计算了溢出阈值(高于1)后,我们可以将它添加到下一个数字,如果发生溢出,也可以这样做。

最后,为了显示,我们只需将65('A')添加到两个字节中的每一个中。 我们的最后一个字节将是'\ 0'null终止,所以我们可以把它变成一个string。

解决scheme2执行所有计算,然后将其转换为26个基数:

在这种情况下,

 number/26 = x 

 remainder r1 = (number%26) 

我们将r1存储为一个字节。

 x/26 = x1 

 remainder r2 = (x%26) 

我们将r2存储到下一个字节。

 x1/26 = x2 

 remainder r3 = (x%26) 

我们将r3存储到下一个字节。 我们得到一个stringr3 r2 r1 '\0' ,然后在每个字节中加上65'A'。

你可以在两个嵌套的循环中完成,从'A''Z' ,然后把两个字符追加在一起。 把结果放在一个向量中。

要获得单字母'A''Z' ,将它们添加到嵌套循环之前的向量中。

做这个:

 x = (x + 5 > 'Z' ? x + 5 - 'Z' + 'A' : x + 5); y = (y + 5 > 'Z' ? y + 5 - 'Z' + 'A' : y + 5); 

你试图产生的结果可以被视为一个基数为27的数字,使用字符'A'到'Z'作为26个数字。 有一点不寻常,因为'A'确实是'0',但是当你达到一个两位数的数字时,就是'AA'(正常的两位数是BA ),就像在9之后的下一个数字是10 )。 我们必须做一个相当小的调整来弥补这种怪异。

你可以使用正常的int (或其他)进行计数,然后在需要时转换为基数27。 由于我不认为它支持更多的列,所以我将这个版本限制在2位数,尽pipe扩展到更多将是相当微不足道的:

 std::string to_excel_column(int input) { int digit1 = input % 26; int digit2 = input / 26; std::string result; if (input > 26) result.push_back(digit2 + 'A' - 1); result.push_back(digit1 + 'A'); return result; } 

你可以作为一个选项,创build一个由两个字符组成的新数据types(类似std::pair<char,char>并为此定义算术。

但是,我认为继续使用int (或unsigned int )进行计数和算术会更简单,并定义一个函数to_col_heading ,将整数转换为Excel的一个/两个字符的列标题:

 #include <string> #include <iostream> #include <stdexcept> #include <iterator> /* This is the function that performs the transformation. */ std::string to_col_heading(unsigned i) { if (i > 26+26*26) throw std::overflow_error ("Value too large for transformation into Excel column heading."); char char1 = 'A' + (i / 26) - 1; char char2 = 'A' + (i % 26); if (char1 < 'A') return std::string(&char2,&char2 + 1); else return std::string(&char1,&char1 + 1) + char2; } int main() { std::ostream_iterator<std::string> out(std::cout,", "); for (unsigned i = 0 ; i < 26+26*26 ; i += 5) *out = to_col_heading(i); std::cout << std::endl; return 0; } 

输出:

 A, F, K, P, U, Z, AE, AJ, AO, AT, AY, BD, BI, BN, BS, BX, CC, CH, CM, CR, CW, DB, DG, DL, DQ, DV, EA, EF, EK, EP, EU, EZ, FE, FJ, FO, FT, FY, GD, GI, GN, GS, GX, HC, HH, HM, HR, HW, IB, IG, IL, IQ, IV, JA, JF, JK, JP, JU, JZ, KE, KJ, KO, KT, KY, LD, LI, LN, LS, LX, MC, MH, MM, MR, MW, NB, NG, NL, NQ, NV, OA, OF, OK, OP, OU, OZ, PE, PJ, PO, PT, PY, QD, QI, QN, QS, QX, RC, RH, RM, RR, RW, SB, SG, SL, SQ, SV, TA, TF, TK, TP, TU, TZ, UE, UJ, UO, UT, UY, VD, VI, VN, VS, VX, WC, WH, WM, WR, WW, XB, XG, XL, XQ, XV, YA, YF, YK, YP, YU, YZ, ZE, ZJ, ZO, ZT, ZY, 

为了支持最多3个(按字母顺序)列标题的数字,下面的function工作。 它完全分开处理前26个值,以简化其余的计算。 我还介绍了一些静态常量来处理26的幂更一致的方式。对于三位数字,你需要26 0,26 1和26 2 ,但是系统可以扩展到覆盖任意数量的数字。

我相信有一种方法来优化这个速度。 这不是这里的重点。

 std::string to_col_heading(unsigned i) { const static unsigned pow1 = 26; const static unsigned pow2 = 26*26; const static unsigned max = pow1 + pow2 + 26 * pow2; if (i < pow1) { char c = 'A' + i % pow1; return std::string(&c,&c+1); } if (i > max) throw std::overflow_error ("Value too large for transformation into Excel column heading."); i -= pow1; char char1 = 'A' + (i / pow2) - 1; char char2 = 'A' + (i%pow2) / pow1; char char3 = 'A' + i % pow1; if (char1 < 'A') return std::string(&char2,&char2 + 1) + char3; else return std::string(&char1,&char1 + 1) + char2 + char3; }