0

Firstly, I apologize if this is a duplicate of some other question. I have spent several hours now playing around and attempting to figure out my problem. I may not have been searching with the correct terms as I am a novice with C.


I need to split up text using strtok and store each value into a struct and store that struct in an array. I need the array's space to be dynamically allocated memory using malloc / realloc.

The problem I am facing is that the last value I set is overwriting all previous values in my array. I am completely lost at this point. I have included a short example of my problem below.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef struct textBit
{
    int textID;
    char** theWord;
    int randInt;
} TextBit;

void printTextBit(TextBit bit);

int main()
{
    int counter = 0;
    char myText[] = "hello this is a bunch of text i am just writing for an example to test something";
    TextBit** textBits;
    textBits = malloc(sizeof(TextBit) * 16);

    char* tok = strtok(myText, " ");
    while(tok != NULL)
    {
        TextBit temp;
        temp.textID = counter;
        temp.randInt = 25;

        char* tempWord = malloc(sizeof(char) * strlen(tok));
        strcpy(tempWord, tok);
        temp.theWord = &tempWord;

        printf("%d %s\n", counter, tok);
        //printTextBit(temp);

        textBits[counter] = &temp;

        counter++;
        tok = strtok(NULL, " ");
    }

    for(int i = 0; i < counter; i++)
    {
        printTextBit(*textBits[i]);
    }
}

void printTextBit(TextBit bit)
{
    printf("TextBit: %s (#%d) - %d\n", *bit.theWord, bit.textID, bit.randInt);
}

This code outputs:

0 hello
1 this
2 is
3 a
4 bunch
5 of
6 text
7 i
8 am
9 just
10 writing
11 for
12 an
13 example
14 to
15 test
16 something
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
TextBit: something (#16) - 25
MarkA2049
  • 47
  • 1
  • 1
  • 4
  • Possible duplicate of [returning address of local variable](https://stackoverflow.com/questions/11876772/returning-address-of-local-variable) – Phil M Dec 12 '18 at 01:46
  • regarding: `char* tempWord = malloc(sizeof(char) * strlen(tok));` 1) the expression: `sizeof( char )` is defined in the C standard as 1. Multiplying anything by 1 has no effect. Suggest removing that expression. 2) always check (!=NULL) the returned value to assure the operation was successful – user3629249 Dec 12 '18 at 02:52

2 Answers2

1

I think you're pretty close. The big problem is that the value of temp and tempword aren't what you want to assign. Most likely they won't change, but their contents will. Also, you're using double pointers for your variables when you shouldn't need to do that. I would change your code to be like this:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef struct textBit
{
    int textID;
    char* theWord;
    int randInt;
} TextBit;

void printTextBit(TextBit bit);

int main()
{
    int counter = 0;
    char myText[] = "hello this is a bunch of text i am just writing for an example to test something";
    TextBit* textBits;
    textBits = malloc(sizeof(TextBit) * 16);

    char* tok = strtok(myText, " ");
    while(tok != NULL)
    {
        TextBit *temp;
        temp = &textBits[counter];
        temp->textID = counter;
        temp->randInt = 25;
        temp->theWord = strdup(tok);

        printf("%d %s\n", counter, tok);
        //printTextBit(temp);

        counter++;
        tok = strtok(NULL, " ");
    }

    for(int i = 0; i < counter; i++) {
        printTextBit(textBits[i]);
    }
}

void printTextBit(TextBit bit)
{
    printf("TextBit: %s (#%d) - %d\n", bit.theWord, bit.textID, bit.randInt);
}

Using strdup will copy the word over to your struct. You could use malloc and strcpy separately, but strdup does both in one line. Also, this code uses temp to point into the textBits array.

bruceg
  • 2,433
  • 1
  • 22
  • 29
1

the main problem is all the entries are using the same address as tok points to. Suggest when adding a word to the array, to use: strdup() (and of course, check the result for !=NULL to assure the operation was successful) then assigned that returned value to the array

user3629249
  • 16,402
  • 1
  • 16
  • 17