[c++] probleme mit cstrings

WhiteShark

Admiral
Registriert
Mai 2002
Beiträge
9.949
nabend,

also fürs studium müssen wir mit cstrings ein programm machen, was den string durchsuchen kann, jeden buchstaben zählen kann, usw.

nun das problem fängt schon mit der eingabe an. da wir ganze sätze einlesen wollen (mit leerzeichen), wollte wir des mit cin.getline() machen.
problem dabei ist, das nur mit dieser funktion garnix passiert.

also haben wir folgende lösung:
Code:
cin >> wort;
cin.getline(wort,255,'\n');

dabei wird allerdings das erste wort im satz verschluckt. und wir ham jetzt keine ahnung wie wir des machen, das er korrekt einließt.


dann müssen wir für paar schleifen die anzahl der zeichen im ctring zählen. das sollte ja mit strlen() gehen, allerdings zählt der nur bis zum ersten leerzeichen.
hattens auch schon mit ner schleife versucht, die ne variable hochzählt und sobald der buchstabe '\0' ist abbricht. aber auch das zählt nur bis zum leerzeichen.


die einzelnen wörter soll man auch sortieren können.
also das aus dem satz "hallo wie geht es dir" eben "dir es geht hallo wie" wird.
wollten dazu bubblesort nehmen, aber irgendwie verschwinden dann immer wörter und sortiert wird auch nicht.


Code:
                        satz[0] = strtok(wort," ");
                        i = 1;
                        while (i<=30){
                        satz[i] = strtok(NULL, " ");
                        i++;
                        }


anzahl=0;
while(satz[anzahl]!='\0')
{
anzahl++;
}

for (int i=0;i<=anzahl;i++)
{
for (int j=0;j<=anzahl;j++)
{
if (strncmp(satz[j],satz[j+1],2) <0)
{
temp=satz[j];
satz[j]=satz[j+1];
satz[j+1]=temp;
}
}
}


bin langsam so leicht am verzweifeln, weil nix so funktioniert wie es soll und wir nurnoch bis freitag zeit haben.


ich hoffe mir kann jemand helfen.


danke schonmal


mfg
crazy
 
Zuletzt bearbeitet:
mal auf die schnelle für das 2te problem (zeichanzahl):

Code:
unsigned i=0;
for(; satz[i]!='\0'; i++)
{}
cout << i << endl;

dann müsste in i die Anzahl stehen.

EDIT:
hm also theoretisch is es ja das gleiche wie du schon hast; aber bei mir hauts hin...
 
Zuletzt bearbeitet:
zum 1.Problem:

lass
cin >> s;
einfach weg

Anm.:

der >>-Operator auf 'cin' liest eine Zeichenkette bis zum ersten Whitespace-Zeichen ein
(Leerzeichen, Tabulator, Zeilenumbruch, Ende des Eingabestreams)
cin.getLine(...) liest bis zum nächsten Zeilenumbruch ein.

mit
cin >> s;
cin.getline(s)
wir also ein Wort eingelesen und in s gespeichert
danach wird der Rest der Zeile eingelesen und in s gespeichert. Alles was vorher in s war, das erste WOrt eben, wird überschrieben
 
danke, aber irgendwie zählt der trotzdem immer nur bis zum leerzeichen.


@cameo:
das hatte ich anfangs versucht. aber lasse ich das cin >> weg, kommt garkeine eingabeaufforderung mehr.
aber hab mir nun beholfen, zwar nicht die feinste lösung, aber wenigstens die eingabe geht jetzt

Code:
                       cin >> wort;
                        cin.getline(leer,255,'\n');

                        strcat(wort,leer);

jetzt hab ich wenigstens schonmal die komplette zeichenkette in wort drinnen stehen. muss jetzt nurnoch zählen wielang die is, das ich ne schleife hab, um die einzelnen buchstaben zählen zu können.

sieht so aus:

