Check either its a char or an integer - c

this is an integer array:
int values[] = { 75, '*', 5,'-' };
for(i=0 ; i<size ; i++){
// Here
}
how to check if the values[i] is an integer or an operation ??
maybe the value equals the Ascii of an operation,, how to deal with it in this case??

You can't. As for as the compiler is concerned, the constants 42 an '*' are one and the same. In the compiled object code, they're both represented as the integer 42.
If you need to differentiate between integers and characters, either use a boolean flag or enum indicating the type of the value, or keep your integers and characters in separate arrays.
Note that in C++, but not in C, there is a slight difference: 42 has the type int, whereas '*' has the type char, so you can differentiate this fact using overloaded functions or templates.

That's a dangerous road to go down. The array in your example will translate (during compilation) into:
int values[] = {75, 42, 5, 45};
So when you see the number 42... what is it? Is it the '*' character, or did you actually mean the number 42?
You can't rely on typecasting, either, because all your values will be cast to ints, since they're stored in an integer array. Your best bet is to make a struct that holds both type and value, like so:
typedef struct
{
int type; //0 for int, 1 for operator, and so forth.
int value; //holds either a character code or an integer value
//you could use a union here, if you felt it would make things cleaner...
} Token;
Then checking to see what type a token is is simply a matter of looking at token.type.
Hope this helps!
PS: The cheating answer would be to use a dynamically typed language. Lots less work on your part, but slower, and I don't know if it's an option for you.

Your array elements cannot be simple integers.
Try this instead:
enum ElementType {INTEGER, OPERATION};
struct ArrayElement {
enum ElementType etype;
int evalue;
};
struct ArrayElement values[] = {
{INTEGER, 75}, {OPERATION, '*'}, {INTEGER, 5}, {OPERATION, '-'}
};
for (i = 0; i < sizeof values / sizeof *values; i++) {
/* Here */
switch (values[i].etype) {
default: printf("unrecognized type. value is %d.\n", values[i].value);
break;
case INTEGER: printf("INTEGER with value %d.\n", values[i].value);
break;
case OPERATION: printf("OPERATION with value '%c'.\n", values[i].value);
break;
}
}

Related

Conversion of decimal to string

