I am looking for a way to take a string and check 3 possibilities.
- Digit and thus converts it to a signed int (not a long)
- Is a symbolic representation previously defined at runtime, and converts it to a signed int
- Neither
The "symbolic representation" will be basically like an associative array that starts at 0 elements and expands as more symbols are added. For example lets say for instance that C had associative arrays (I wish) with this peusdocode:
symbol_array['q'] = 3;
symbol_array['five'] = 5;
symbol_array['negfive'] = -5;
symbol_array['random294'] = 28;
signed int i;
string = get_from_input();
if(!(i = convert_to_int(string))) {
if(!(i = translate_from_symbol(string))) {
printf("Invalid symbol or integer\n");
exit(1);
}
}
printf("Your number: %d\n, i);
The idea being if they entered "5" it would convert it to 5 via convert_to_int, and if they entered "five" it would convert it to 5 via translate_from_symbol. As what I feel may be hardest is if they entered "random294" it wouldn't convert it to 294, but to 28. If they entered "foo" then it would exit(1).
My general questions are these: (Instead of making multiple posts)
When making convert_to_int
I know I shouldn't use atoi
because it doesn't fail right. Some people say to use strtol
but it seems tedious to convert it back to a non-long int. The simplistic (read: shortest) way I've found is using sscanf
:
int i;
if ((sscanf(string, "%d", &i)) == 1){
return i;
}
However, some people look down on that even. What is a better method if not sscanf or converting strtol?
Secondly, how can I not only return an integer but also know if it found one. For example if the user entered "0" then it would return 0, thus setting off my FALSE in my if statement. I had considered using -1 if not found but since I am returning signed int's then this also suffers from the same problem. In PHP I know for example with strpos
they use === FALSE
Finally, is there any short code that emulates associate arrays and/or lets me push elements on to the array in runtime?
First, you might want to revise your syntax and set the keyword apart from the operand, i.e.
"neg five"
instead of"negfive"
. Otherwise your symbol lookup for the keywords has to consider every prefix. ("random294"
might be okay if your keywords aren't allowed to have digits in them.)Sure,
sscanf
tells you whether you found a decimal in the return value and writes that decimal to a separateint
, which is nice, but you'll have to watch out for trailing characters by checking that the number of characters read equals the length of your string with the%n
format. Otherwise,sscanf
will consider5x
as legal decimal number.strtol
also returns a pointer to the location after the parsed decimal number, but it relies too much on checkingerr
for my taste.The fact that
strtol
uses long integers shouldn't be an issue. If the input doesn't fit into an int, returnINT_MAX
orINT_MIN
or issue an error.You can also easily write a wrapper function around
sscanf
orstrtol
that suits your needs better. (I know I'd like a function that returns true on success and stores the integer via a pointer argument,sscanf
style, where success means: no trailing non-digit characters.)Finally, about the associative arrays: There is no short code, at least not in C. You'll have to implement your own hash map or use a library. As a first draft, I'd use a linear list of strings and check them one by one. This is a very naive approach, but easy to implement. I assume that you don't start out with a lot of symbols, and you're not doing a lot of checks, so speed shouldn't be an issue. (You can sort the array and use binary search to speed it up, but you'd have to re-sort after every insertion.) Once you have the logic of your program working, you can start thinking about hash maps.