Как вы разделяете строку в C? - PullRequest
1 голос
/ 29 января 2012

Если у меня есть строка вроде:

const char* mystr = "Test Test Bla Bla \n Bla Bla Test \n Test Test \n";

Как бы я использовал символ новой строки '\ n', чтобы разбить строку на массив строк?

Я пытаюсь выполнить в C то, что string.Split() делает в C # или строковый алгоритм boost split делает в C ++.

Ответы [ 5 ]

8 голосов
/ 29 января 2012

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

char *copy = strdup(mystr);
char *tok;

tok = strtok(copy, "\n");
/* Do something with tok. */
while (tok) {
    tok = strtok(NULL, "\n");
    /* ... */
}

free(copy);
3 голосов
/ 29 января 2012

Самый простой способ разбить строку в C - это использовать strtok(), однако вместе с перечнем предостережений по поводу его использования можно использовать:

  1. Это деструктивно (разрушает входную строку), и вы не можете использовать его в строке, которую вы указали выше.
  2. Он не реентерабелен (он сохраняет свое состояние между вызовами, и вы можете использовать его только для токенизации одной строки за раз ... не говоря уже о том, чтобы использовать ее с потоками). Некоторые системы предоставляют реентерабельную версию, например, strtok_r(). Ваш пример может быть разделен как:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main (void) {
      char mystr[] = "Test Test Bla Bla \n Bla Bla Test \n Test Test \n";
      char *word = strtok(mystr, " \n");
    
       while (word) {
          printf("word: %s\n", word);
          word = strtok(NULL, " \n");
       }
    
       return 0;
    }
    

Обратите внимание на важное изменение вашего строкового объявления - теперь оно является массивом и может быть изменено. Конечно, можно токенизировать строку, не разрушая ее, но C не предоставляет простого решения для этого как часть стандартной библиотеки.

1 голос
/ 29 января 2012

В приведенных выше реакциях я вижу только циклы while () {}, где IMHO для циклов () {} более компактны.

cnicutar:

for(tok = strtok(copy, "\n");tok; tok = strtok(NULL, "\n") {
    /* ... */
}

FatalError:

char *word;
for ( word = strtok(mystr, " \n");word; word = strtok(NULL, " \n") {
   printf("word: %s\n", word);
}

Zack:

for (arry[i=0]=p=copy; *p ; p++)
{
  if (*p == '\n')
  {
    *p = '\0';
    arry[i++] = p+1;
  }
}

[четкость этого последнего примера спорно]

1 голос
/ 29 января 2012

Помните, что C заставляет вас делать все выделение памяти вручную.Помните также, что в C на самом деле нет строк , только массивы символов.Кроме того, строковые литералы являются неизменяемыми, поэтому вам придется скопировать их.Сначала будет проще скопировать все это.

Итак, что-то вроде этого (полностью не проверено):

char *copy = xstrdup(mystr);
char *p;
char **arry;
size_t count = 0;
size_t i;

for (p = copy; *p; p++)
  if (*p == '\n')
    count++;

arry = xmalloc((count + 1) * sizeof(char *));

i = 0;
p = copy;
arry[i] = p;
while (*p)
{
  if (*p == '\n')
  {
    *p = '\0';
    arry[i++] = p+1;
  }
  p++;
}

return arry; /* deallocating arry and arry[0] is 
                the responsibility of the caller */
0 голосов
/ 29 января 2012

Вы можете использовать нижеупомянутую библиотеку.Он имеет много других полезных функций.

http://www.boost.org/doc/libs/1_48_0/libs/tokenizer/index.html

Или вы можете использовать функцию strtok.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...