How to use strtok()
Asked Answered
R

2

5

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.

Reprobate answered 21/9, 2013 at 0:49 Comment(10)
Your while loop continues until tok is NULL, right? So in the second printf statement, tok is NULL. Is that surprising?Astrea
Add a newline to the first printf()Puling
And if you need help with strtok() you can always consult the documentation.Merous
@Astrea Yeah it is printing NULL. How to I make it to print '&' instead?Reprobate
@user2201650: How many times do you think the loop executes? What do you think it prints the first time?Astrea
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.Merous
@Astrea I think it executes thrice. The 1st time it prints 'ls'.Reprobate
@Merous Yeah, but I want the tok variable to take '&' at the end and print it outside the while loop.Reprobate
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.Lantern
@Barmar, got it! THank you so much for the answer. I did the strcmp() and it worked! :) Thanks a lot! :)Reprobate
E
9
  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.

Encomiast answered 21/9, 2013 at 1:0 Comment(4)
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?Reprobate
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.Encomiast
@JonathanLeffler Or without the extra variable and strtok pastebin.com/4xHG9yGXPuling
@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.Encomiast
S
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;
}
Similarity answered 21/9, 2013 at 7:58 Comment(2)
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.Encomiast
This code is buggy, you should replace strtok first value inside the while loop to NULLFrieze

© 2022 - 2024 — McMap. All rights reserved.