【问题标题】:Issue with string concatenation in CC中的字符串连接问题
【发布时间】:2013-03-28 04:32:15
【问题描述】:

这是关于C 编程语言的。

我有大量的二维数组 (sizes are not fixed)。考虑以下示例。

bool sym_a[][]={{...},{...},...};  //consider these are initialized properly
bool sym_b[][]={{...},{...},...};
...
bool sym_z[][]={{...},{...},...};
bool sym_0[][]={{...},{...},...};
bool sym_1[][]={{...},{...},...};
...
bool sym_9[][]={{...},{...},...};
...

注意命名约定,所有的名字都是一样的。只有数组名称的最后一个字符会改变(如果可以有多个字符会更好,但这并不重要)。

好的,现在我有一个函数。它根据传递的参数选择其中一个二维数组。然后对选定的数组执行一些任务。请注意,任务是常见的,只有选定的数组会被更改。

例如,根据我目前能想到的,是的switch-case,我可以实现如下功能。

void doStuff(char letter){
    switch(letter){
        case 'a':
            sym_a[0][0]=1;  //just for demonstration :D
        break;
        case 'b':
            sym_b[0][0]=1;  //same thing, only the character 'a' changed to 'b'
        break;
        ...
        case 'z':
            sym_z[0][0]=1;
        break;
        case '0':
            sym_0[0][0]=1;
        break;
        case '1':
            sym_1[0][0]=1;
        break;
        ...
        ...
    }    
}

但必须有更好的方法。如果我有 1000 个这样的数组,那么我是否必须编写 1000 个这样的案例?对于所有情况,内容完全相同。变量名只有一个字符被改变。

如果有类似字符串连接的东西会很好。

#define conc(a,b) a ## b

那么conc(sym_,a) 将代表sym_a。但这不能直接应用在这里。因为我无法将确切的字母传递给conc(a,b) 的右侧参数,所以只能传递包含所需字母的变量。

void doStuff(char letter){
    conc(sym_,letter)[0][0]=1;
}

conc(sym_,letter) 给出sym_letter。但我需要将sym_ 与字符变量letter 的内容连接起来。

例如,如果我打电话给doStuff('b'); 他们应该给出sym_b,而不是sym_letter

希望我的要求明确。这件事看起来很简单,但我想不出办法摆脱它。请注意,二维数组的大小(行数/列数)不是固定的。否则我可以使用 3D 数组。

感谢任何想法。

【问题讨论】:

  • 为什么需要这么多二维变量一直活着?
  • 我不认为 C 语言有 bool 数据类型。您可以使用位移运算符创建单个 int 数组并存储所有布尔数据。
  • @akshay202 好吧,他们不是一直都是alive(你是什么意思?)。它们就像在程序中硬编码并且仅在需要时才考虑。无论如何,这都不是问题。但是你有没有更好的选择?上面的代码是我目前正在使用的(是的,它有效)。但我需要一个简单的替代方案
  • 我的意思是,你真的需要内存来让所有这些数组一直保持分配状态吗?你不是在浪费内存吗?
  • "我有大量的二维数组(大小不固定)。考虑下面的例子。bool sym_a[][];"这在 C 中是不可能的。数组的大小必须在编译时固定,因为大小是数组类型的一部分。

标签: c++ arrays pointers multidimensional-array


【解决方案1】:

你有大量的静态数组,所以很自然的扩展,你最终会有大量的条件来访问它们。

您可以定义一个额外的静态数组,将字符代码映射到一个数组。

static const struct {
  char* lookup_code;
  bool **array;
} char_code_lookup[] = {
    { .lookup_code = "a", sym_a },
    { .lookup_code = "b", sym_b },
    /* ... */
    { .lookup_code = NULL, NULL }, /* Terminator */
};

然后,您的 doStuff 函数可以扫描数组以查找与静态定义数组匹配的适当查找代码。

通过一些宏魔法,您可以同时生成静态数组和静态查找数组以减少重复,但上面列出的方法可能更易于阅读。

或者,您可以使用malloc 动态分配数组,同时在运行时创建数组时关联查找代码。

【讨论】:

  • 如果真的有1000 这样的数组(意味着宽字符),那么写这可能有点慢。然后可以qsort 允许二进制搜索,或者更有可能重新设计一点以允许直接跳转(取决于查找代码的详细信息。)
  • 没错,这样的实现会很慢。如图所示,每个查找代码都会有一个strcmp,直到找到匹配项。改进的设计可以动态分配数组并将查找键与哈希值相关联,允许 O(1) 哈希查找。
【解决方案2】:

这样的事情有帮助吗? [抱歉,如果这里有一些 C++。 ]

bool** sym_a;
bool** sym_b ;
bool** sym_z;
bool** sym_0;
bool** sym_1;
bool** sym_9 ;


unsigned lowestEntry = 'a';
unsigned highestEntry = '9';
const unsigned numEntries = highestEntry - lowestEntry;

size_t size = sizeof(bool**)* numEntries;

bool*** lookup = (bool***)malloc(size); 

#define conc(a,b) a ## b
#define index(a) #a[0]-'a'
#define add(a) lookup[index(a)] = conc(sym_,a)

void init()
{
    memset(lookup, 0, size);
     add(a);
     add(b);
     add(z);
     add(9);
     add(k); // does not compile, sym_k not defined.
}

bool** findSymbolTable(char val)
{
    return lookup[val - lowestEntry];
}

【讨论】:

    【解决方案3】:

    分配一个大的 int 数组并将其分区以供其他变量使用。

    例如。

    int 数据[2600];

    sym_a 将有前 100 个整数,sym_b 将有前 100 个整数,依此类推。您将能够在这些数组中存储 8 * 100* 4 个布尔值。

    现在访问 sym_p[x][y] 你会说你总共有 R 行和 C 列:

    int * 开始 = 数据 + (ASCIValue(p) - ASCIValue(a)) * 100;

    您必须从头开始读/写位号 (C * x + y)。

    【讨论】:

      猜你喜欢
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-02
      • 2011-12-02
      • 1970-01-01
      • 2011-09-03
      相关资源
      最近更新 更多