dzielenie łancucha i do tablicy sruuuuu

0

Witam
Zgłaszam się do was z takim problemem, być może banalnym ale nie zajmuje się c++ zawodowo.

Jak podzielić łańcuch znaków (zdanie) na wyrazy, a potem (albo Od razu) stworzyć tablice tych wyrazów (każdy element tablicy to inny wyraz)?

Za pomoc bardzo i z góry dziękuje

0

Tak naprawde to jest problem lingwistyczny :P Chyba ze chodzi Ci o dzielenie w miejscu spacji?

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

countwords(char* s){
  if(!*s)return 0;
  int i=0;
  int k=*s^32;
  while(*s){
    while(*s==32)s++;
    if(*s)i++;
    while(*s^32 && *s)s++;
  }
  return i;
}

getword(char* s,int nr,char* buf){
  if(!*s)return 0;
  int k=*s^32;
  while(*s){
    while(*s==32)s++;
    if(*s)nr--;
    char* t=s;
    while(*s^32 && *s)s++;
    if(!nr){
      *(strncpy(buf,t,s-t)+(s-t))=0;
      return 1;
    }
  }
  return 0;
}

main(){
  char* s="    ala ma   wszawego  kota       ";
  int i;
  printf("liczba slow : %d\n",i=countwords(s));
  i++; // damy +1 slowo do sprawdzenia
  while(i){
    char t[20];
    if(getword(s,i,t))printf("slowo %d : %s\n",i--,t);
      else printf("slowo %d nie istnieje\n",i--);
  }
  return 0;
}

Do tablicy sam sobie już wrzucisz (w miejscu printf-a)...

0

Flabra: widze ze masz poczucie humoru :)

Sprobuj czegos takiego:

char** arr;

void tokenize(char**& arr, const char* str, int& count)
{
	if(!str) return;
	char tmp[32] = {0};
	
	short len = strlen(str);

	count = 0;
	for(short n=0;n<len;n++)
		if(str[n] != ' '/*||str[n] != '\n'*/)
			count++;

	arr = new char*[count];
	short wrd=0,ndx=0;

	for(n=0,count=0;n<len;n++)
	{
		if(str[n] != ' '/*||str[n] != '\n'*/)
			tmp[ndx++] = str[n];
		else
		{
			arr[count] = new char[ndx+1];
			strcpy(arr[count],tmp);
			arr[count++][ndx] = ndx = 0;
		}
	}
}

moga byc male bledy bo pisalem "z palca" ;)

0

Super :D

tylko czasem w tablicy robią się krzaczki, a dla niektórych tekstów (może to wredność mojego kompa) wywala program :/

dokładnie dzieje się tak dla zbyt długich wyrazów, np. trzy razy "wszechmogący" albo "maksymialian" powoduje krzaczki a później zawieche, wyskakuje informacja błędzie, jak mniemam chodzi o pamięć. jak zmusić go do prawidłowej pracy?

0

Behehehe :D - dłuższych kodów pisać nie mogliście? [green]
Pół strony jakiś kosmosów dla tak prostego zadania :P

char *p, *zdanie = "Ala ma    kota a kot ma pałę";
char tab[7][10];
int i=0;
if (p = strtok(zdanie, " "))
 do
  strcpy(tab[i++], p);
 while (p = strtok(NULL, " "));

Tablica tab tutaj ustawiona statycznie dla uproszczenia - sam ją musisz stworzyć w odpowiednich rozmiarach.

0

no tez super :] tylko nie mogę dojść dlaczego nie chce uwzględniać pierwszego wyrazu...

//mi uwzględnia wszystko dobrze - na pewno pod tab[0] nie ma pierwszego wyrazu? Nie wierzę... - M

3

Czyzby znowu konkurs "Kto to napisze najkrocej?"

Odnosnie funkcji strtok:

