Kopiowanie co drugiego wyrazu stringa do odpowiedniej tablicy [C++]

0

Witam,
Czytam książkę "Symfonia C++ Standard". Aktualnie jestem na ćwiczeniach z rozdziału 7. Natknąłem się ostatnio na zadanie, w którym muszę za pomocą tablic znakowych stworzyć program, który będzie kopiował parzyste wyrazy stringa do jednej tablicy znakowej, a nieparzyste do drugiej. W każdej tablicy wyrazy mają być oddzielone spacjami.

Oto co napisałem:

 
#include <iostream>
using namespace std;

/* DZIAŁANIE PROGRAMU:
1. Robimy tablicę ze stringiem, a potem dwie puste: na wyrazy parzyste i nie parzyste.
2. Wywołujemy funkcję Kopiuj (w argumentach wysyłając adresy stworzonych wcześniej tablic),
która co drugi wyraz kopiuje do tablicy parzyste, a resztę do tablicy nieparzyste; */

void Kopiuj(char zrodlo[], char parzyste[], char nieparzyste[]);

int wywolania = 0;

int main()
{
    char zdanie[] = "Pogralbym sobie w tenisa";
    char tab_parzyste[100] = {};
    char tab_nieparzyste[100] = {};

    Kopiuj(zdanie, tab_parzyste, tab_nieparzyste);
}

void Kopiuj(char zrodlo[], char parzyste[], char nieparzyste[])
{
    bool parzystosc = true; // true, bo pierwszy wyraz będzie parzysty

    for(int i = 0; ; i++)
    {
        wywolania++;

        if(parzystosc)
        {
            parzyste[i] = zrodlo[i];
        }
        else
        {
            nieparzyste[i] = zrodlo[i];
        }

        if (zrodlo[i] == 32) // 32 to kod ASCII spacji.
        {
            parzystosc = !parzystosc;
        }

        if(zrodlo[i] == 0)
        {
            cout << "i = " << i << endl;
            break;
        }

        cout << wywolania << ". wywolanie: " << parzyste << "        " << nieparzyste << endl;
        cout << "Wielkosc parzyste: " << sizeof(parzyste) << " i wielkosc nieparzyste: " << sizeof(nieparzyste) << endl;
        cout << "Zmienna bool: " << parzystosc << endl;
    }
}

Niestety - pętla kopiuje tylko pierwszy wyraz, ale dzięki instrukcjom wypisania wiem, że pętla przeskakuje po wszystkich literach i wyrazach. Możecie mi wyjaśnić w czym tkwi problem?

1

Mozna na przyklad tak:

#include <iostream>
#include <tuple>
#include <algorithm>
#include <vector>
#include <string>
#include <iterator>
#include <functional>
#include <sstream>
using namespace std;

class StringList {
public:
	StringList(string init): data(split(init)) {}
	StringList(vector<string> init): data(init) {}
	StringList(initializer_list<string> init): data(init) {}

	tuple<StringList, StringList>
	partition(function<bool(const string)> p) {
		vector<string> v1, v2;
		for_each(data.begin(), data.end(), [&](string str) {
			if(p(str)) v1.push_back(str);
			else v2.push_back(str);
		});
		StringList l1(v1), l2(v2);
		return tie(l1, l2);
	}
	
	friend ostream& operator<<(ostream& out, const StringList& l) {
		for_each(l.data.begin(), l.data.end(), [&](const string& str) { out << str << " "; });
		return out;
	}

private:
	const vector<string> data;
	
	vector<string> split(string str) {
		istringstream iss(str);
		return vector<string>{
			istream_iterator<string>{iss},
			istream_iterator<string>{}
		};
	}
};

int main() {
	StringList src("Ala ma kota, a kot ma ale.");
	tuple<StringList, StringList> res = src.partition([](const string str) { return str.length() % 2; });
	cout << get<0>(res) << "\n";
	cout << get<1>(res) << "\n";
	return 0;
}

A jak nie chcesz ubijac muchy armata, to wystarczy przeciez copy do samego zadania.

0
void Kopiuj(char zrodlo[], char parzyste[], char nieparzyste[])
  {
   bool parzystosc=true; // true, bo pierwszy wyraz będzie parzysty
   for(int i=0,p=0,n=0;zrodlo[i];++i)
     {
      (parzystosc?parzyste[p++]:nieparzyste[n++])=zrodlo[i];
      if(zrodlo[i]==' ') parzystosc=!parzystosc;
     }
   parzyste[p]=nieparzyste[n]=0;
   //cout<<parzyste<<endl<<nieparzyste<<endl;
  }
0

Wersja na samych wkaźnikach - obsługuje dłuższe niż jeden znak przerwy.

#include <iostream>
using namespace std;

void Kopiuj(char zrodlo[], char parzyste[], char nieparzyste[]);

int main() {
    char zdanie[] = "Pogralbym sobie  w  tenisa";
    char tab_parzyste[100] = {};
    char tab_nieparzyste[100] = {};
 
    Kopiuj(zdanie, tab_parzyste, tab_nieparzyste);
    cout << "Parzyste: (" << string(tab_parzyste).length() << ") " << tab_parzyste << endl;
    cout << "Nieparzyste: (" << string(tab_nieparzyste).length() << ") " << tab_nieparzyste << endl;
    return 0;
}

