Home > Software design >  How can I convert char* to char[] in C and then add it in an array without problem?
How can I convert char* to char[] in C and then add it in an array without problem?

Time:10-19

I know some similar questions already exists but they did not help me in my case.

What I need to do is creating a table symbol for a compiler project using flex. Basically, I get a char* (a new identifier to add to the table symbol) that is then placed in a char[1000] array, that is my table symbol.

Everything works fine until I try to print my table symbol (called symbArray): when I'm trying to print symbArray[4] for ex., it also prints me symbArray[5] and symbArray[6], ... At this point, if you have any solutions, I'll take it.

What I tried to do to solve it is to use strcpy(intermediaryVariable, yytext) to convert my char* (called yytext) into a char[100] (intermediaryVariable). But this does not seems to work because now, symbArray[4] = symbArray[5] = symbArray[6] (see details later).

Here is my function that should add the symbol to the table after that I tried to solve the problem with strcpy():

void addSymbole(char text[100], int index) {
    // findSymboleArray is a function to verify if our identifier does not already exist
    // symbArray is the symbole array declare on a global scope as char* symbArray[1000];
    if (findSymboleArray(text) == -1 && symbArray[index] == NULL) {
        char textToCopy[100];
        strcpy(textToCopy, text);
        symbArray[index] = textToCopy;
        printf("%s goes to index %i.\n", text, index);
    }
}

Here is how I call my function addSymbole()

// newChar is the intermediaryVariable declared on a global scope as char newChar[100];
// symbArrayLength is declared as int symbArrayLength = 0; on a global scope too

strcpy(newChar, yytext);
addSymbole(newChar, symbArrayLength);
symbArrayLength  = 1;

And here is how I print the content of my symbol table:

void printSymboleArray() {
    for(int i = 0; i < 1000; i  ) {
        if(symbArray[i] == NULL) {
            // so that the for-loop can be stopped
            i = 1000;
        } else {
            printf("value of element at index %i: %s.\n", i, symbArray[i]);
        }
    }
}

Here is a part of result that I can get when I print the symbol table:

value of element at index 0: main.
value of element at index 1: char.
value of element at index 2: int.
value of element at index 3: float.
value of element at index 4: A878U_GH.
value of element at index 5: A878U_GH.
value of element at index 6: A878U_GH.
value of element at index 7: A878U_GH.

with symbols that are:

coucou
bogoss13_
BAD_CHAR
A878U_GHJ // note that in the result, the J is not printed and is sometimes replaced by random characters like '3' or 'c' for example when retesting the program

so that the expected result is:

value of element at index 0: main.
value of element at index 1: char.
value of element at index 2: int.
value of element at index 3: float.
value of element at index 4: coucou.
value of element at index 5: bogoss13_.
value of element at index 6: BAD_CHAR.
value of element at index 7: A878U_GHJ.

Please note that main, char, float and int are initialized with this function:

void initializeSymboleArray() {
    // reserved names
    symbArray[0] = "main";
    symbArray[1] = "char";
    symbArray[2] = "int";
    symbArray[3] = "float";
    symbArrayLength = 4;
}

To sum up, I would like to know how to properly convert a char* into a char[] so that such a problem that I get (all the elements in the indexes are equal to the last identifier detected) does not appear. If there is another solution than converting a char* into a char[], I would be glad to hear it.

I hope this isn't too much confusing and I apologize in advance for the lack of clarity. Thank you for reading me.

CodePudding user response:

printf("%s", str) will print byte sequence pointed to by str until it reach a null ("\0") symbol. So my educated guess is, your original problem was because you did not null-terminated your strings. The strcpy function will automatically null terminate the result (as stated in the manual).

Your new solution has a memory management issue. In addSymbole function you define a buffer called textToCopy then use strcpy to place the string in that buffer. Afterwards you proceed and add a pointer to this buffer in your table (symbArray[index] = textToCopy;). Because this buffer is allocated on the stack, it would be poped (removed) when the function returns (the buffer gets out of scope). So the pointer is no longer valid.

I guess the reason why you see all the indexes have the same value is because the same memory is reused when you again call the addSymbole function. You can verify this by checking the memory address (print("%p\n", &symbArray[i])).

You can use malloc for reserving some memory on the heap. When you allocate memory from heap it would stay there until you explicitly free that (using free function).

If I want to modify your code I would rewrite your addSymbole function like shown below.

void addSymbole(char text[100], int index) {
    // findSymboleArray is a function to verify if our identifier does not already exist
    // symbArray is the symbole array declare on a global scope as char* symbArray[1000];
    if (findSymboleArray(text) == -1 && symbArray[index] == NULL) {
        char *textToCopy = malloc(100); // allocate a buffer with enough size.
        if (!textToCopy) { // If malloc failed to reserve memory it returns NULL
            // Hanlde the error here
        }
        strcpy(textToCopy, text);
        symbArray[index] = textToCopy;
        printf("%s goes to index %i.\n", text, index);
    }
}

I also want to warn you about the line you are copying yytext to a buffer. strcpy copies characters of the string until reaching "\0".

strcpy(newChar, yytext);

If yytext is not null-terminated then it would cause issues. You could at least use strncpy so that your newChar don't overflow.

char *strncpy(char *dest, const char *src, size_t n);

CodePudding user response:

UB (undefined behaviour). You assign symbArray[index] = textToCopy; pointer with address of the automatic variable textToCopy and this variable stops to exists when the function returns.

char *addSymbole(const char *text, const size_t index) 
{
    if (findSymboleArray(text) == -1 && symbArray[index] == NULL) 
    {
        symbArray[index] = malloc(strlen(text)   1);
        if(symbArray[index])
        {
            strcpy(symbArray[index], text);
        }      
        printf("%s goes to index %i.\n", text, index);
    }
    return symbArray[index];
}
  • Related