1

I have this code in c language, it does check if a number written in a certain numeric base, decimal, octal, ..etc is correct, means that it is using characters which belongs to this certain base, for example, an octal number should only use characters [0, 1, 2, 3, 4, 5, 6, 7], it checks all the bases between 2 and 36.

The problem is that when I try to substring "base" characters from the total characters it give me a warning saying that 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;
    }
Rodwan Bakkar
  • 474
  • 3
  • 17

4 Answers4

4

One simple solution would be to truncate the string

char all_symbols[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";   // length corrected
if(base > 36)
    return 0;
all_symbols[base] = 0;
//.. as before
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • 3
    By far the best solution. Some nitpick: It seems `all_symbols` shall be `[37]` – Support Ukraine Apr 02 '19 at 10:42
  • @4386427 good spot, I just copied that from the question. Edited. – Weather Vane Apr 02 '19 at 10:42
  • could you please elaborate more I don't really know how this can work :P – Rodwan Bakkar Apr 02 '19 at 10:52
  • 1
    Well, what you did was to copy `base` characters from `all_symbols[]` to `base_symbols[]`, and this achieves the same thing: the required string of valid characters. But note: you haven't allowed room for the `NUL` string terminator with arrays of length `[36]` and `[base]`, and you did not put a terminator at the end of `base_symbols[]`. – Weather Vane Apr 02 '19 at 10:57
3

ISO C90 forbids variable length array 'base_symbols'

There's nothing wrong with the code, you get error this because you are using an old, obsolete compiler. You need to get a modern one such as gcc.

Please note that older versions of gcc did support newer versions of the language if you compiled correctly: gcc -std=c11 or gcc -std=c99, but used "gnu90" as default, which is C90 + non-standard extensions. Newer versions 5.0 or later default to "gnu11".

For example, -ansi means "give me 30 years old crap mode" aka C90. Unless you really need C90 for backwards-compatibility reasons, you should be using gcc -std=c17 -pedantic-errors -Wall -Wextra.

What is the difference between C, C99, ANSI C and GNU C?

Lundin
  • 195,001
  • 40
  • 254
  • 396
1

use char *index;
then index = strchr(all_symbols, toupper ( num[k])); to see if the character is in the set
if index is in the set it will have a larger address. subtract the smaller address from the larger address to get a positive result
then if ( index && index - all_symbols < base) then num[k] is valid for that base.
toupper() is in ctype.h

xing
  • 2,125
  • 2
  • 14
  • 10
1

The solution by @WeatherVane (i.e. https://stackoverflow.com/a/55472654/4386427) is a very good solution for the code posted by OP.

The solution below shows an alternative approach that doesn't use string functions.

// 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;
}
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63