I'm trying to convert a decimal value into a string. I use the STM32CubeIDE IDE but am getting an error like 'Invalid binary operator'. I'm able to set &n to the decimal value 3695. I need to convert that into a string. How would I do that?
void main()
{
uint8_t TxArr;
uint16_t Data;
int a[10];
int i;
while (1)
{
HAL_I2C_Master_Transmit(&hi2c1,0x16, &TxArr, 1, 1000);
HAL_I2C_Master_Receive(&hi2c1, 0x17, &Data, 2, 1000);
for(i=0;i<4;i++)
{
a[i]=Data%10+0x30; //value in Data is 3695.
Data=Data/10;
HAL_UART_Transmit(&huart3, a[i], 11, 100);
HAL_Delay(300);
}
}
The error is produced by:
n = n / 10;
What this would do if n was a pointer (int* n) is that it would repoint n to a location one tenth the original number. You will need to begin using normal array operators if you want your code to work properly.
The second problem you have is the following:
You declare n as a array of 10 integers of type and with int.
int n[10];
Then in your for loop you try to do this:
n > 0;
This is an invalid operation as n wil decay into a pointer and as such the address of your array is compared to 0. This will always evaluate as TRUE!
A good way to convert a integer to a string (char array) is this answer.
In your sitaution that would be
int yourToBeConvertedNumber;
char str[INT_MAX]; // or any other reasonable upper bound you have set for the input data.
snprintf(str, sizeof(str), "%d", yourToBeConvertedNumber);
Generally speaking, to convert an integer to a string, you can use the sprintf function. It should be available in newliband even newlib-nano standard C libraries.
However my guess here is that you have an array of integers where each element is a number between 0 and 9 ?
If this is true you have several issues: you seem to handle the variable n like an integer and not an address. Also your string should be one element longer and composed of chars.
You may do something like this:
char a[11];
for(i=0;i<10;i++)
{
a[i]=n[i]%10 +'0';
}
a[11]='\0';

Is there a way to receive all kinds of data types?

I have been asked to write a code that receives a type of data without being specific about what type (example, int, float, double ect..) and its certainly a number.
The code is simple, find a number in the array and return it's location in the array.
This is the code i wrote:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int findselectnum(int num, int array[], int size)
{
int i = 0;
for (i = 0; i <= size; i++)
{
if (num == array[i])
return i;
}
return EOF;
}
int main()
{
int array[] = { 1, 3, 5, 10, 88, 21, 100, 77, 0, 11, 2 }, num = 0, result = 0, size = 0;
printf("Enter a number you wish to find\n");
scanf("%d", &num);
size = sizeof(array);
result = findselectnum(num, array, size);
if (result != EOF)
printf("The number %d is in array[%d]\n", num, result);
else
printf("The number does not exists on the array");
}
As you can see, i can only use the int type, so numbers that are float, or double, wont get the same result.
So how can i use all types of data? Is there some kind of a structure for that?
Thanks in advance.
You can use a void* type instead of the int[] type.
It is the type used by the memcpy() function so that it can copy any type of data.
Then you have to cast your void* argument to compare it with the variable of the type you want.
Personally, I wouldn't use C to perform this kind of task.
C++ is maybe a bit more appropriate since it natively handles such mechanisms (templates):
https://en.wikipedia.org/wiki/Template_(C%2B%2B)
I have been asked to write a code that receives a type of data without being specific about what type (example, int, float, double ect..) and its certainly a number.
So how can i use all types of data?
You can't. More specifically, the CPU itself can't. To compare 2 numbers, the CPU has to know what size the numbers are, if the numbers are integer or floating type, and (if it's not just comparing for equality) if the number is signed or not.
There are 3 ways around this:
a) Code duplication (including templates in C++ where the compiler automatically generates N versions of the code for N types, and using macros in C to do similar).
b) Only support the largest type (e.g. maybe double in C) and convert everything to the largest type so that you only need one function for one type.
c) Abuse variable arguments and have run-time branches based on a "what type is it" argument (and increased risk of programmer mistakes); like int findselectnum(char *data_type, int size, ...). This mostly ends up being code duplication in disguise (e.g. you'd duplicate the loop in each case of a switch(data_type)).
Depending on the actual situation; I'd use a mixture of the first 2 options - e.g. find out why the software has been so poorly designed that it needs to do the same work on multiple different types, then try to change the design so it only needs to care about a small number of different types; then have a small number of different functions for the types that are "unavoidably necessary" (e.g. maybe an int findselectnum_int(int num, int array[], int size) and a separate int findselectnum_double(double num, double array[], int size); with nothing for float or short or whatever because they were avoidable).

Translate string to number

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 separate int, 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 consider 5x as legal decimal number. strtol also returns a pointer to the location after the parsed decimal number, but it relies too much on checking err for my taste.
The fact that strtol uses long integers shouldn't be an issue. If the input doesn't fit into an int, return INT_MAX or INT_MIN or issue an error.
You can also easily write a wrapper function around sscanf or strtol 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.
Something like this should do your job:
#include <stdio.h>
#include <string.h>
struct StringToLongLookUp {
char *str;
char *num;
};
struct StringToLongLookUp table[] =
{
{ "q" , "3" },
{ "five" , "5" },
{ "negfive" , "-5" },
{ "random294", "28" }
};
int translate_from_symbol(char **str)
{
int i;
for(i = 0; i < (sizeof(table) / sizeof(struct StringToLongLookUp)); i++)
{
if(strcmp(*str, table[i].str) == 0)
{
*str = table[i].num;
return 1; // TRUE
}
}
return 0; // FALSE
}
int main()
{
char buf[100];
char *in = buf;
char *out;
int val;
scanf("%s", in);
translate_from_symbol(&in);
val = strtol(in, &out, 10);
if (in != out)
{
printf("\nValue = %d\n", val);
}
else
{
printf("\nValue Invalid\n");
}
}
Of course, you get a long, but converting that to int shouldn't be an issue as mentioned above.

If I have to represent integers and char's in a single array, what would be an acceptable way to do this in C?

Can I declare an int array, then initialize it with chars? I'm trying to print out the state of a game after each move, therefore initially the array will be full of chars, then each move an entry will be updated to an int.
I think the answer is yes, this is permitted and will work because an int is 32 bits and a char is 8 bits. I suppose that each of the chars will be offset by 24 bits in memory from each other, since the address of the n+1'th position in the array will be n+32 bits and a char will only make use of the first 8.
It's not a homework question, just something that came up while I was working on homework. Maybe I'm completely wrong and it won't even compile the way I've set everything up?
EDIT: I don't have to represent them in a single array, as per the title of this post. I just couldn't think of an easier way to do it.
You can also make an array of unions, where each element is a union of either char or int. That way you can avoid having to do some type-casting to treat one as the other and you don't need to worry about the sizes of things.
int and char are numeric types and char is guaranteed smaller than int (therefore supplying a char where an int is expected is safe), so in a nutshell yes you can do that.
Yes it would work, because a char is implicitly convertible to an int.
"I think the answer is yes, this is permitted and will work because an int is 32 bits and a char is 8 bits." this is wrong, an int is not always 32 bits. Also, sizeof(char) is 1, but not necessarily 8 bits.
As explained, char is an int compatible type.
From your explanation, you might initially start with an array of int who's values are char, Then as the game progresses, the char values will no longer be relevant, and become int values. Yes?
IMHO the problem is not putting char into an int, that works and is built into the language.
IMHO using a union to allow the same piece of space to be used to store either type, helps but is not important. Unless you are using an amazingly small microcontroller, the saving in space is not likely relevant.
I can understand why you might want to make it easy to write out the board, but I think that is a tiny part of writing a game, and it is best to keep things simple for the rest of the game, rather than focus on the first few lines of code.
Let's think about the program; consider how to print the board.
At the start it could be:
for (int i=0; i<states; ++i) {
printf("%c ", game_state[i]);
}
Then as the game progresses, some of those values will be int.
The issue to consider is "which format is needed to print the value in the 'cell'?".
The %c format prints a single char.
I presume you would like to see the int values printed differently from ordinary printed characters? For example, you want to see the int values as integers, i.e. strings of decimal (or hex) digits? That needs a '%d' format.
On my Mac I did this:
#include <stdio.h>
#define MAX_STATE (90)
int main (int argc, const char * argv[]) {
int game_state[MAX_STATE];
int state;
int states;
for (states=0; states<MAX_STATE; ++states) {
game_state[states] = states+256+32;
}
for (int i=0; i<states; ++i) {
printf("%c ", game_state[i]);
}
return 0;
}
The expression states+256+32 guarantees the output character codes are not ASCII, or even ISO-8859-1 and they are not control codes. They are just integers. The output is:
! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? # A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y
I think you'd like the original character to be printed (no data conversion) when the value is the initial character (%c format), but you do want to see data conversion, from a binary number to a string of digit-characters (%d or a relative format). Yes?
So how would the program tell which is which?
You could ensure the int values are not characters (as my program did). Typically, this become a pain, because you are restricted on values, and end up using funny expressions everywhere else just to make that one job easier.
I think it is easier to use a flag which says "the value is still a char" or "the value is an int"
The small saving of space from using a union is rarely worth while, and their are advantages to having the initial state and the current move available.
So I think you end up with something like:
#include <stdio.h>
#define MAX_STATE (90)
int main (int argc, const char * argv[]) {
struct GAME { int cell_state; int move; char start_value } game_state[MAX_STATE];
enum CELL_STATE_ENUM { start_cell, move_cell };
int state;
int states;
for (states=0; (state=getchar())!= EOF && states<MAX_STATE; ++states) {
game_state[states].start_value = state;
game_state[states].cell_state = start_cell;
}
// should be some error checking ...
// ... make some moves ... this is nonsense but shows an idea
for (int i=0; i<states; ++i ) {
if (can_make_move(i)) {
game_state[states].cell_state = move_cell;
game_state[states].move = new_move(i);
}
}
// print the board
for (int i=0; i<states; ++i) {
if (game_state[i].cell_state == start_cell) {
printf("'%c' ", game_state[i].start_value);
} else if (game_state[i].cell_state == move_cell) {
printf("%d ", game_state[i].move);
} else {
fprintf(stderr, "Error, the state of the cell is broken ...\n");
}
}
return 0;
}
The move can be any convenient value, there is nothing to complicate the rest of the program.
Your intent can be made a little more clear my using int8_t or uint8_t from the stdint.h header. This way you say "I'm using a eight bit integer, and I intend for it to be a number."
It's possible and very simple. Here is an example:
int main()
{
// int array initialized with chars
int arr[5] = {'A', 'B', 'C', 'D', 'E'};
int i; // loop counter
for (i = 0; i < 5; i++) {
printf("Element %d id %d/%c\n", i, arr[i], arr[i]);
}
return 0;
}
The output is:
Element 0 is 65/A
Element 1 is 66/B
Element 2 is 67/C
Element 3 is 68/D
Element 4 is 69/E

invalid conversion from 'char' to 'int* in C

I have the following arrays:
int A[] = {0,1,1,1,1, 1,0,1,0,0, 0,1,1,1,1};
int B[] = {1,1,1,1,1, 1,0,1,0,1, 0,1,0,1,0};
int C[] = {0,1,1,1,0, 1,0,0,0,1, 1,0,0,0,1};
//etc... for all letters of the alphabet
And a function that prints the letters on a 5x3 LED matrix:
void printLetter(int letter[])
I have a string of letters:
char word[] = "STACKOVERFLOW";
and I want to pass each character of the string to the printLetter function.
I tried:
int n = sizeof(word);
for (int i = 0; i < n-1; i++) {
printLetter(word[i]);
}
But I get the following error: invalid conversion from 'char' to 'int*'
What should i be doing?
Thanks!!
Behind the parameter type error there is a deeper issue: you lack the mapping between a char and the corresponding int[].
Redefining printLetter as
void printLetter(char letter)
satisfies the compiler, but doesn't solve your problem per se. Whether inside or outside printLetter, you need to get the corresponding int[] for a given char.
A simple brute-force way to achieve this would be to use a switch, but a better way is to use a second array, i.e. something like this:
void printLetter(char letter) {
static int* charToMatrix[] = { A, B, C, ... };
int* matrixToPrint = charToMatrix[letter - 'A'];
// print the matrix
}
Note that this is an example - I don't have access to a C compiler right now, so I can't guarantee it works straight away, but hopefully it illustrates the point well enough. It also lacks bounds checking, so it accesses memory in strange random places, possibly resulting in a crash, if you attempt to print an "unknown" character.
This solution is supposed to work for the uppercase letters; if you need to print lowercase letters or other characters as well, you might prefer going with an array of 256 elements, where only the elements at indexes corresponding to the "known" matrices are filled, and the rest is set to NULL.
You cannot so easly transform the 'a' from "stackoverflow" to the A - the array of ints. You can define all the arrays that represent a letter in one single letter and get them by the convertion of your letter to int.
What you need to do is convert from a character to one of your arrays. So when you have the letter 'A', you'll want to use array A. The easiest way to do this is via lookup table.
int *lookup[256]; // assuming ASCII
memset(lookup, 0, sizeof(lookup));
lookup['A'] = A;
lookup['B'] = B;
...
Then when you have a character, you can get the proper array:
void printletter(char c);
{
int *data = lookup((unsigned char)c);
// In case you get a letter that you don't know how to display
if (data != NULL)
{
// display with data
}
}
Instead of building up your array at runtime, you can also build up your array at compile time although it will be a bit harder as you will need to manually put in NULL pointers.
int *lookup[256] = {
NULL, // you need a total of 65 NULL's
NULL,
...
A, // so this is at the correct position
B,
C,
...
};
The function is declared as void printLetter(int letter[]), which means it takes a pointer to an array of ints. On the other hand, word is an array of chars, and word[i] is a char, which is not at all the right type. If printLetter() is really just supposed to print a single character, you should change its argument to be a char.
void printLetter(int letter[])
should be
void printLetter(char letter)
Because: word is a char[] word[i] is a character.

Resources