如何在c ++之外增加'z'之外的字母组合?

时间:2013-06-27 04:46:18

标签: c++ excel char increment

我正在研究Excel电子表格,我只需要使用一种类型的公式来处理大量数据。由于在公式中唯一必要的更改涉及字母,我想知道是否有办法使程序按照Excel列顺序递增它们(A,B,C ... Z; AA,AB,AC ...... AZ; BA,BB,BC ... BZ)。

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

#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',但是,有没有办法做到这一点?

5 个答案:

答案 0 :(得分:1)

常规解决方案说明

解决方案1:创建base-26系统本身:

假设您有26个字母。所以首先让26号码系统。我们为每个数字使用1个字节。我们创建一个数字数组,然后我们需要在添加超过26时调整。

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

计算了溢出阈值(高于1)后,我们可以将其添加到下一个数字中,如果发生溢出则执行相同操作。

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

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

在这种情况下,

26+7=33 -> 33+230=263

number/26 = x

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

remainder r1 = (number%26)

x/26 = x1

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

remainder r2 = (x%26)

x1/26 = x2

我们将r3存储到下一个字节。我们得到一个字符串remainder r3 = (x%26) ,然后为每个字节添加65'A'。

答案 1 :(得分:0)

这样做:

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

答案 2 :(得分:0)

您可以在两个嵌套循环中执行此操作,包括'A''Z',然后将两个字符追加在一起。将结果放在矢量中。

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

答案 3 :(得分:0)

作为一个选项,您可以创建一个由两个字符组成的新数据类型(类似于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个(字母)数字,下面的功能有效。它完全分开处理前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;
}

答案 4 :(得分:0)

您尝试生成的结果可以被视为基数为27的数字,使用字符“A”到“Z”作为26位数字。这是 little 不寻常,因为'A'实际上是'0',但是当你得到一个两位数的数字时,它是“AA”,(正常的两位数将是{ {1}} - 即,就像9之后的下一个数字BA)。我们必须做一个相当小的调整,以弥补这种奇怪。

您可以使用普通10(或其他)进行计数,然后在需要时转换为基数27。由于我认为它不支持更多列,我将此版本限制为2位数,但扩展到更多将是相当微不足道的:

int