C++ - Usereingaben (cin, getline...)

Hallo zusammen!
Bei einem C++-Programm (Linux) kommt es zweimal vor, dass entweder der Benutzer etwas eingibt oder ich etwas aus einem Textfile lese.

Zur Benutzereingabe:
Ich weiss die länge der Eingabe nicht (nur ungefähr, also 10<eingabe<100 und ich weiss nicht, aus wievielen Wörtern sie besteht. Sie kann zum Beispiel so aussehen:
update library now
Es sind also 3 Wörter, un im besten Fall hätte ich die alle in einzelnen Strings mit denen ich dann weiter arbeiten kann.
Bis jetzt hab ich das so gelöst:
Code:
string eingabe;
cout << "Eingabe: ";
getline(cin, eingabe);
return 0;
Das Problem ist nun, dass alles in einem String ist und ich nicht die einzelenen Wörter habe.
Frage 1:
Gibt es eine (einfache) Möglichkeit, einen String in soviele Strings zu zerlegen wie es Wörter im String hat?
Ich hab da mal sowas ausprobiert:
Code:
string befehl="hallo welt";
int stringanfang=0;
int stringende=0;
string wort1;    
string wort2;    

for (int i=0; i < 20; i++)
{
  if (befehl[i] == 32)
  {
    stringende = (i-1);
    stringanfang = (i+1);
    for (int i=0; i<(stringanfang-1); i++)
    {
    wort1[i] = befehl[i];
    cout << ""<<wort1;
    }
    for (int i=(stringende+2); i<(stringanfang + 10); i++)
    {
    wort2[i] = befehl[i];
    }
    break;
  }
}
cout << ""<<wort1;
cout << ""<<wort2;
}
Ist ne ziemliche Holzfäller Methode und funktioniert auch nicht, weil wort1 nur temporär? gefüllt wird. Das heisst unten, bei den 2 cout kommt nichts raus :)

Zur Frage 2:
Ich habe ein Textfile:
befehl1 skript1
befehl2 skript2
befehl3 skript3
Der Aufbau ist immer so, die Namen können aber unterschiedlich sein. D.h. statt befehl1 könnte es auch update heissen.
Diese Linien hab ich bis jetzt so eingelesen:
Code:
ifstream scripts ("scripts");
if (scripts.is_open())
{
 int i = 0;
 while (! scripts.eof() ) //while script hat ende nicht erreicht
 {
 getline (scripts,line);
XXX
}
Bei XXX muss noch etwas reinkommen, dass den String line, der aus zwei Wörtern besteht, in zwei Strings mit je einem Wort schneidet.

Das Prinzip ist also oben und unten eingentlich das gleiche, ich hoffe ihr habt mir einen oder zwei Tipps :)
Danke!
 
Warum ließt du die Strings nicht immer bis zum Leerzeichen ein und schreibst danach eine neue String Variable?
Dann könntest du

"update library now" wirklich direkt verarbeiten ;-)
 
Hallo!
Hier ist ein gutes tut zur Stringklasse:
http://www.uni-bayreuth.de/departments/math/~rbaier/lectures/c/html/node62.html
Sowas ist nicht schwer zu realisieren, aber ich will dir den Code nicht vorwerfen, auch wenn's in den Fingern juckt. ^^
Mal ein paar Hilfestellungen:
Benutze eine For-Schleife und betrachte jeweils einen char große Substrings und prüfe, ob ein Leerzeichen vorkommt. Jetzt ist der erste String der Substring von der Buffervariable (am Anfang 0) bis zur momentanen For-Position. (normalerweise nimmet man dafür i). Dann setzt du den buffer gleich i und suchst fleißig weiter. Den String kannst du in nem String array oder Vector speichern...
Hoffe das hilft dir weiter =)

Edit: da war einer schneller >.<
Aber die Lösung halt ich nicht für Sinn der Sache. Das Ganze soll ja wie eine Konsole designed sein und da gibt man nunmal nicht die Parameter in der nächsten Zeile xD
 
Danke. Extinction, für deine Antwort.
Sowas ähnliches hab ich ja gemacht und oben gepostet, oder blick ich grad nicht durch?
Das Prinzip wär doch genau das, nur das ich da keinen Output bekomme:
Code:
#include <iostream>
#include <string>
using namespace std;

int main()
{
string befehl="hallo welt";
int stringanfang=0;
int stringende=0;
string wort1;
string wort2;
int zeichen=befehl.size(); // get string size
for (int i=0; i < zeichen; i++)
{
  if (befehl[i] == 32) //wenn leerzeichen gefunden wurde
  {
    stringende = (i-1);
    stringanfang = (i+1);
    for (int i=0; i<(stringanfang-1); i++)
    {
    wort1[i] = befehl[i];
    cout << ""<<wort1;
    }
    for (int i=(stringende+2); i< zeichen; i++)
    {
    wort2[i] = befehl[i];
    }
    break;
  }
}
cout << ""<<wort1;
cout << ""<<wort2;
}

Jetzt könnt' ich natürlich noch zählen, wieviele wörter im string sind (und nicht einfach von 2 ausgehen) und das mit einer schleife noch so machen, dass tatsächlich soviele strings wie wörter erstellt werden.
 
Nur mal ein kleiner Denkanstoß wenn du willst schreibe ich es nachher noch genauer, da ich imo nich viel zeit habe:

Nutze die STL, denn es gibt dort ein paar nette Funktionen wie find und ähnliche, und wenn dir das nicht reicht, benutz einen Tokenizer oder schreib dir einen, ist einfacher als alles von Hand zu machen.
 
