2

I am currently having difficulty reading words separated by spaces line by line from stdin. I am trying to read words line by line, and just print them, from accessing an array of strings.

If I am trying to read this sentence:

Enter words: Hi there, how was your day sir?

Then I just want to print the sentence underneath, like this:

Your sentence: Hi there, how was your day sir?

This is what my code is so far:

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

int
main(int argc, char *argv[]) {
    char *word = NULL;
    char **words = NULL;
    int word_size = 1, word_len = 0, word_count = 0;
    int words_size = 1, i, ch;

    word = (char*)malloc(word_size *sizeof(char));

    words = (char **) malloc(words_size*sizeof(char*));

    printf("Enter words:\n");
    while ((ch = getchar()) != EOF) {
        if (isalpha(ch)) {
            word_size++;
            word = realloc(word, word_size+1);
            word[word_len++] = ch;
            word[word_len] = '\0';
        }

        if (isspace(ch)) {
            words_size++;
            words = realloc(words, words_size+1);

            words[word_count] = malloc(strlen(word)+1);

            words[word_count++] = word;
            word_len = 0;
            word_size = 1;
        }

        if (ch == '\n') {

            printf("Your sentence is:\n");
            for (i = 0; i < word_count; i++) {
                printf("%s ", words[i]);
            }
            printf("\n");

            word_len = 0;
            word_size = 1;
            words_size = 1;
        }

    }
    return 0;
}

I am just not sure why this doesn't work, and why it prints the last word. I know there is a lot of mallocing and reallocing, I am just trying to get better at using them.

Any help would be appreciated

RoadRunner
  • 25,803
  • 6
  • 42
  • 75
  • [Don't cast return of malloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Garf365 Oct 10 '16 at 13:19
  • 1
    You should use `fgets` to store the whole sentence and then compute it. – LPs Oct 10 '16 at 13:20
  • To find where your code goes wrong, use a debugger. It's a really useful tools to find but _but_ also to learn (which is your main goal here). – Garf365 Oct 10 '16 at 13:23
  • 1
    probably this solve: `words[word_count++] = word;` --> `strcpy(words[word_count++], word);` – LPs Oct 10 '16 at 13:26

1 Answers1

1

You are failing assigning the word to your char **.

Using

words[word_count++] = word;

You are assigning address of local variable word to pointer words[word_count] That gave you, at the end of computation, all words with last stored word into word c-string.

You prepare space for the word c-string using

words[word_count] = malloc(strlen(word)+1);

So what you have to do is to copy the content of word c-string into allocaded space

strcpy(words[word_count++], word);

Otherwise you are leaking memory allocated for the word.

Side notes:

  1. malloc and realloc can fail, so check its return value != NULL
  2. You must free mallocated memory. On "hi-level" OS memory is freed automatically at the end of execution, but is not granted on all platforms/OS

EDIT

Another problem is that you are reallocating the wrong size for your char** You shoud use

words_size++;
words = realloc(words, sizeof(*words)*words_size);

That is size of char * for the new number of words to store

You can also avoid to use strlen, you have the length of word stored into word_len variable

words[word_count] = malloc(word_len+1);

Last thing, before to store a new word you should check that at least alpha char was found. This avoid the output of first space char of your test sting:

if ((isspace(ch)) && (word_size>1))
LPs
  • 16,045
  • 8
  • 30
  • 61
  • @You're welcome. I updated my answer with another issue. – LPs Oct 10 '16 at 13:57
  • 1
    You have the word counter, `word_count`. So when it exceed the required number you can skip all other chars until `\n` – LPs Oct 11 '16 at 11:54
  • 1
    If you are talking about a different implementation then the posted one with `realloc`, and using an array of pointers, you can simply check `sizeof(array)/sizeof(array[0])` to retrieve the number of element. So you can check that your word counter is `<`. – LPs Oct 11 '16 at 12:11
  • Too much ;) 20 years more or less. – LPs Oct 11 '16 at 13:06