C: Разделение строки на две строки и возвращение 2-элементного массива - PullRequest
0 голосов
/ 02 октября 2018

Я пытаюсь написать метод, который принимает строку и разбивает ее на две строки на основе строки-разделителя, аналогично .split в Java:

char * split(char *tosplit, char *culprit) { 

    char *couple[2] = {"", ""};

    int i = 0; 

    // Returns first token  
    char *token = strtok(tosplit, culprit);    


    while (token != NULL && i < 2) { 
        couple[i++] = token; 
        token = strtok(NULL, culprit); 
    } 

    return couple;
} 

Но я продолжаю получать предупреждения:

In function ‘split’:
warning: return from incompatible pointer type [-Wincompatible-pointer-types]
     return couple;
            ^~~~~~
warning: function returns address of local variable [-Wreturn-local-addr]

... и, конечно, метод не работает, как я надеялся.

Что я делаю не так?

РЕДАКТИРОВАТЬ: Я также открыт для других способов сделать это, кроме использования strtok ().

Ответы [ 4 ]

0 голосов
/ 02 октября 2018

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

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

/* 
 * NOTE: unsafe (and leaky) implementation using strtok
 *
 * *into must point to a memory space where tokens can be stored
 * or if *into is NULL then it allocates enough space.
 * Returns:
 *  allocated array of items that you must free yourself
 *
 */


char **__split(char *src, const char *delim)
{
    size_t idx = 0;
    char *next;
    char **dest = NULL;


    do {
        dest = realloc(dest, (idx + 1)* sizeof(char *));
        next = strtok(idx > 0 ? NULL:strdup(src), delim);
        dest[idx++] = next;
    } while(next);


    return dest; 
}


int main() {
    int x = 0;
    char **here = NULL;
    here = __split("hello,there,how,,are,you?", ",");

    while(here[x]) {
        printf("here: %s\n", here[x]);
        x++;
    }

}

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

0 голосов
/ 02 октября 2018

Просмотр вещей:

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

Во-вторых, вы возвращаете адрес локальной переменной, который - после завершения функции - выходит из области видимости и не должен быть доступен впоследствии.

В-третьих, вы определяете массив из 2указатели, тогда как ваш while -loop может писать за этими пределами.

Если вы действительно хотите разбить на две строки, должен работать следующий метод:

char ** split(char *tosplit, char *culprit) {     
    static char *couple[2];
    if ((couple[0] = strtok(tosplit, culprit)) != NULL) {
        couple[1] = strtok(NULL, culprit);
    }
    return couple;
} 
0 голосов
/ 02 октября 2018

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

Я думаю, что вы ищете что-то вроде этого:

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

char* split( char* s, char* delim ) {
  char* needle = strstr(s, delim);

  if (!needle)
    return NULL;

  needle[0] = 0;
  return needle + strlen(delim);
}

int main() {
  char s[] = "Fluffy furry Bunnies!";
  char* res = split(s, "furry ");
  printf("%s%s\n", s, res );
}

, который печатает "Пушистые кролики!".

0 голосов
/ 02 октября 2018

Тип couple равен char**, но вы определили тип возвращаемого значения функции как char*.Кроме того, вы возвращаете указатель на локальную переменную.Вам нужно передать массив указателей в функцию от вызывающей стороны.Например:

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

char** split( char** couple, char* tosplit, char* culprit ) 
{ 
    int i = 0; 

    // Returns first token  
    char *token = strtok( tosplit, culprit);    

    for( int i = 0; token != NULL && i < 2; i++ ) 
    { 
        couple[i] = token; 
        token = strtok(NULL, culprit); 
    } 

    return couple;
} 

int main()
{
    char* couple[2] = {"", ""};
    char tosplit[] = "Hello World" ;

    char** strings = split( couple, tosplit, " " ) ;

    printf( "%s, %s", strings[0], strings[1] ) ;

    return 0;
}
...