Thread: entering characters into a string pointer

  1. #1
    Registered User
    Join Date
    Jul 2012
    Location
    Australia
    Posts
    242

    entering characters into a string pointer

    Hi all.

    1. The debugger shows that the characters are entered into the word pointer, and when a punctuation or space character is encountered, I terminate the string with a '\0'. But when I use puts to print the string, garbage is printed. Why is this?

    2. Also, if I don't allocate memory for word the compiler gives a warning about it being used uninitialised. But I didn't allocate memory for the array of pointers(words), and the compiler didn't give any warnings. Whats the difference between a pointer and an array of pointers?

    Thanks in advance.

    Code:
    // wordcount.c - count words.
    
    #include <stdio.h>
    #include <ctype.h>
    #include <stdlib.h>
    
    #define WORDS_MAX 20
    #define WORD_SIZE 50
    
    int main( void )
    {
        char *string = "How now brown cow. A cow has four brown legs.";
        char *words[WORDS_MAX];
        char *word;
        int ch, ctr, string_ctr = 0, word_ctr = 0, word_buffer = 0;
    
        while((ch = string[string_ctr]) != '\0')
        {
            word = malloc(WORD_SIZE * sizeof(char));
            if((ispunct(ch) == 0) && (isspace(ch) == 0)) // ch is not a punctuation and not a white space
            {
                word[word_buffer] = ch;
                word_buffer++;
                string_ctr++;
            }
            else
            {
                word[word_buffer] = '\0';
                puts(word);
                words[word_ctr] = word;
                string_ctr++;
                word_ctr++;
                word_buffer = 0;
                free(word);
            }
        }
        printf("\n");
        for(ctr = 0; ctr < word_ctr; ctr++)
            puts((words[ctr]));
        return 0;
    }
    IDE: Code::Blocks | Compiler Suite for Windows: TDM-GCC (MingW, gdb)

  2. #2
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    Well, C doesn't have string pointers or word pointers. Your program's called wordcount, so if your goal is to count words it's doing far too much work. But you seem to be tokenising a string and storing the tokens in an array of pointers to char, so if that's your goal, you could take a look at a post I wrote ( Implementing argv/argc in C ), which is fairly relevant considering the design decisions you've chosen.

    Whats the difference between a pointer and an array of pointers?
    Well, what's the difference between a pointer and an array? A pointer is a scalar type that stores an address of an object, and an array is an aggregate type which stores a list of objects. For your purposes, it's an aggregate type that stores a list of twenty pointers to char.

  3. #3
    Registered User
    Join Date
    Jul 2012
    Location
    Australia
    Posts
    242
    Thanks Barney. I've figured that the problem was in the location of the malloc. That is fixed, but I can't figure out why I am still getting garbage printed in the for loop.

    Code:
    // wordcount.c - count words.
    
    #include <stdio.h>
    #include <ctype.h>
    #include <stdlib.h>
    
    #define WORDS_MAX 20
    #define WORD_SIZE 50
    
    int main( void )
    {
        char *string = "How now brown cow. A cow has four brown legs.";
        char *words[WORDS_MAX];
        char *word;
        int ch, ctr, string_ctr = 0, word_ctr = 0, word_buffer = 0;
    
        if((word = malloc(WORD_SIZE * sizeof(char))) == NULL)
            perror("Error allocating memmory");
        while((ch = string[string_ctr]) != '\0')
        {
            if((ispunct(ch) == 0) && (isspace(ch) == 0)) // ch is not a punctuation and not a white space
            {
                word[word_buffer] = ch;
                word_buffer++;
                string_ctr++;
            }
            else
            {
                word[word_buffer] = '\0';
                words[word_ctr] = word;
                printf("%s ", words[word_ctr]);
                string_ctr++;
                word_ctr++;
                word_buffer = 0;
                free(word);
                if((word = malloc(WORD_SIZE * sizeof(char))) == NULL)
                    perror("Error allocating memmory");
            }
        }
        free(word);
        printf("\n");
        for(ctr = 0; ctr < word_ctr; ctr++)
            printf("%s ", words[ctr]);
        return 0;
    }
    IDE: Code::Blocks | Compiler Suite for Windows: TDM-GCC (MingW, gdb)

  4. #4
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    Why are you calling malloc at all? Without it you could easily get your code down to half the size it currently is, running in less memory, performing slightly faster, and easier to read and understand. It offers no benefits in this situation since you know the size of the string in advance, and can allocate mutable storage for it easily like so:

    char string[] = "How now brown cow. A cow has four brown legs.";

  5. #5
    Registered User
    Join Date
    Jul 2012
    Location
    Australia
    Posts
    242
    Yes, you are correct, this program can be written much better. But for learning purposes, I must persist in asking questions that are based on the unique problems that are inherent in the current piece of code.

    In the context of the C language, why does "printf("%s ", words[word_ctr]);" in the else() loop not print garbage, but the same code prints garbage in the for() loop? Has the values of the array of pointers changed when exiting the else() loop? If so, what has caused this change. I am confused about this strange behaviour, and the debugger can't give me an explanation in plain English.
    IDE: Code::Blocks | Compiler Suite for Windows: TDM-GCC (MingW, gdb)

  6. #6
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by cfanatic View Post
    In the context of the C language, why does "printf("%s ", words[word_ctr]);" in the else() loop not print garbage, but the same code prints garbage in the for() loop?
    The problem here is that by the time you get down to your for loop, you've already freed all of the pointers you put into your words array. Try changing it like this

    Code:
    if((word = malloc(WORD_SIZE * sizeof(char))) == NULL)
            perror("Error allocating memmory");
        while((ch = string[string_ctr]) != '\0')
        {
            if((ispunct(ch) == 0) && (isspace(ch) == 0)) // ch is not a punctuation and not a white space
            {
                word[word_buffer] = ch;
                word_buffer++;
            }
            else
            {
                word[word_buffer] = '\0';
                words[word_ctr] = word;
                printf("word: \"%s\"\n", words[word_ctr]);
                word_ctr++;
                word_buffer = 0;
                if((word = malloc(WORD_SIZE * sizeof(char))) == NULL)
                    perror("Error allocating memmory");
            }
            string_ctr++;
        }
        free(word);
        printf("\n");
        printf("printing all words: ");
        for(ctr = 0; ctr < word_ctr; ctr++)
            printf("%s ", words[ctr]);
        printf("\n");
        
        // free words
        for(ctr = 0; ctr < word_ctr; ctr++)
            free(words[ctr]);

  7. #7
    Registered User
    Join Date
    Jul 2012
    Location
    Australia
    Posts
    242
    Thanks heaps. Much appreciated.

    EDIT:

    Code:
    words[word_ctr] = word;
    If I assign the word pointer to the array of pointers, and then free the word pointer, does that mean the corresponding value in the array of pointers is now garbage? I had thought that once the assignment been made, the value would remain permanent in the array of pointers, and I could then free or change the value of the word pointer without any effect on the array of pointers.

    Quote Originally Posted by c99tutorial View Post
    The problem here is that by the time you get down to your for loop, you've already freed all of the pointers you put into your words array. Try changing it like this

    Code:
    if((word = malloc(WORD_SIZE * sizeof(char))) == NULL)
            perror("Error allocating memmory");
        while((ch = string[string_ctr]) != '\0')
        {
            if((ispunct(ch) == 0) && (isspace(ch) == 0)) // ch is not a punctuation and not a white space
            {
                word[word_buffer] = ch;
                word_buffer++;
            }
            else
            {
                word[word_buffer] = '\0';
                words[word_ctr] = word;
                printf("word: \"%s\"\n", words[word_ctr]);
                word_ctr++;
                word_buffer = 0;
                if((word = malloc(WORD_SIZE * sizeof(char))) == NULL)
                    perror("Error allocating memmory");
            }
            string_ctr++;
        }
        free(word);
        printf("\n");
        printf("printing all words: ");
        for(ctr = 0; ctr < word_ctr; ctr++)
            printf("%s ", words[ctr]);
        printf("\n");
        
        // free words
        for(ctr = 0; ctr < word_ctr; ctr++)
            free(words[ctr]);
    Last edited by cfanatic; 02-09-2013 at 01:40 PM.
    IDE: Code::Blocks | Compiler Suite for Windows: TDM-GCC (MingW, gdb)

  8. #8
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Code:
    words[word_ctr] = word;
    This line just assigns the value of word (a memory address) to words[word_ctr] with the effect that both pointers point now to the same address. Thus when you free word, words[word_ctr] will point to an invalid address.

    Bye, Andreas

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Superfluous characters after string -- pointer issues?
    By marshaul in forum C Programming
    Replies: 21
    Last Post: 01-04-2011, 04:13 AM
  2. Entering and splitting string
    By Etdim in forum C Programming
    Replies: 17
    Last Post: 12-19-2007, 04:12 AM
  3. Probelm when entering a string
    By ManiacBR in forum C++ Programming
    Replies: 4
    Last Post: 11-23-2006, 05:07 AM
  4. Replies: 8
    Last Post: 10-17-2005, 07:01 PM
  5. preventing user entering characters
    By Ashkan in forum C Programming
    Replies: 12
    Last Post: 08-24-2003, 12:56 PM