Как разбить строку на 2 строки в C - PullRequest
38 голосов
/ 26 марта 2010

Мне было интересно, как можно взять 1 строку, разделить ее на 2 с помощью разделителя, например пробела, и назначить 2 части двум отдельным строкам. Я пытался использовать strtok(), но безрезультатно.

Ответы [ 8 ]

56 голосов
/ 26 марта 2010
#include <string.h>

char *token;
char line[] = "SEVERAL WORDS";
char *search = " ";


// Token will point to "SEVERAL".
token = strtok(line, search);


// Token will point to "WORDS".
token = strtok(NULL, search);

Обновление

Обратите внимание, что в некоторых операционных системах справочная страница strtok упоминает:

Этот интерфейс устарел в strsep (3).

Пример с strsep показан ниже:

char* token;
char* string;
char* tofree;

string = strdup("abc,def,ghi");

if (string != NULL) {

  tofree = string;

  while ((token = strsep(&string, ",")) != NULL)
  {
    printf("%s\n", token);
  }

  free(tofree);
}
11 голосов
/ 26 марта 2010

Для таких целей я склонен использовать strtok_r () вместо strtok ().

Например ...

int main (void) {
char str[128];
char *ptr;

strcpy (str, "123456 789asdf");
strtok_r (str, " ", &ptr);

printf ("'%s'  '%s'\n", str, ptr);
return 0;
}

Это выведет ...

'123456' '789asdf'

Если требуется больше разделителей, тогда цикл.

Надеюсь, это поможет.

3 голосов
/ 26 марта 2010

Вы можете использовать strtok () для этого Пример: у меня это работает

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

int main ()
{
    char str[] ="- This, a sample string.";
    char * pch;
    printf ("Splitting string \"%s\" into tokens:\n",str);
    pch = strtok (str," ,.-");
    while (pch != NULL)
    {
        printf ("%s\n",pch);
        pch = strtok (NULL, " ,.-");
    }
    return 0;
}
3 голосов
/ 26 марта 2010
char *line = strdup("user name"); // don't do char *line = "user name"; see Note

char *first_part = strtok(line, " "); //first_part points to "user"
char *sec_part = strtok(NULL, " ");   //sec_part points to "name"

Примечание: strtok изменяет строку, поэтому не передавайте ей указатель на строковый литерал.

1 голос
/ 19 февраля 2016

Вот как вы реализуете strtok() подобную функцию (взято из лицензированной библиотеки обработки строк BS для C, называемой zString ).

Функция ниже отличается от стандартной strtok() тем, как она распознает последовательные разделители, тогда как стандарт strtok() не делает.

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

Ниже приведен пример кода, демонстрирующий использование

  Example Usage
      char str[] = "A,B,,,C";
      printf("1 %s\n",zstring_strtok(s,","));
      printf("2 %s\n",zstring_strtok(NULL,","));
      printf("3 %s\n",zstring_strtok(NULL,","));
      printf("4 %s\n",zstring_strtok(NULL,","));
      printf("5 %s\n",zstring_strtok(NULL,","));
      printf("6 %s\n",zstring_strtok(NULL,","));

  Example Output
      1 A
      2 B
      3 ,
      4 ,
      5 C
      6 (null)

Вы даже можете использовать цикл while (стандартная библиотека strtok() даст здесь тот же результат)

char s[]="some text here;
do {
    printf("%s\n",zstring_strtok(s," "));
} while(zstring_strtok(NULL," "));
1 голос
/ 26 марта 2010

Вы можете сделать:

char str[] ="Stackoverflow Serverfault";
char piece1[20] = ""
    ,piece2[20] = "";
char * p;

p = strtok (str," "); // call the strtok with str as 1st arg for the 1st time.
if (p != NULL) // check if we got a token.
{
    strcpy(piece1,p); // save the token.
    p = strtok (NULL, " "); // subsequent call should have NULL as 1st arg.
    if (p != NULL) // check if we got a token.
        strcpy(piece2,p); // save the token.
}
printf("%s :: %s\n",piece1,piece2); // prints Stackoverflow :: Serverfault

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

1 голос
/ 26 марта 2010

Если у вас есть выделенный массив символов, вы можете просто поместить '\0' куда хотите.Затем укажите новый указатель char * на местоположение сразу после недавно вставленного '\0'.

. Это уничтожит вашу исходную строку, хотя в зависимости от того, куда вы положили '\0'

1 голос
/ 26 марта 2010

Если вы готовы изменить исходную строку, вы можете просто заменить разделитель на \0. Исходный указатель будет указывать на первую строку, а указатель на символ после разделителя будет указывать на вторую строку. Хорошо, что вы можете использовать оба указателя одновременно, не выделяя новые строковые буферы.

...