C jak rozbić tekst na argumenty po spacjach?


(arekk-99) #1

Dzień dobry

Chciałbym rozbić wpisywany tekst na wyrazy i dodać je do jakiejś tablicy tak, jak to np się robi w php funkcją explode

Mam zmienną char* tekst; zawierającą np 50 wyrazów. Chciałbym w jakiś sposób uzyskać tablicę tych wyrazów z indeksami, żebym mógł odczytać 1 wyraz np item[1] to jest drugi wyraz itd. Czy jest coś takiego możliwe w jakiś niezbyt trudny sposób?


(kowgli) #2

https://www.google.pl/search?q=c+split+string+into+array


(arekk-99) #3

A odwrotność? Istnieje szansa, ze będę musiał skleić potem ten tekst z powrotem.


(Fizyda) #4

Może zwykła pętla wystarczy i obliczenie długości cstringa w celu stworzenia nowej dynamicznej tablicy?


(arekk-99) #5

czyli

#define sizearray(a) (sizeof(a) / sizeof((a)[0]))

char* strglue(char** tab)

{

char* buf;

for(int i = 0; i <= sizearray(tab); i++)

{
strcat(buf, tab_);_

}

return buf;

}


(Fizyda) #6
// words[][] - tablica dwuwymiarowa typu char w której masz zapisane słowa

// words_num - liczba słów w tablicy words - długość tablicy words



char * all_words;

int cstr_length = 0;



for(int i = 0; i < words_num; i++)

{

  cstr_length += strlen(words[i]);

}



cstr_length += words_num - 1; // miejsce na spacje pomiędzy wyrazami

all_words = new char[cstr_length];



for(int i = 0, j = 0; i < cstr_length && j < words_num; i++, j++)

{

  for(int k = 0; k < strlen(words[j]); i++, k++)

  {

  	all_words[i] = words[j][k];

  }

  

  all_words[i] = " "; //znak spacji nie wiem czy zadziała

}

Mniej więcej coś takiego, pisane z palca i do tego w c++ bo nie do końca wiem jakie są różnice między c a c++. Na pewno musisz zamienić new na malloc z c.

Mogłem popełnić jakieś błędy bo jak wspomniałem - pisane z palca.


(arekk-99) #7

fajnie, ze strtok wywala błąd

char** strsplit(char* text, char* wsk)
{
char** res = NULL;
char* p = strtok (text, " ");
int n_spaces = 0, i;
while § {
if((res = realloc(res, sizeof (char*) * ++n_spaces)) == NULL)
    exit (-1);
  res[n_spaces-1] = p;
  p = strtok (NULL, wsk);
}
res = realloc (res, sizeof (char*) * (n_spaces+1));
res[n_spaces] = 0;
return res;
free(res);
}

==32398== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==32398==  Bad permissions for mapped region at address 0x405836
==32398==    at 0x4EBA289: strtok (in /usr/lib/libc-2.24.so)
==32398==    by 0x4029CA: strsplit (functions.c:612)
==32398==    by 0x40178E: main (main.c:270)


(Fizyda) #8

Wydaje mi się, że tutaj masz problem:

p = strtok (NULL, wsk);

Ale nie wiem co to wsk bo nazwa nic nie mówi.

 

PS. Fajnie że używasz debugera.


(kostek135) #9

@arekk-99

Z dump-a widzę, że używasz Linuksa. Po prawdzie nie wiem jakiego, ale prawie każdy, który ma jakieś gnom-owe elementy będzie miał GLib

Może pora przestać wynajdywać koło na nowo i korzystać z tego co jest? Np. Na Ubuntu-a-like możesz sprawdzić czy masz dostępne glib

dpkg -l |grep libglib

jeśli tak, możesz go użyć skracając żmudne operacje:

#include <stdio.h>

#include <glib.h>



int main() {

	gchar* text = "Word with some spaces";

	

	gchar** tokens = g_strsplit(text, " ", G_MAXINT);



	for (gchar** ptr = tokens; *ptr; ptr++)

		printf("%s\n", *ptr);



	gchar* new_text = g_strjoinv(" ", tokens);



	printf("%s\n", new_text);



	g_strfreev(tokens);

	g_free(new_text);



	return 0;

}

kompilujesz w poniższy sposób (może się różnić w zależności od wersji biblioteki):

gcc main.c -o main `pkg-config --cflags --libs glib-2.0`