#arrays #c #if-statement #c-strings #strchr
#массивы #c #if-оператор #c-строки #strchr
Вопрос:
У меня есть функция, которая подсчитывает количество уникальных символов в 2D-массиве, перебирая его и увеличивая количество в каждой ячейке 1D-массива на 1 каждый раз, когда найден символ из допустимого массива символов. Затем я перебираю 1D-массив, и каждый раз, когда найдена ячейка с числом больше 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;
}
Ответ №1:
Объявите массив символов или строковый литерал, например
const char *letters = "KRBGCYQM.";
а затем используйте стандартную строковую функцию strchr
, объявленную в заголовке <string.h>
, например
char *p = strchr( letters, b->shelves[i][j] );
if ( p != NULL )
{
if ( b->shelves[i][j] != '.' ) chars[p - letters];
}
else
{
return false;
}
Обратите внимание на то, что читателям вашего кода неясно, почему символ '.'
включен, хотя он не учитывается.
Комментарии:
1. Я продолжал получать stack-buffer-overflow при запуске, но, похоже, это проблема в более широкой программе, поскольку я тестировал ваш метод в меньшем масштабе, и он сработал, так что спасибо!
Ответ №2:
Могу ли я предложить битовые поля вместо массива символов? Что-то вроде этого:-
present = 0
foreach char c in b->shelves
if c is a uppercase letter
present |= 1 << (c - 'A')
present amp;= 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
Комментарии:
1. Могу ли я предложить битовые поля … почему? Вы не можете использовать битовые поля для подсчета.
2. Мы еще не рассматривали битовые поля или побитовые операторы, поэтому я мог бы попытаться реализовать это, просто чтобы опередить события, спасибо за идею
3. @AndrewHenle: Ну, в примере кода, хотя для каждой буквы есть счетчик, выполняется единственный тест на ненулевое значение, так зачем считать? Битовое поле работает так же хорошо и использует меньше памяти (хорошо, несколько байт, но оно предоставит дополнительный инструмент в наборе трюков OPS, поскольку OP, похоже, учится в данный момент). Затем вы можете И поле для проверки на наличие недопустимых записей, и довольно легко подсчитать количество установленных битов.