На языке C, как я могу разделить строку на подстроки, разделенные символом пробела. [Дубликат]

Порядок, в котором указаны взаимозависимые связанные библиотеки, неверен.

Порядок, в котором связаны библиотеки, имеет значение, если библиотеки зависят друг от друга. В общем случае, если библиотека A зависит от библиотеки B, тогда libA ДОЛЖЕН появляться перед libB в флагах компоновщика.

Например:

// B.h
#ifndef B_H
#define B_H

struct B {
    B(int);
    int x;
};

#endif

// B.cpp
#include "B.h"
B::B(int xx) : x(xx) {}

// A.h
#include "B.h"

struct A {
    A(int x);
    B b;
};

// A.cpp
#include "A.h"

A::A(int x) : b(x) {}

// main.cpp
#include "A.h"

int main() {
    A a(5);
    return 0;
};

Создайте библиотеки:

$ g++ -c A.cpp
$ g++ -c B.cpp
$ ar rvs libA.a A.o 
ar: creating libA.a
a - A.o
$ ar rvs libB.a B.o 
ar: creating libB.a
a - B.o

Скомпилируйте:

$ g++ main.cpp -L. -lB -lA
./libA.a(A.o): In function `A::A(int)':
A.cpp:(.text+0x1c): undefined reference to `B::B(int)'
collect2: error: ld returned 1 exit status
$ g++ main.cpp -L. -lA -lB
$ ./a.out

Чтобы повторить снова, порядок имеет значение!

23
задан Yu Hao 1 November 2013 в 07:18
поделиться

7 ответов

Вот еще одна реализация strtok(), которая имеет возможность распознавать последовательные разделители (в стандартной библиотеке strtok() этого нет)

Эта функция является частью лицензированной библиотеки BSD, называемой zString . Вы более чем можете внести свой вклад:)

https://github.com/fnoyanisi/zString

char *zstring_strtok(char *str, const char *delim) {
    static char *static_str=0;      /* var to store last address */
    int index=0, strlength=0;       /* integers for indexes */
    int found = 0;                  /* check if delim is found */

    /* delimiter cannot be NULL
    * if no more char left, return NULL as well
    */
    if (delim==0 || (str == 0 && static_str == 0))
        return 0;

    if (str == 0)
        str = static_str;

    /* get length of string */
    while(str[strlength])
        strlength++;

    /* find the first occurance of delim */
    for (index=0;index<strlength;index++)
        if (str[index]==delim[0]) {
            found=1;
            break;
        }

    /* if delim is not contained in str, return str */
    if (!found) {
        static_str = 0;
        return str;
    }

    /* check for consecutive delimiters
    *if first char is delim, return delim
    */
    if (str[0]==delim[0]) {
        static_str = (str + 1);
        return (char *)delim;
    }

    /* terminate the string
    * this assignmetn requires char[], so str has to
    * be char[] rather than *char
    */
    str[index] = '\0';

    /* save the rest of the string */
    if ((str + index + 1)!=0)
        static_str = (str + index + 1);
    else
        static_str = 0;

        return str;
}

Как упоминалось в предыдущих сообщениях, поскольку strtok() или тот, который я вложил выше, полагается на переменную static *char, чтобы сохранить местоположение последнего разделителя между последовательными вызовами, следует проявлять особую осторожность при работе с многопоточными приложениями.

0
ответ дан Fehmi Noyan ISI 31 August 2018 в 23:08
поделиться
2
ответ дан Fernando 31 August 2018 в 23:08
поделиться

Вы можете упростить код, введя дополнительную переменную.

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

int main()
{
    char str[100], *s = str, *t = NULL;

    strcpy(str, "a space delimited string");
    while ((t = strtok(s, " ")) != NULL) {
        s = NULL;
        printf(":%s:\n", t);
    }
    return 0;
}
3
ответ дан Ferruccio 31 August 2018 в 23:08
поделиться
int not_in_delimiter(char c, char *delim){

    while(*delim != '\0'){
            if(c == *delim) return 0;
            delim++;
    }
    return 1;
}

char *token_separater(char *source, char *delimiter, char **last){

char *begin, *next_token;
char *sbegin;

/*Get the start of the token */
if(source)
  begin = source;
else
  begin = *last;

sbegin = begin;

/*Scan through the string till we find character in delimiter. */
while(*begin != '\0' && not_in_delimiter(*begin, delimiter)){
       begin++;
}

/* Check if we have reached at of the string */
if(*begin == '\0') {
/* We dont need to come further, hence return NULL*/
   *last = NULL;
    return sbegin;
}
/* Scan the string till we find a character which is not in delimiter */
 next_token  = begin;
 while(next_token != '\0' && !not_in_delimiter(*next_token, delimiter))    {
    next_token++;
 }
 /* If we have not reached at the end of the string */
 if(*next_token != '\0'){
  *last = next_token--;
  *next_token = '\0';
   return sbegin;
}
}

 void main(){

    char string[10] = "abcb_dccc";
    char delim[10] = "_";
    char *token = NULL;
    char *last = "" ;
    token  = token_separater(string, delim, &last);
    printf("%s\n", token);
    while(last){
            token  = token_separater(NULL, delim, &last);
            printf("%s\n", token);
    }

}

Вы можете прочитать подробный анализ в блоге, указанном в моем профиле:)

-1
ответ дан jitsceait 31 August 2018 в 23:08
поделиться

strtok может быть очень опасным. Он не является потокобезопасным. Его предполагаемое использование должно вызываться снова и снова в цикле, передавая результат с предыдущего вызова. Функция strtok имеет внутреннюю переменную, которая хранит состояние вызова strtok. Это состояние не уникально для каждого потока - оно глобально. Если какой-либо другой код использует strtok в другом потоке, у вас возникают проблемы.

Я бы рекомендовал искать реализацию регулярного выражения или использовать sscanf, чтобы разделить эту строку.

Попробуйте следующее:

char strprint[256];
char text[256];
strcpy(text, "My string to test");
while ( sscanf( text, "%s %s", strprint, text) > 0 ) {
   printf("token: %s\n", strprint);
}

Примечание. Строка «текст» уничтожается по мере ее разделения. Это не может быть предпочтительным поведением =)

7
ответ дан Kieveli 31 August 2018 в 23:08
поделиться

При чтении документации strtok я вижу, что вам нужно передать указатель NULL после первого вызова «инициализации». Может быть, вы этого не сделали. Конечно, конечно.

0
ответ дан xtofl 31 August 2018 в 23:08
поделиться

Вот пример использования strtok, помните, что strtok разрушает его входную строку (и поэтому не может когда-либо использоваться в строковой константе

char *p = strtok(str, " ");
while(p != NULL) {
    printf("%s\n", p);
    p = strtok(NULL, " ");
}

В основном следует отметить, что передача NULL в качестве первого параметра в strtok говорит ему, чтобы он получил следующий токен из строки, которая была ранее маркерной.

34
ответ дан Yu Hao 31 August 2018 в 23:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: