【问题标题】:Shortening a function that counts the number of unique chars in a 2D array缩短计算二维数组中唯一字符数的函数
【发布时间】:2021-03-19 22:30:32
【问题描述】:

我有一个函数,它通过循环计算二维数组中唯一字符的数量,并在每次找到有效字符数组中的字符时将一维数组的每个单元格中的计数增加 1。然后我循环一维数组,每次找到一个数字大于 0 的单元格时,都会增加一个计数器。如果此数字高于我的结构的高度/宽度,则返回 false。

'.'表示一个空白空间,虽然它在程序方案中有效,但不应算作唯一字符。

我想知道是否有一种方法可以创建具有相同功能但更短的函数。

bool uniqueChars (Bookcase *b)
{
   int i, j, chars[8] = {0}, cnt = 0;
   char validChars[10] = {"KRGYBMCW."};

   bNullPoint(b);

   for (i = 0; i < b->height; i++) {
      for (j = 0; j < b->width; j++) {
         b->shelves[i][j] = toupper(b->shelves[i][j]); /* To aid with testing*/
         if (strchr(validChars, b->shelves[i][j])) {
            if (b->shelves[i][j] == 'K') {
               chars[0] += 1;
            }
            if (b->shelves[i][j] == 'R') {
               chars[1] += 1;
            }
            if (b->shelves[i][j] == 'B') {
               chars[2] += 1;
            }
            if (b->shelves[i][j] == 'G') {
               chars[3] += 1;
            }
            if (b->shelves[i][j] == 'C') {
               chars[4] += 1;
            }
            if (b->shelves[i][j] == 'Y') {
               chars[5] += 1;
            }
            if (b->shelves[i][j] == 'W') {
               chars[6] += 1;
            }
            if (b->shelves[i][j] == 'M') {
               chars[7] += 1;
            }
         } else {
            return false;
         }
      }
   }
   for (i = 0; i < 8; i++) {
      if (chars[i] > 0) {
         cnt += 1;
      }
   }
   if (cnt > b->height) {
      return false;
   }
   return true;
}

【问题讨论】:

    标签: arrays c if-statement c-strings strchr


    【解决方案1】:

    例如声明一个字符数组或字符串字面量

    const char *letters = "KRBGCYQM.";
    

    然后使用标头&lt;string.h&gt;中声明的标准字符串函数strchrlike

    char *p = strchr( letters, b->shelves[i][j] );
    if ( p != NULL ) 
    {
        if ( b->shelves[i][j] != '.' ) ++chars[p - letters];
    }
    else
    {
        return false;
    }
    

    请注意,您的代码的读者不清楚为什么包含字符'.',尽管它没有被计算在内。

    【讨论】:

    • 我在运行它时不断收到堆栈缓冲区溢出,但这似乎是更广泛的程序中的一个问题,因为我在较小的规模上测试了你的方法并且它有效,所以谢谢!跨度>
    【解决方案2】:

    我可以建议位域而不是字符数组吗?像这样的东西:-

    present = 0
    foreach char c in b->shelves
        if c is a uppercase letter
            present |= 1 << (c - 'A')
    present &= valid letters bit pattern (this is a constant and is the or of 1 shifted by each letter)
    return number of bits in present <= b->height
    

    或者,如果您不喜欢这样,请使用开关而不是 if 测试的顺序:-

    switch b->shelves[i][j]
        case 'K'
            ++chars[0]
        other cases for the valid letters
            ++chars[whatever]
        default:
            error - an invalid character
    

    【讨论】:

    • 我可以建议位域... 为什么?您不能使用位域进行计数。
    • 我们还没有研究过位域或位运算符,所以我可能会尝试实现它,只是为了看起来领先一步,谢谢你的想法
    • @AndrewHenle:嗯,在示例代码中,虽然每个字母都有一个计数,但唯一完成的测试是非零,那么为什么要计数呢?位字段也可以工作并且使用更少的内存(好的,几个字节,但它会在 OP 的技巧包中提供一个额外的工具,因为 OP 目前似乎正在学习)。然后,您可以 AND 字段来检查无效条目,并且很容易计算设置的位数。
    猜你喜欢
    • 1970-01-01
    • 2017-04-07
    • 2019-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多