strtok - как избежать появления новой строки в массиве строк? - PullRequest
2 голосов
/ 01 марта 2011

Если я обманываю тему, я действительно извиняюсь, я искал это без результата здесь. У меня есть код

void split(char* str, char* splitstr)
{
     char* p;
     char splitbuf[32];
     int i=0;
     p = strtok(str,",");
     while(p!= NULL)
     {
               printf("%s", p);    
               sprintf(&splitstr[i],"%s",p);
               i++;
               p = strtok (NULL, ",");

     }
}

Как я могу использовать правильный sprintf, чтобы поместить разделенные слова по strtok в строковый массив? Могу ли я как-то избежать разрывов, созданных strtok? Я программирую на ANSI C. Я объявил массив splitstr и str таким же образом.

char* splitstr;//in main char splitstr[32];

Спасибо за помощь.


редактирование:

i would like do something like this:
INPUT (it is a string) > "aa,bbb,ccc,ddd"
I declare: char tab[33];
OUTPUT (save all items to array of strings if it is even possible) > 
tab[0] is "aa"
tab[1] is "bbb"
...
tab[3] is "ddd" but not "ddd(newline)"

edit2 [18:16]

Я забыл добавить, что строка данных из строки чтения файла. Вот почему я написал о "DDD (новая строка)". После этого я обнаружил, что новая строка была также показана strtok, но как еще один элемент. Кстати, все ответы хороши, чтобы обдумать проблему. Несколько секунд назад мой ноутбук сломался (я не знаю, почему экран стал черным) Как только я возьму под контроль свой компьютер, я проверю коды. : -)

Ответы [ 3 ]

1 голос
/ 01 марта 2011

Обратите внимание, что я не специалист по ANSI C, а специалист по C ++, но вот рабочий код.Он использует массив фиксированного размера, который может быть или не быть проблемой.Чтобы сделать что-то еще, потребуется более сложное управление памятью:

/* Not sure about the declaration of splitstr here, and whether there's a better way.
   char** isn't sufficient. */
int split(char* str, char splitstr[256][32])
{
   char* p;
   int i=0;
   p = strtok(str,",");
   while(p) {
   strcpy(splitstr[i++], p);
       p = strtok (NULL, ",");
   }
   return i;
}

int main(int argc, char* argv[])
{
 char input[256];
  char result[256][32];
  strcpy(input, "aa,bbb,ccc,ddd");
  int count = split(input, result);

  for (int i=0; i<count; i++) {
    printf("%s\n", result[i]);
  }
      printf("the end\n");
}

Обратите внимание, что я поставляю "aa, bbb, ccc, ddd" и получаю {"aa", "bbb", "ccc","DDD"} из.Нет новых строк в результате.

1 голос
/ 01 марта 2011

Сделайте снимок:

#include <stdlib.h>
#include <string.h>
...
void split(char *str, char **splitstr) 
{      
  char *p;      
  int i=0;      

  p = strtok(str,",");      
  while(p!= NULL)      
  {                
    printf("%s", p);
    splitsr[i] = malloc(strlen(p) + 1);
    if (splitstr[i])
      strcpy(splitstr[i], p);
    i++;
    p = strtok (NULL, ",");       
  } 
}

А затем, в main:

#define MAX_LEN  ... // max allowed length of input string, including 0 terminator
#define MAX_STR  ... // max allowed number of substrings in input string

int main(void)
{
  char input[MAX_LEN]; 
  char *strs[MAX_STR] = {NULL}; 
  ...
  split(input, strs);
  ...
}

Некоторые объяснения.

strs определяется в main как массив указателей на char.Каждый элемент массива будет указывать на строку, извлеченную из входной строки.В общем, все, что выделено, это массив указателей, каждый элемент изначально равен NULL;память для каждого элемента будет выделена в функции split с использованием malloc в зависимости от длины подстроки. Где-то после того, как вы закончили с strs, вам нужно будет освободить эти указатели, используя free:

for (i = 0; i < MAX_STR; i++)
  free(strs[i]);

Теперь, почему splitstr объявлен как char ** вместоchar *[MAX_STR]?За исключением случаев, когда он является операндом операторов sizeof или & или является строковым литералом, используемым для инициализации другого массива в объявлении, тип выражения массива будет неявно преобразован из N-element array of T в pointer to T,и значением выражения будет расположение первого элемента в массиве.

Когда мы вызываем split:

split(input, strs);

, выражение массива input неявно преобразуется извведите char [MAX_LENGTH] в char * (T == char), а выражение массива strs неявно преобразуется из типа char *[MAX_STRS] в char ** (T == char *).Таким образом, splitstr получает значения указателя для двух параметров, в отличие от значений массива.

1 голос
/ 01 марта 2011

Если я правильно понимаю, вы хотите сохранить строки, полученные strtok. В этом случае вы захотите объявить splitstr как char [MAX_LINES] [32] и использовать strcpy, что-то вроде этого:

strcpy(splitstr[i], p);

где i - i-я строка, прочитанная с использованием strtok.

...