BUGS
Never use these functions. If you do, note that:
These functions modify their first argument.
These functions cannot be used on constant strings.
The identity of the delimiting character is lost.
The strtok() function uses a static buffer while parsing, so it's not thread safe. --------------------------

Dobra, a teraz moja propozycja kodu:

#include <vector>
#include <string>
using namespace std;

vector<string> SplitIntoWords(const string& Str) {
  vector<string> Result;
  int SpacePos = -1;
  int OldPos = 0;
  while ((SpacePos = Str.find(" ", SpacePos + 1)) != string::npos) {
     Result.push_back(Str.substr(OldPos, SpacePos - OldPos - 1));
     OldPos = SpacePos;
  }
  Result.push_back(Str.substr(OldPos, string::npos));
  return Result;
}

Uniwersalne, przenosne, krotkie i szybkie. :)

0

Niby tak, ale po zmianie delimitera ze spacji na ":" to juz nie dziala to tak jak powinno :)

0

Wypowiedz moja tyczyla sie kodu Krolika. Mowiac o ":" ze nie dziala poprawnie chodzilo mi ze na poczatku tokena zostaje ten nieszczesny ":". Wczesniej tego nie zauwazylem bo byla spacja i wlasnie ona pozostawala w tokenie.

0

Niby rozwiazaniem jest zamiana
Str.substr(OldPos, SpacePos - OldPos - 0).c_str();
Str.substr(OldPos+1, SpacePos - OldPos - 0).c_str();
Wtedy w pierwszym tokenie bedzie brakowac znaku ale reszta nie bedzie miala wstawionego delimitera

vector<string> SplitIntoWords(const string& Str) {
Form1->Memo1->Clear();
Form1->Memo1->Text = "";
vector<string> Result;
AnsiString xxx;
int SpacePos = -1;
int OldPos = 0;
while ((SpacePos = Str.find(" ", SpacePos + 1)) != string::npos) {
xxx = Str.substr(OldPos+1, SpacePos - OldPos - 0).c_str();
Result.push_back(xxx.c_str());
Form1->Memo1->Lines->Add(xxx);
OldPos = SpacePos;
}
Result.push_back(Str.substr(OldPos, string::npos));
return Result;
}

0

AnsiString ccc = " alakota🅰️kotwielka2 ";
SplitIntoWords(ccc.c_str());

vector<string> SplitIntoWords(const string& Str) {
Form1->Memo1->Clear();
Form1->Memo1->Text = "";
vector<string> Result;
AnsiString xxx;
int SpacePos = -1;
int OldPos = 0;
while ((SpacePos = Str.find(":", SpacePos + 1)) != string::npos) {
xxx = Str.substr(OldPos+1, SpacePos - OldPos - 1).c_str();
Result.push_back(xxx.c_str());
Form1->Memo1->Lines->Add(xxx);
OldPos = SpacePos;
}
Result.push_back(Str.substr(OldPos, string::npos));
return Result;
}

2

Stringstream'ami można krótko i prosto:

string temp,tekst = "ala ma kota co pozjadal rybki";
vector<string> tab;

istringstream os(tekst);
while(os >> temp)
	tab.push_back(temp);
1

Można jeszcze bez jawnej pętli:

std::string text = "ala ma kota co pozjadal rybki";
	
std::istringstream sstream(text);
std::istream_iterator<std::string> it(sstream), end;
std::vector<std::string> vector(it, end);

Ale oba te rozwiązania mają taką wadę, że nie można sprecyzować własnego separatora. Polecam użycie boost::split, a jak się nie da to trzeba samemu dzielić napis. Można bez wyszukiwania znaków, wystarczy std::getline.

std::string text = "ala:ma:kota:co:pozjadal:rybki", fragment;
std::vector<std::string> vector;
std::istringstream sstream(text);

while(std::getline(sstream, fragment, ':'))
	vector.push_back(fragment);

1 użytkowników online, w tym zalogowanych: 0, gości: 1