Как да използвате strtok()

Пиша C програма, за да проуча използването на функция strtok(). Ето моят код:

#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;
}

Той отпечатва следния изход:

ls&




(null)

Но искам да отпечата & във втория израз printf. Как го правя? Имам нужда от тази част за моя проект за домашна работа.


person user2201650    schedule 21.09.2013    source източник
comment
Вашият while цикъл продължава, докато tok стане NULL, нали? Така че във втория израз printf, tok е NULL. Това изненадващо ли е?   -  person rici    schedule 21.09.2013
comment
Добавете нов ред към първия printf()   -  person this    schedule 21.09.2013
comment
И ако имате нужда от помощ с strtok(), винаги можете да консултирате се с документацията.   -  person WhozCraig    schedule 21.09.2013
comment
@rici Да, отпечатва NULL. Как да го накарам да отпечата "&" вместо това?   -  person user2201650    schedule 21.09.2013
comment
@user2201650: Колко пъти мислите, че се изпълнява цикълът? Какво мислите, че отпечатва първия път?   -  person rici    schedule 21.09.2013
comment
Защо изобщо имате последващите действия printf()? И след като сте написали това, какво мислите, че printf("\n\n\n\n\n%s", NULL); ще направи, тъй като сте гарантирани, че това ще бъде изпълнено? Отървете се от второто printf и просто отпечатвайте всеки жетон, докато не остане повече.   -  person WhozCraig    schedule 21.09.2013
comment
@rici Мисля, че се изпълнява три пъти. Първият път отпечатва 'ls'.   -  person user2201650    schedule 21.09.2013
comment
@WhozCraig Да, но искам променливата tok да вземе "&" в края и да го отпечата извън цикъла while.   -  person user2201650    schedule 21.09.2013
comment
Трябва да излезете от цикъла, ако strcmp(tok, "&") == 0. Ако изчакате до tok == NULL, тогава вторият printf няма какво да отпечата.   -  person Barmar    schedule 21.09.2013
comment
@Barmar, разбрах! Много ви благодаря за отговора. Направих strcmp() и проработи! :) Благодаря много! :)   -  person user2201650    schedule 21.09.2013


Отговори (2)


  1. Уверете се, че можете да определите границите на това, което печатате, когато печатате.
  2. Извежда нови редове в края на отпечатаните съобщения; е по-вероятно информацията да се появи навреме, ако направите това.
  3. Не отпечатвайте NULL указатели като низове; не всички версии на printf() ще се държат добре — някои от тях изхвърлят ядро.

Код:

#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;
}

Или (оптимизирано, с любезното съдействие на 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;
}

Изход:

<<ls>>
<<&>>

Можете да изберете свои собствени знаци за маркери, но когато не се забърквате с XML или HTML, намирам двойните ъглови скоби за сравнително добри за работата.

Можете също така да използвате структурата на цикъла си с цената на писане на второ извикване до strtok() (което е минимална цена, но може да се твърди, че нарушава принципа DRY: Не се повтаряйте):

#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;
}

Същият изход.


Ревизирано изискване

Бих искал да добавя израз printf() извън цикъла while и да отпечатам '&' отвън. Трябва ми, тъй като искам да го сравня по-късно с друга променлива в програмата. Има ли някакъв начин да го направите?

Да, обикновено има начин да направите почти всичко. Това изглежда работи. Също така работи разумно, ако има повече токени за анализ, или ако има само & за анализ, или ако няма токени. Ясно е, че тялото на външния цикъл може да се превърне във функция, ако желаете; дори би било разумно да го направим.

#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;
}

Изход:

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: <<>>

Обърнете внимание как маркерите плащат за себе си в последните два примера. Не можете да ги различите без маркерите.

person Jonathan Leffler    schedule 21.09.2013
comment
Бих искал да добавя оператор printf извън цикъла while и да отпечатам '&' извън. Трябва ми, тъй като искам да го сравня по-късно с друга променлива в програмата. Има ли някакъв начин да го направите? - person user2201650; 21.09.2013
comment
Е, предполагам, че можете да го направите; повечето неща могат да бъдат направени. Сигурен ли си, че си струва? Дай ми няколко минути, докато помисля за това. Това не е... очевидно изискване... да кажем. - person Jonathan Leffler; 21.09.2013
comment
@JonathanLeffler Или без допълнителната променлива и strtok pastebin.com/4xHG9yGX - person this; 21.09.2013
comment
@self. Току-що погледнах вашия поставен код; прав си, може да се направи по-плавно. Правил съм това в миналото; Бях забравил този път. - person Jonathan Leffler; 21.09.2013

трябва да напишете sth така:

#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;
}
person all0star    schedule 21.09.2013
comment
След първото извикване на strtok(), трябва да използвате NULL като първи аргумент, за да посочите, че продължавате от мястото, където е спряло предишното извикване. - person Jonathan Leffler; 21.09.2013
comment
Този код е бъг, трябва да замените първата стойност на strtok в цикъла while на NULL - person dear_tzvi; 09.06.2016