Code:
                      cout << "rel. Haufigkeit der Zeichen" << endl << endl;


                        for(; wort[v]!='\0'; v++)
                        {}
                        cout << v << endl << wort[v]<<endl;
                        //cout << satz;

                        for (int i=0;i<v;i++){
                        //if (wort[i]==' '){i++;}
                        //if (wort[i]=='\0'){ break;}
                        switch (wort[i]){
                        case 'a': anzahlbuchstaben[0]++;break;
                        case 'b': anzahlbuchstaben[1]++;break;
                        case 'c': anzahlbuchstaben[2]++;break;
                        case 'd': anzahlbuchstaben[3]++;break;
                        case 'e': anzahlbuchstaben[4]++;break;
                        case 'f': anzahlbuchstaben[5]++;break;
                        case 'g': anzahlbuchstaben[6]++;break;
                        case 'h': anzahlbuchstaben[7]++;break;
                        case 'i': anzahlbuchstaben[8]++;break;
                        case 'j': anzahlbuchstaben[9]++;break;
                        case 'k': anzahlbuchstaben[10]++;break;
                        case 'l': anzahlbuchstaben[11]++;break;
                        case 'm': anzahlbuchstaben[12]++;break;
                        case 'n': anzahlbuchstaben[13]++;break;
                        case 'o': anzahlbuchstaben[14]++;break;
                        case 'p': anzahlbuchstaben[15]++;break;
                        case 'q': anzahlbuchstaben[16]++;break;
                        case 'r': anzahlbuchstaben[17]++;break;
                        case 's': anzahlbuchstaben[18]++;break;
                        case 't': anzahlbuchstaben[19]++;break;
                        case 'u': anzahlbuchstaben[20]++;break;
                        case 'v': anzahlbuchstaben[21]++;break;
                        case 'w': anzahlbuchstaben[22]++;break;
                        case 'x': anzahlbuchstaben[23]++;break;
                        case 'y': anzahlbuchstaben[24]++;break;
                        case 'z': anzahlbuchstaben[25]++;break;
                        }

                        }
                        temp_z=0;
                        // gesamtzahlbuchstaben zählen
                        for (int i=0;i<=25;i++){
                        temp_z=temp_z + anzahlbuchstaben[i];
                        }

                        // ausgabe
                        for (int i=0;i<=25;i++){
                        if (anzahlbuchstaben[i]>0){
                        switch (i)
                        {
                        case 0: cout << "a: "; break;
                        case 1: cout << "b: "; break;
                        case 2: cout << "c: "; break;
                        case 3: cout << "d: "; break;
                        case 4: cout << "e: "; break;
                        case 5: cout << "f: "; break;
                        case 6: cout << "g: "; break;
                        case 7: cout << "h: "; break;
                        case 8: cout << "i: "; break;
                        case 9: cout << "j: "; break;
                        case 10: cout << "k: "; break;
                        case 11: cout << "l: "; break;
                        case 12: cout << "m: "; break;
                        case 13: cout << "n: "; break;
                        case 14: cout << "o: "; break;
                        case 15: cout << "p: "; break;
                        case 16: cout << "q: "; break;
                        case 17: cout << "r: "; break;
                        case 18: cout << "s: "; break;
                        case 19: cout << "t: "; break;
                        case 20: cout << "u: "; break;
                        case 21: cout << "v: "; break;
                        case 22: cout << "w: "; break;
                        case 23: cout << "x: "; break;
                        case 24: cout << "y: "; break;
                        case 25: cout << "z: "; break;
                        }

                        //cout << anzahlbuchstaben[i] / temp_z * 100 << " %"<< endl;
                        cout << anzahlbuchstaben[i] << endl;
                        }
                        }

leider durchläuft er das ganze nur v-mal. in v sollte ja die anzahl der zeichen stehen. aber da steht se nur bis zum ersten leerzeichen.
folglich läuft er bei z.B. "hallo welt" nur bis zum o durch.

ich dachte mir jetzt, das man zur not einfach die leerzeichen entfernt und dann die buchstaben zählt.
nur wie stelle ich das am besten an.


mfg
crazy





Edit: so das zählen der buchstaben funzt, nachdem ich die leerzeichen aus dem cstring entfernt habe
Code:
                        for (i=0;i<255;i++)
                        {
                        if (wort[i]!=' ')
                        {
                        temp2[f]=wort[i];
                        f++;
                        }
                        }
                        temp2[f]='\0';


danke soweit für die hilfe. jetzt muss ich des ganze nurnoch sortieren und dann soll man noch ein einzelnes wort bearbeiten können.
zum bearbeiten hab ich schon ne idee. hab ja im array satz jeweils die worte einzeln stehen. also bei "hallo welt" steht in satz[0] hallo und in satz[1] welt.
die lass ich dann gerade bearbeiten und les des dann einzeln wieder in eine komplette zeichenkette, nachdem bearbeiten.

aber die sortierung geht irgendwie nicht.

Code:
                        satz[0] = strtok(wort," ");
                        i = 1;
                        while (i<=30){
                        satz[i] = strtok(NULL, " ");
                        i++;
                        }


anzahl=0;
while(satz[anzahl]!='\0')
{
anzahl++;
}

for (int i=0;i<=anzahl;i++)
{
for (int j=0;j<=anzahl;j++)
{
if (strncmp(satz[j],satz[j+1],2) <0)
{
temp=satz[j];
satz[j]=satz[j+1];
satz[j+1]=temp;
}
}
}

