Thread: Trouble printing an array of chars

  1. #1
    Registered User
    Join Date
    Nov 2010
    Posts
    2

    Trouble printing an array of chars

    I am having trouble printing a sentence backwards the second time around through my loop without it printing the null values of the array. Is there anyway to get rid of the <NULL> that prints (for each word in the previous sentence) after each new sentence? Thanks. Here is my code:


    Code:
    #include <string.h>
    #include <stdio.h>
    
      void tokenThis();
      int i;
      int j = 0;
      char *tokens[100];
      char *tokenPtr;
      char string[100];
      
       
     int main ()
     {
    	 int choice;
    
    	 printf("Enter 1 to exit or enter a sentence to be tokenized:\n");
    	 scanf_s("%d",&choice);
    	 while(choice!=1)
    	 {
          
          gets(string);//get the string
          tokenThis();//call function to tokenize sentence
          printf("\n\n\n");
          memset(&tokens[0], 0, sizeof(tokens)); 
          memset(&string[0], 0, sizeof(string));
          printf("\nEnter a sentence to be tokenized or enter 1 to exit:\n");
    	  scanf_s("%d",&choice);	 
    	 }//end while
       return 0;
    
     }//end of main
    
     void tokenThis()
     { // Get the first part
        tokenPtr = strtok (string, " ");
     
       // Get all following parts
       //
       while (tokenPtr)
       {
       // Store a word into array
    
         tokens [j++] = tokenPtr;
     
         // Pick next word (NULL token will stop the loop)
         
         tokenPtr = strtok (NULL, " ");
       }
     
       // Print all parts in reverse order
       
       printf ("\n\nThis is the sentence reversed:\n");
       for (i = j - 1; i >= 0; i--)
       {
         printf ("%s ", tokens [i]);
      
       }
     }//end of tokenThis method

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    This is due to two things:
    1. A simple logical error (not re-initializing j to zero every time you run tokenThis)
    2. You memset tokens and string after the first tokenString, making everything null.

    But perhaps it is better to use this as an opportunity to point out that global variables are generally a bad idea. Since I'm guessing you're kinda new to programming or C, I will say flat out "you should never use global variables".

    Make all variables local to the appropriate function, and pass them into other functions as needed. Since j is only used in tokenThis, declare it inside that function. string and tokens are needed in main, which calls tokenThis, so declare them in main and pass them to tokenThis, etc.

  3. #3
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Oh yeah, and two notes on your input gathering:
    1. Don't use gets, since it doesn't have a length limit and thus allows for easy buffer overflows (especially if somebody types a sentences from a Melville novel into your program). Use fgets instead.
    2. gets and fgets put the newline/enter that was read as the last character in the string. Trim this to avoid the new line in the middle of your reversed sentence.

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by anduril462 View Post
    2. gets and fgets put the newline/enter that was read as the last character in the string. Trim this to avoid the new line in the middle of your reversed sentence.
    Close, but no:
    The fgets() function reads at most one less than the number of characters
    specified by size from the given stream and stores them in the string
    str. Reading stops when a newline character is found, at end-of-file or
    error. The newline, if any, is retained. If any characters are read and
    there is no error, a `\0' character is appended to end the string.

    The gets() function is equivalent to fgets() with an infinite size and a
    stream of stdin, except that the newline character (if any) is not stored
    in the string.
    It is the caller's responsibility to ensure that the
    input line, if any, is sufficiently short to fit in the string.
    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Nov 2010
    Posts
    2
    Thank you. I got rid of my global variables and placed them in the appropriate functions. In doing so, I was able to cut out using memset alltogether and everything works fine
    As far as fgets, when I use it I cannot figure out how to get rid of the newline that appears after the first printed word in reverse order.

  6. #6
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Quote Originally Posted by ppata View Post
    Thank you. I got rid of my global variables and placed them in the appropriate functions. In doing so, I was able to cut out using memset alltogether and everything works fine
    As far as fgets, when I use it I cannot figure out how to get rid of the newline that appears after the first printed word in reverse order.
    Just snip it before doing anything.

    Code:
    char * ch = NULL;
    if((ch = strchr(input, '\n')) != NULL)
    {
       *ch = '\0';
    }

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    @ppta: Take Quzah's comment as a lesson to always double check the advice you're given. Seems I was a bit off in my description of gets and fgets (done from memory, shame on me). Check MSDN, since it looks like you're programming on Windows.

    As for the newline, remember that a "string" in C is basically an array of characters. So if your string is "hello", you have an array like {'h', 'e', 'l', 'l', 'o', '\0'} (null terminator). Index 0 would contain 'h', index 1 'e', etc. If there was a terminating new line, it would look like {'h', 'e', 'l', 'l', 'o', '\n', '\0'}. The newline at index 5 or wherever, if it exists, needs to be replaced with a '\0' character.
    Code:
    int last;
    ...
    last = strlen(string);
    if ('\0' == string[last]) {
        string[last] = '\0';
    }
    You should do this before your call to tokenThisk.

    @Quzah: Thanks for that catch. I guess since I never use gets, I didn't think about the subtler differences. Any idea why there would be a difference in the way they handle new lines?

  8. #8
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Don't you mean.

    Code:
    int last;
    ...
    last = strlen(string)-1;
    if ('\n' == string[last]) {
        string[last] = '\0';
    }

  9. #9
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    D'oh! I'm failing all over today. Yeah, that's what I meant.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Printing 2D Array
    By BB89 in forum C Programming
    Replies: 11
    Last Post: 11-16-2009, 05:33 AM
  2. printing 2d array with char
    By doongas in forum C Programming
    Replies: 2
    Last Post: 09-16-2005, 12:26 PM
  3. Merge sort please
    By vasanth in forum C Programming
    Replies: 2
    Last Post: 11-09-2003, 12:09 PM
  4. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM
  5. Printing an Array to the screen
    By simhap in forum C++ Programming
    Replies: 6
    Last Post: 11-01-2001, 11:16 AM