void Kopiuj(char zrodlo[], char parzyste[], char nieparzyste[])
{
   bool parzystosc = false; // bo pierwszy wyraz jest nieparzysty
   char *zptr = zrodlo;
   char *pptr = parzyste;
   char *nptr = nieparzyste;
   char **cptrptr;
   
   *pptr = *nptr = '\0';
   
   while(*zptr) 
   {
     if (*zptr == ' ') { 
       while(*(++zptr) == ' ') {}
       parzystosc = !parzystosc;         
     }    

     if (parzystosc) 
       cptrptr = &pptr;
     else
       cptrptr = &nptr;
       
     if (**cptrptr == ' ')
       (*cptrptr)++;
     
     while(*zptr != ' ' && *zptr != '\0') {
       *((*cptrptr)++) = *zptr++;  
     }
     
     **cptrptr = ' ';
   }
   
   *pptr = *nptr = '\0';
} 

Wynik:
Parzyste: (12) sobie tenisa
Nieparzyste: (11) Pogralbym w

0

Wersja w C++ & Boost (nie testowane):

#include <iostream>
using namespace std;

void Kopiuj(char zrodlo[], char parzyste[], char nieparzyste[]);

int main() {
    char zdanie[] = "Pogralbym sobie  w  tenisa";
    char tab_parzyste[100] = {};
    char tab_nieparzyste[100] = {};
 
    Kopiuj(zdanie, tab_parzyste, tab_nieparzyste);
    cout << "Parzyste: (" << string(tab_parzyste).length() << ") " << tab_parzyste << endl;
    cout << "Nieparzyste: (" << string(tab_nieparzyste).length() << ") " << tab_nieparzyste << endl;
    return 0;
}

void Kopiuj(char zrodlo[], char parzyste[], char nieparzyste[])
{
  string line(zrodlo);
  vector<string> strs;
  boost::split(strs,line,boost::is_any_of(" "));
  std::stringstream parzysteStream;
  std::stringstream nieparzysteStream;
  std::stringstream *dest;

  for (size_t i = 0, epos = strs.size(); i < epos; i++)
  {
     if (i % 2) 
      dest = &nieparzysteStream;
     else
      dest = &parzysteStream;
     if (i > 1)
       *dest << " ";
     *dest << strs[i];
  }

  string s = parzysteStream.str();
  s.copy(parzyste, s.length());

  s = nieparzysteStream.str();
  s.copy(nieparzyste, s.length());
}

Wada tego rozwiązania: kopiowanie na we i na wy. Można to w pewnym stopniu wyeliminować zmieniając nagłówek funkcji Kopiuj.

0

Wersja na samych wkaźnikach - obsługuje dłuższe niż jeden znak przerwy. Alternatywa do http://4programmers.net/Forum/C_i_C++/236543-kopiowanie_co_drugiego_wyrazu_stringa_do_odpowiedniej_tablicy_c++?p=1049902#id1049902

#include <iostream>
using namespace std;
 
void Kopiuj(char *zrodlo,char *parzyste,char *nieparzyste)
  {
   char *tb[]={parzyste,nieparzyste},prev=0;
   for(int pos=0;*zrodlo;pos^=(*zrodlo==' ')&&(prev!=' '),prev=*(zrodlo++))
     {
      if((*zrodlo!=' ')||(prev!=' ')) *(tb[pos]++)=*zrodlo;
     }
   tb[0][0]=tb[1][0]=0;
  }
 
int main()
  {
   char zdanie[] = "Pogralbym     sobie  w  tenisa";
   char tab_parzyste[100] = {};
   char tab_nieparzyste[100] = {};
 
   Kopiuj(zdanie, tab_parzyste, tab_nieparzyste);
   cout << "Parzyste: (" << string(tab_parzyste).length() << ") " << tab_parzyste << endl;
   cout << "Nieparzyste: (" << string(tab_nieparzyste).length() << ") " << tab_nieparzyste << endl;
   return 0;
  }
0

Dzięki wszystkim za odpowiedzi. Nie spodziewałem się tak dużej ilości odpowiedni (znałem tą stronę, ale nie wchodziłem od paru lat i w sumie nie byłem pewien czy na tą stronę ktoś w ogóle jeszcze wchodzi ;D)

Ostatecznie wybrałem wsparcie 13th_Dragon, ponieważ kod który udostępnił był podobny do mojego i nie miałem problemów z jego zrozumieniem.

0
 
#include <iostream>
#include <string>
#include <regex>
#include <vector>
#include <array>

int main() {
  std::string input = "Ala ma kota, a kot ma ale.";
  std::regex pattern("\\s+");
  std::array<std::vector<std::string>, 2> results;
  unsigned dest = 1;
  std::sregex_token_iterator end;
  for (std::sregex_token_iterator it(input.begin(), input.end(), pattern, -1); it != end; it++) {
    results[dest = dest ? 0 : 1].push_back(it->str());
  }

  for (auto i : { 0, 1 }) {
    std::copy(results[i].begin(), results[i].end(),
      std::ostream_iterator<std::string>(std::cout, " "));
    std::cout << std::endl;
  }

  return 0;
}

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