cout << anzahl << endl;
 
Zuletzt bearbeitet:
WhiteShark schrieb:
@cameo:
das hatte ich anfangs versucht. aber lasse ich das cin >> weg, kommt garkeine eingabeaufforderung mehr.
Dann stimmt aber irgendwas mit deimem Compiler/Linker nicht. Lass doch einmal folgendes Programm ausführen

Code:
#include <iostream>

using namespace std;

#define MAX_LINE 100

int main(){

	char s[MAX_LINE];
	cin.getline(s,MAX_LINE,'\n');

	cout << s << endl;

	return 0;
}
 
@cameo:
also nachdem ich die stdlib.h eingebunden und ein system("pause"); drangehängt hab, konnt ich sehen, dass es funzt.


habs bei mir im code genauso. frag mich jetzt wieso des da net so geht.
aber auf umwegen gehts ja dann doch.
benutzte übrigens als compiler dev-cpp 4.


habe jetzt nurnoch das problem ein einzelnes wort zu bearbeiten und die suche.

habe es nun so gelöst, das mit strtok die zeichenkette ja in einzelne worte geteilt wird.
also bei "hallo welt" steht hallo in satz[0] und welt in satz[1].

soweit sogut. man kann jetzt die einzelnen worte ersetzen. allerdings, wenn ich nun hallo durch ein längeres wort ersetze, dann verschiebt sich alles. also ersetze ich es beispielsweise mit hallodu, dann steht in satz[1] dult.


ausserdem sollen die einzelnen worte nach dem ändern wieder in die normale zeichenkette wort eingesetzt werden, mit man auch danach suchen kann.


Code:
satz[0] = strtok(wort," ");
                        i = 1;
                        while (i<=30){
                        satz[i] = strtok(NULL, " ");
                        i++;
                        }


Code:
   cout << "Woerter aendern\n";
                        u=0;

                        while (satz[u]!='\0')
                        {
                        cout << u+1 << ". " << satz[u] << endl;
                        u++;
                        }
                        cin >> eingabe2;

                        cout << "Sie moechten das Wort \"" << satz[eingabe2-1] << "\" aendern. 

Bitte geben sie das neue Wort ein.\n";
                        cin >> satz[eingabe2-1];

                        for (int i=0;i<strlen(satz);i++){
                         strcat(wort,satz[i]);
                         }


                        cout << wort << endl;
                        cout << "Wort geaendert\n";
 
WhiteShark schrieb:
@cameo:
also nachdem ich die stdlib.h eingebunden und ein system("pause"); drangehängt hab, konnt ich sehen, dass es funzt.
??
Tja, kann dazu jetzt auch nicht mehr sagen.
Egal, wenn Du die Benutzerdaten irgendwie in dein Programm bringst, ist das ja in Ordnung.
Letzendlich wird ja wohl hoffentlich die Programmlogik beurteilt und nicht die Benutzereingabe.
 
nabend,

mit ein wenig hilfe im irc funzt nun soweit alles, bis auf die sortierung.

die sieht bei mir jetzt so aus:

Code:
for (int i=0;i<30;i++)
{
for (int x=0;x<30;x++)
{
if (strncmp(satz[x],satz[x+1],2)<0)
{
temp5=satz[x];
satz[x]=satz[x+1];
satz[x+1]=temp5;
}
}



problem dabei ist, das er abstürzt, sobald ich sortieren will.

satz und temp5 sind wie folgt deklariert:
char *satz[100];
char *temp5;


vll wisst ihr ne lösung, warum des nicht funzt.


mfg
crazy
 
char *satz[100]; ist ein Array aus Zeigern.
Das erste Element zeigt auf den Satz, wenn du nun inkrementierst ... worauf wird dort gezeigt? genau ... -> Zugriffsverletzung und das Ding schmiert ab.

Hoffe es hat geholfen.
 
habs letzte nacht noch komplett umgeschrieben, weil es plötzlich klick gemacht hat, als ich schon halb am einpennen war.

mir kam urplötzlich die idee einer tabelle, also einem zweidimensionalem array. hab also die zeichenkette durchgeschleift und in ein zweidimensionales array geschrieben, dass in jeder zeile ein wort steht.
dadurch konnt ich ganz einfach suchen, ersetzen, sortieren, usw.

code spar ich mir jetzt, komm gerad vom feiern zurück und feier hier noch weiter. bei bedarf füg ich gerne noch was an.


unser lehrer hat uns das programm übrigens gestern abgenommen und es ist alles gelaufen.
 
Zurück
Oben