4

I'm writing a C program to study the usage of function strtok(). Here is my code:

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

main() {
    char abc[100] = "ls &";
    char *tok;

    tok = strtok(abc, " ");
    while (tok != NULL) {
        printf("%s", tok);
        tok = strtok(NULL, " ");
    }
    printf("\n\n\n\n\n%s", tok);
    return 0;
}

It is printing the following output:

ls&




(null)

But I want it to print & at the second printf statement. How do I do it? I need this part for my homework project.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
user2201650
  • 527
  • 7
  • 13
  • 28
  • 1
    Your `while` loop continues until `tok` is `NULL`, right? So in the second `printf` statement, `tok` is `NULL`. Is that surprising? – rici Sep 21 '13 at 00:51
  • 3
    Add a newline to the first printf() – this Sep 21 '13 at 00:52
  • And if you need help with `strtok()` you can always [consult the documentation](http://en.cppreference.com/w/c/string/byte/strtok). – WhozCraig Sep 21 '13 at 00:53
  • @rici Yeah it is printing NULL. How to I make it to print '&' instead? – user2201650 Sep 21 '13 at 00:53
  • @user2201650: How many times do you think the loop executes? What do you think it prints the first time? – rici Sep 21 '13 at 00:55
  • Why do you even *have* the followup `printf()` ? And since you wrote this, what do you think `printf("\n\n\n\n\n%s", NULL);` will do, since you're *guaranteed* that will be what is executed? Get rid of the second `printf` and just print each token until there are no more. – WhozCraig Sep 21 '13 at 00:55
  • @rici I think it executes thrice. The 1st time it prints 'ls'. – user2201650 Sep 21 '13 at 00:56
  • @WhozCraig Yeah, but I want the tok variable to take '&' at the end and print it outside the while loop. – user2201650 Sep 21 '13 at 00:57
  • You need to exit the loop if `strcmp(tok, "&") == 0`. If you wait until `tok == NULL`, then the second printf doesn't have anything to print. – Barmar Sep 21 '13 at 01:02
  • @Barmar, got it! THank you so much for the answer. I did the strcmp() and it worked! :) Thanks a lot! :) – user2201650 Sep 21 '13 at 01:12

2 Answers2

8
  1. Make sure you can identify the limits of what you print when you're printing.
  2. Output newlines at the end of printed messages; the information is more likely to appear in a timely manner if you do that.
  3. Don't print NULL pointers as strings; not all versions of printf() will behave nicely — some of them dump core.

Code:

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

int main(void)
{
    char abc[] = "ls &";
    char *tok;
    char *ptr = abc;

    while ((tok = strtok(ptr, " ")) != NULL)
    {
        printf("<<%s>>\n", tok);
        ptr = NULL;
    }
    return 0;
}

Or (optimized, courtesy of self.):

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

int main(void)
{
    char abc[] = "ls &";
    char *tok = abc;

    while ((tok = strtok(tok, " ")) != NULL)
    {
        printf("<<%s>>\n", tok);
        tok = NULL;
    }
    return 0;
}

Output:

<<ls>>
<<&>>

You can choose your own marker characters, but when not messing with XML or HTML, I find the double angle brackets reasonably good for the job.

You can also use your loop structure at the cost of writing a second call to strtok() (which is a minimal cost, but might be argued to violate the DRY principle: Don't Repeat Yourself):

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

int main(void)
{
    char abc[] = "ls &";
    char *tok = strtok(abc, " ");

    while (tok != NULL)
    {
        printf("<<%s>>\n", tok);
        tok = strtok(NULL, " ");
    }
    return 0;
}

Same output.


Revised requirement

I would like to add a printf() statement outside the while loop and print '&' outside. I need it since I want to compare it later with another variable in the program. Is there any way to do so?

Yes, there is usually a way to do almost anything. This seems to work. It also works sanely if there are more tokens to parse, or if there's only the & to parse, or if there are no tokens. Clearly, the body of the outer loop could be made into a function if you so wished; it would be sensible to do so, even.

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

int main(void)
{
    char tests[][16] =
    {
        "ls -l -s &",
        "ls &",
        "&",
        "    ",
        ""
    };

    for (size_t i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
    {
        printf("Initially: <<%s>>\n", tests[i]);
        char *tok1 = strtok(tests[i], " ");
        char *tok;

        while ((tok = strtok(NULL, " ")) != NULL)
        {
            printf("Loop body: <<%s>>\n", tok1);
            tok1 = tok;
        }
        if (tok1 != NULL)
            printf("Post loop: <<%s>>\n", tok1);
    }

    return 0;
}

Output:

Initially: <<ls -l -s &>>
Loop body: <<ls>>
Loop body: <<-l>>
Loop body: <<-s>>
Post loop: <<&>>
Initially: <<ls &>>
Loop body: <<ls>>
Post loop: <<&>>
Initially: <<&>>
Post loop: <<&>>
Initially: <<    >>
Initially: <<>>

Note how the markers pay for themselves in the last two examples. You couldn't tell those apart without the markers.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I would like to add a printf statement outside the while loop and print '&' outside. I need it since I want to compare it later with another variable in the program. Is there any way to do so? – user2201650 Sep 21 '13 at 01:05
  • Well, I suppose you can do it; most things _can_ be done. Are you sure it is worth it? Give me a few minutes while I think about it. It is not … an obvious requirement … shall we say. – Jonathan Leffler Sep 21 '13 at 01:07
  • @JonathanLeffler Or without the extra variable and strtok http://pastebin.com/4xHG9yGX – this Sep 21 '13 at 01:07
  • @self. I just looked at your pasted code; you're right, it can be made slicker. I've done that in the past; I'd forgotten this time around. – Jonathan Leffler Sep 21 '13 at 01:21
0

you should write sth like this:

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

int main();
{
char string[] = "ls &"; //you should not write 100, cuz you waste memory
char *pointer;

pointer = strtok(string, " "); //skip only spaces
while(pointer != NULL)
   {
      printf("%s\n", pointer);
      pointer = strtok(string, " ");
   }
return 0;
}
all0star
  • 99
  • 1
  • 1
  • 11
  • 4
    After the first call to `strtok()`, you must use `NULL` as the first argument to indicate that you are continuing where the previous call left off. – Jonathan Leffler Sep 21 '13 at 17:33
  • 1
    This code is buggy, you should replace strtok first value inside the while loop to NULL – dear_tzvi Jun 09 '16 at 14:54