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;
    }
12
  • 1
    Just replace char base_symbols[base]; with char base_symbols[36];, if you don't want to use VLAs. Commented Apr 2, 2019 at 10:01
  • 2
    I honestly don't see why you need base_symbols at all. The same indices are valid (and mean the same) in all_symbols. Commented Apr 2, 2019 at 10:02
  • I guess I need it, let's say the base is octal then I have substring 8 characters and check if my number belongs to them, please correct me if I am wrong Commented Apr 2, 2019 at 10:04
  • 1
    -ansi is the same as -std=c90 Commented Apr 2, 2019 at 10:17
  • 1
    -ansi means "give me 30 years old crap mode". You should be using gcc -std=c17 -pedantic-errors -Wall -Wextra. Commented Apr 2, 2019 at 10:34

4 Answers 4

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
Sign up to request clarification or add additional context in comments.

4 Comments

By far the best solution. Some nitpick: It seems all_symbols shall be [37]
@4386427 good spot, I just copied that from the question. Edited.
could you please elaborate more I don't really know how this can work :P
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[].
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?

1 Comment

As of gcc 10.2.0, "gnu17" (the GNU dialect of ISO C17) is the default.
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

1 Comment

but why index - all_symbols and not the contrary?
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;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.