Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I store lots of strings with different lengths in the same char array without specifying its size?

Tags:

c

string

I'll implement a dictionary that is basically an array of structures.

Here's the structure:

struct WORD {
    char* word;
    struct WORD* next;
};

And the array that'll help me reach them:

struct WORD* dictionary[26];

The number 26 stands for 26 letters of the alphabet. We need a linked-list for every single letter, bu that is irrelevant now.

The problem is, I need the char* variable in the structure to be able to store words of different lengths. If I leave it as char*, fscanf fuction doesn't work while reading the words from the file onto the structure. If I make it char word[10] for example, I'd be wasting space for shorter words.

What am I supposed to do?


2 Answers

If I leave it as char*, fscanf function doesn't work

You need to leave it as char*, and dynamically allocate the string.

Start with a buffer of some large size, say, 1024. Read the word into that buffer using fscanf with a limit. After that, copy the buffer into a dynamically allocated space for the word:

char buf[1024];
WORD *head = NULL;
while (fscanf(f, "%1023s", buf) == 1) {
    size_t len = strlen(buf);
    if (!len) continue; // Ignore empty words
    WORD *node = malloc(sizeof(WORD));
    // Copy the word
    node->word = malloc(len+1); // One for '\0' terminator
    strcpy(node->word, buf);
    // Attach as the new head
    node->next = head;
    head = node;
}

Note: You can score some points for style with flexible array member: make word an array with no size, and allocate it together with the node itself, like this:

struct WORD {
    struct WORD* next;
    char word[];
};
...
char buf[1024];
WORD *head = NULL;
while (fscanf(f, "%1023s", buf) == 1) {
    size_t len = strlen(buf);
    if (!len) continue; // Ignore empty words
    WORD *node = malloc(sizeof(WORD)+len+1);
    // Copy the word
    strcpy(node->word, buf);
    // Attach as the new head
    node->next = head;
    head = node;
}

Now you have a single allocation instead of two.

like image 151
Sergey Kalinichenko Avatar answered Sep 10 '25 10:09

Sergey Kalinichenko


You can use a temporary buffer with a fixed length and store the word there, so that you can figure out the length. Once you figured out the length, use malloc to allocate the exact number of bytes to the word pointer, and copy it. something like this:

char tempBuffer[20 + 1] = {0}; //Null terminates the string
fsanf(file, "%s", tempBuffer); // read the string
word = (char*) malloc(sizeof(char) * strlen(tempBuffer));  //allocate memory
strcpy(word, (char*) tempBuffer); //copy the string
like image 24
erick orozco Avatar answered Sep 10 '25 11:09

erick orozco