2016-09-23 3 views
-3

Я пытаюсь преобразовать строку (пример: «hey there mister») в двойной указатель, указывающий на каждое слово в предложении. так: split_string-> | указатель1 | указатель2 | указатель3 | где pointer1 -> «hey», pointer2 -> «there» и pointer3 -> «mister».Разделить строку на двойной указатель в C

char **split(char *s) { 
    char **nystreng = malloc(strlen(s)); 
    char str[strlen(s)]; 
    int i; 

    for(i = 0; i < strlen(s); i++){ 
     str[i] = s[i]; 
    } 

    char *temp; 
    temp = strtok(str, " "); 

    int teller = 0; 
    while(temp != NULL){ 
     printf("%s\n", temp); 
     nystreng[teller] = temp; 
     temp = strtok(NULL, " "); 
    } 
    nystreng[teller++] = NULL; 

    //free(nystreng); 

    return nystreng; 
} 

Мой вопрос: почему это не работает?

+0

В какой момент в вашей программе это не работает, как вы думаете, что это делает? – RPGillespie

+0

Пожалуйста, сообщите нам, что означает «не работает» в этом контексте. Какой результат вы получаете? –

+2

Прямо с места в карьер, это выглядит очень подозрительно: 'char ** nystreng = malloc (strlen (s));'. Непонятно, почему требуемое пространство будет равно длине 's' и не зависит от размера' char * '. –

ответ

1

У вашего кода есть несколько проблем. Среди них:

  • char **nystreng = malloc(strlen(s)); - это просто неправильно. Объем пространства, в котором вы нуждаетесь, - это размер char * раз числа, в которые будет разделяться строка плюс один (для терминатора указателя NULL).

  • *nystreng Вы заполняете с указателями, полученных из strtok(), работающих на местных массиве str. Эти указатели действительны только для времени жизни str, который заканчивается при возврате функции.

  • Вы не выделяете пространство для терминатора строк в str, и вы его не пишете, но вы передаете его strtok(), как если бы это была строка с прекращением.

  • Вы не увеличиваете teller внутри своего цикла токенизации, поэтому каждый указатель маркера перезаписывает предыдущий.

У вас есть существенная проблема здесь, в том, что вы не знаете до того, как разделите строку, сколько штук будет. Тем не менее, вы можете получить верхнюю границу, посчитав число символов разделителя и добавив 1. Затем вы можете выделить место для этого количества указателей char плюс один. Кроме того, вы можете создать связанный список, чтобы обрабатывать фрагменты, как вы tokenize, а затем выделить массив результатов только после того, как вы знаете, сколько штук есть.

Что касается str, если вы хотите вернуть указатели в него, как вы это делаете, то он также должен быть динамически распределен. Если платформа обеспечивает strdup(), то вы можете просто использовать

char *str = strdup(s); 

В противном случае, вам необходимо проверить длину, выделить достаточно места с malloc() (включая пространство для терминатора), а затем скопировать строку ввода в выделенное пространство , предположительно с strcpy().Обычно вы хотите освободить строку позже, но вы не должны этого делать, если вы возвращаете указатели в это пространство.

С другой стороны, вы можете рассмотреть возможность возврата массива строк, который может быть отдельно освобожден. Для этого вы должны выделять каждую подстроку индивидуально (strdup() снова будет вашим другом, если у вас есть), и в этом случае вы захотите освободить рабочее пространство (или разрешить его очистку автоматически, если вы используете VLA).

0

Есть две вещи, которые нужно сделать -

char str[strlen(s)]; //size should be equal to strlen(s)+1 

Extra 1 для '\0'. Прямо сейчас вы проходите str (не заканчивается '\0') до strtok, что вызывает не определено поведение.

И вторая вещь, вам также необходимо выделить память для каждого указателя nystring, а затем использовать strcpy вместо того, чтобы указывать на temp (не забудьте пространство для NUL терминатора).

Смежные вопросы