альтернатива массива переменной длины на языке c - PullRequest
1 голос
/ 02 апреля 2019

У меня есть этот код на языке c, он проверяет, является ли число, записанное в определенной числовой основе, десятичном, восьмеричном, ..etc, корректным, означает, что он использует символы, которые принадлежат этой определенной базе, например, восьмеричное число должно использовать только символы [0, 1, 2, 3, 4, 5, 6, 7], оно проверяет все основания от 2 до 36.

Проблема в том, что, когда я пытаюсь вычленить "базовые" символы из общего количества символов, появляется предупреждение о том, что ISO C90 forbids variable length array 'base_symbols'

int checkNumBase(char *num, int base){

        char all_symbols[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        char base_symbols[base];

        int i;
        unsigned int k;    

        for(i = 0; i<base; i++){
            base_symbols[i] = all_symbols[i];
        }


        for(k = 0; k<strlen(num); k++){        
            if(strchr(base_symbols, num[k]) == NULL){

                return 0;
            }
        }
        return 1;
    }

Ответы [ 4 ]

4 голосов
/ 02 апреля 2019

Одним из простых решений было бы усечь строку

char all_symbols[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";   // length corrected
if(base > 36)
    return 0;
all_symbols[base] = 0;
//.. as before
3 голосов
/ 02 апреля 2019

ISO C90 запрещает массив переменной длины base_symbols

В коде нет ничего плохого, вы получаете ошибку, потому что вы используете старый, устаревший компилятор. Вы должны получить современный, такой как GCC.

Обратите внимание, что более старые версии gcc поддерживали более новые версии языка, если вы правильно скомпилировали: gcc -std=c11 или gcc -std=c99, но по умолчанию использовали "gnu90", то есть C90 + нестандартные расширения. Более новые версии 5.0 или более поздние по умолчанию «gnu11».

Например, -ansi означает «дайте мне 30-летний режим дерьма», он же C90. Если вам не нужен C90 по причинам обратной совместимости, вы должны использовать gcc -std=c17 -pedantic-errors -Wall -Wextra.

В чем разница между C, C99, ANSI C и GNU C?

1 голос
/ 02 апреля 2019

Решение от @WeatherVane (т. Е. https://stackoverflow.com/a/55472654/4386427) - очень хорошее решение для кода, размещенного OP.

Решение ниже показывает альтернативный подход, который не использует строковые функции.

// Calculate the minimum base that allows use of char c
int requiredBase(char c)
{
  if (c >= '0' && c <= '9') return c - '0' + 1;  // '0' requires base 1, '1' requires base 2, ...
  if (c >= 'A' && c <= 'Z') return c - 'A' + 11; // 'A' requires base 11, 'B'requires base 12, ...
  return INT_MAX;
}

int checkNumBase(char *num, int base){
  while (*num)
  {
    if (requiredBase(*num) > base) return 0;
    ++num;
  }
  return 1;
}
1 голос
/ 02 апреля 2019

использование char *index;
затем index = strchr(all_symbols, toupper ( num[k])); чтобы увидеть, есть ли персонаж в наборе
если index в наборе, он будет иметь больший адрес. вычтите меньший адрес из большего, чтобы получить положительный результат
тогда if ( index && index - all_symbols < base) тогда num [k] действителен для этой базы.
toupper() в ctype.h

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...