Hmmm... Ich habs mir nicht genau angesehen, sorry. Hab mir jetzt aber dafür mal mehr Zeit genommen. Leider kann ich deinen Code nicht compilieren. Der Compiler macht zwar keine Fehlermeldung, aber das Programm schließt mit einem Fehler...
Ich bin auch nicht ganz durchgestiegen, wie das funktioniert. >.< Liegt vieleicht dran, dass ich unter windows programmiere.
Nichts desto trotz hab ich einfach mal ein fertiges Prog geschrieben, das dich vor vollendete Tatsachen stellt. ^^
Ist auch extra gut kommentiert :D

Code:
#include <iostream>
#include <string>
using namespace std;

int main()
{

//Variablen definieren...
string befehl="Dies ist ein einfacher Testtext :D";
int stringanfang=0;
int wortzahl=0;
string woerter[100];
int buchstaben=0;

//diese Schleife läuft so oft durch, wie der String lang ist.
//Ich hab die Anweisung direkt eingebaut. Das spart eine Variable ;)
for (int i=0;i<=befehl.size();i++)
{
	//Der Counter "buchstaben" zählt die Buchstaben des aktuellen Wortes
	buchstaben++;

	//Hier wird geprüft, ob ein Leerzeichen vorliegt, und
	//der Teilstring zuende ist.
	if (befehl.substr(i,1)==" ")
	{
		//Das aktuelle Wort wird im Array gespeichert.
		//dafür brauchen wir die Zahl der Buchstaben :D
		woerter[wortzahl]=befehl.substr(stringanfang,buchstaben);
		//Den Anfang des neuen Wortes legen wir auf i+1, um das Leerzeichen
		//nicht mit einzubeziehen!
		stringanfang=i+1;
		//Den Buchstabencounter reseten...
		buchstaben=0;
		//und zu guter letzt notieren, dass wir ein Wort mehr haben. ^^
		wortzahl++;
	}

}
//Hier erfassen wir den Text hinter dem letzten Leerzeichen.
//Sonst würde der auf der Strecke bleiben, da ja nur der Text
//bis zum nächsten leerzeichen erfasst wird.
woerter[wortzahl]=befehl.substr(stringanfang,string::npos);

//eine kleine Ausgabeschleife. Nur die Arrayteile, die Text beinhalten
// werden angezeigt.
for (i=0;i<100;i++)
{
	if (woerter[i]!="")
	{
		cout << woerter[i] << endl;
	}
}

//und Ende =)
return 0;
}
Naja, leider hab ich deine Methode nicht übernommen, sodass du nich mehr aus deinem Fehler lernen kannst. Is meiner Meinung nach das Wichtigste :X
 
schau mal:
Code:
void tokenizer(const string& full, vector<string>& token)
{
	string::size_type p;
	string ser = full;

	while((p = ser.find(' ')) != string::npos)
	{
		token.push_back(ser.substr(0, p));
		ser = ser.substr(p+1);
	}
	token.push_back(ser);
}
funktioniert einwandfrei^^

(ich weiß ist unsauber habe aber ur 2 min gedacht sry)
es geht auch ohne Stringkopien zum Beispiel mit iteratoren...
 
@Exctinction

Das schaut gut aus, wobei es ja eigentlch das gleiche ist wie ich es gemacht habe nur etwas weniger kompliziert und mit substrings. Das Prinzip ist aber dasselbe.

Leider kann ich es nicht kompilieren:
test.cpp: In function ?int main()?:
test.cpp:47: Fehler: Namenssuche von ?i? hat sich für neue ISO-Regeln zum ?for?-Gültigkeitsbereich geändert
test.cpp:18: Fehler: bei ?i? wird veraltete Bindung verwendet

Ich habs mit g++ unter Debian Edge versucht.
Wär super wenn das klappen würde, ich schreibs dann noch etwas um so dass es "meiner sprache" entspricht.

liebe grüsse & vielen dank,
cw

@copykill
ich schau deine variante auch noch an.
 
Original von CentralWay
Leider kann ich es nicht kompilieren:
test.cpp: In function ?int main()?:
test.cpp:47: Fehler: Namenssuche von ?i? hat sich für neue ISO-Regeln zum ?for?-Gültigkeitsbereich geändert
test.cpp:18: Fehler: bei ?i? wird veraltete Bindung verwendet

in zeile 46 noch ein "int" vor das i ;)
das i aus zeile 17 gilt nur im nachfolgenden block, nicht mehr in zeile 46
 
Original von Heinzelotto
Original von CentralWay
Leider kann ich es nicht kompilieren:
test.cpp: In function ?int main()?:
test.cpp:47: Fehler: Namenssuche von ?i? hat sich für neue ISO-Regeln zum ?for?-Gültigkeitsbereich geändert
test.cpp:18: Fehler: bei ?i? wird veraltete Bindung verwendet

in zeile 46 noch ein "int" vor das i ;)
das i aus zeile 17 gilt nur im nachfolgenden block, nicht mehr in zeile 46
Hm, super vielen Dank!
Ich Idiot hab diese Schleifen mehr als einmal angeschaut...

Danke euch allen!
---Problem solved---
:)
 
kann eigentlich nicht sein, denn laut ISO-C++ ist der gültigkeitsbereich einer im Initialisierungsbereich deklarierten & definierten variable nur der nachfolgende block.

aber die fehlermeldung lautet ja:
test.cpp:47: Fehler: Namenssuche von ?i? hat sich für neue ISO-Regeln zum ?for?-Gültigkeitsbereich geändert

ich glaube, es wird zeit für ein compiler-update ;)
 
aso das hatte ich irgendwie automatisch berichtigt... (Eclipse sei dank)
 
Zurück
Oben