0

I'm building a word counter program. To achieve this, I was thinking about saving the string the user inputted, and using strtok() to split the sentence with space as the delimiter. But first I want to allocate enough memory for each word. Let's say the sentence is "Hello World". I've already dynamically allocated memory for the string itself. Now I want to split Hello World into 2 strings, "Hello" and "World". My goal is to allocate enough memory so that there's not too much empty space but I also don't want to allocate too little space. Here is my code so far:

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

char *strmalloc(char **string);
char *user_input = NULL;
char *word_array[];

int main(void) {
    printf("Enter a sentence to find out the number of words: ");
    user_input = strmalloc(&user_input);

    return 0;
}

char *strmalloc(char **string) {
    char *tmp = NULL;
    size_t size = 0, index = 0;
    int ch;

    while ((ch = getchar()) != '\n' && ch != EOF) {
        if (size <= index) {
            size += 1;
            tmp = realloc(*string, size);
            if (!tmp) {
                free(*string);
                string = NULL;
                break;
            }
            *string = tmp;
        }
        (*string)[index++] = ch;
    }
    return *string;
}

How would I go about doing this? Should I do the splitting first or allocate the space required for the array first?

3
  • If you will just count words you don't need to allocate memory for the string at all - just count the number of non consecutive word separator characters Commented Jan 9, 2021 at 19:15
  • I forgot to mention that I would like to practice dynamic memory allocation so I would like to do it this way. However I'm stuck so that's why I'm asking the question here on stackoverflow. I hear what you're saying though Commented Jan 9, 2021 at 19:44
  • This has already been answered here stackoverflow.com/questions/12579719/… Please do some research before posting questions and try to make them more specific Commented Jan 10, 2021 at 9:27

1 Answer 1

1

You can count words without splitting the sentence, here is an example :

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

// Change this to change the separator characters
static inline char isSeparator(char ch) { return isspace(ch) || ispunct(ch); }

char * jumpSeparator(char *string) {
    while(string[0] && isSeparator(string[0])) string++;
    return string;
}
    
char * findEndOfWord(char *string) {
    while (string[0] && !isSeparator(string[0])) string++;
    return string;
}

int countWords(char *string) {
    char * ptr = jumpSeparator(string);
    if (strlen(ptr) == 0) return 0;
    int count = 1;
    while((ptr = findEndOfWord(ptr)) && ptr[0]) {
        ptr = jumpSeparator(ptr);
        if (!ptr) break;
        count++;
    }
    return count;
}
  
int main() {
    char * sentence = "This    is,a function... to||count words";
    int count = countWords(sentence);
    printf("%d\n", count); //====> 7
}

EDIT : Reusing the same functions here is another example that allocates substrings dynamically :

int main() {
    char * sentence  = "This    is,a function... to||split words";
    int count        = countWords(sentence); 
    char * ptr       = sentence, *start, *end;
    char ** substrings = malloc(count * sizeof(char *));
    int i=0;
    while((ptr = jumpSeparator(ptr)) && ptr[0]) {
        start           = ptr;
        ptr             = findEndOfWord(ptr);
        end             = ptr;
        int len          = end-start;
        char * newString = malloc(len + 1);
        memcpy(newString, start, len);
        newString[len]   = 0;
        substrings[i++]  = newString;
    }
    // Prints the result
    for(int i=0; i<count; i++) printf("%s\n", substrings[i]);

    // Frees the allocated memory
    for(int i=0; i<count; i++) free(substrings[i]);
    free(substrings);
    return 0;
}

Output :

This
is
a
function
to
split
words
Sign up to request clarification or add additional context in comments.

2 Comments

I know that I can do it this way but I would like to practice dynamic memory allocation. Can you please show me how to dynamically allocate memory for an array of pointers to char please?
The code can use a bit of work to add different word separators like tabs, semicolons etc and ignore consecutive word separators - for example "word1<space>,<space><space>word2" will return 4 words instead of 2. (I used <space> for " " because the comments will not let you add multiple consecutive spaces

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.