www.vorhilfe.de
Vorhilfe

Kostenlose Kommunikationsplattform für gegenseitige Hilfestellungen.
Hallo Gast!einloggen | registrieren ]
Startseite · Forum · Wissen · Kurse · Mitglieder · Team · Impressum
Forenbaum
^ Forenbaum
Status Vorhilfe
  Status Geisteswiss.
    Status Erdkunde
    Status Geschichte
    Status Jura
    Status Musik/Kunst
    Status Pädagogik
    Status Philosophie
    Status Politik/Wirtschaft
    Status Psychologie
    Status Religion
    Status Sozialwissenschaften
  Status Informatik
    Status Schule
    Status Hochschule
    Status Info-Training
    Status Wettbewerbe
    Status Praxis
    Status Internes IR
  Status Ingenieurwiss.
    Status Bauingenieurwesen
    Status Elektrotechnik
    Status Maschinenbau
    Status Materialwissenschaft
    Status Regelungstechnik
    Status Signaltheorie
    Status Sonstiges
    Status Technik
  Status Mathe
    Status Schulmathe
    Status Hochschulmathe
    Status Mathe-Vorkurse
    Status Mathe-Software
  Status Naturwiss.
    Status Astronomie
    Status Biologie
    Status Chemie
    Status Geowissenschaften
    Status Medizin
    Status Physik
    Status Sport
  Status Sonstiges / Diverses
  Status Sprachen
    Status Deutsch
    Status Englisch
    Status Französisch
    Status Griechisch
    Status Latein
    Status Russisch
    Status Spanisch
    Status Vorkurse
    Status Sonstiges (Sprachen)
  Status Neuerdings
  Status Internes VH
    Status Café VH
    Status Verbesserungen
    Status Benutzerbetreuung
    Status Plenum
    Status Datenbank-Forum
    Status Test-Forum
    Status Fragwürdige Inhalte
    Status VH e.V.

Gezeigt werden alle Foren bis zur Tiefe 2

Navigation
 Startseite...
 Neuerdings beta neu
 Forum...
 vorwissen...
 vorkurse...
 Werkzeuge...
 Nachhilfevermittlung beta...
 Online-Spiele beta
 Suchen
 Verein...
 Impressum
Das Projekt
Server und Internetanbindung werden durch Spenden finanziert.
Organisiert wird das Projekt von unserem Koordinatorenteam.
Hunderte Mitglieder helfen ehrenamtlich in unseren moderierten Foren.
Anbieter der Seite ist der gemeinnützige Verein "Vorhilfe.de e.V.".
Partnerseiten
Dt. Schulen im Ausland: Mathe-Seiten:

Open Source FunktionenplotterFunkyPlot: Kostenloser und quelloffener Funktionenplotter für Linux und andere Betriebssysteme
Forum "Praxis" - Zeichenketten ohne Bibo (C++)
Zeichenketten ohne Bibo (C++) < Praxis < Informatik < Vorhilfe
Ansicht: [ geschachtelt ] | ^ Forum "Praxis"  | ^^ Alle Foren  | ^ Forenbaum  | Materialien

Zeichenketten ohne Bibo (C++): Korrektur,Tipp,Idee,Rückfrage
Status: (Frage) beantwortet Status 
Datum: 09:43 Di 16.04.2013
Autor: Mija

Aufgabe
Schreiben Sie ein C++-Programm zum Arbeiten mit Zeichenketten. Das Programm soll aus zwei Modulen bestehen: einem Modul zeichenketten.cpp, das Zeichenkettenfunktionen enthält und einem Hauptmodul zeichenketten_main.cpp zum Testen dieser Funktionen (vorzugsweise mit einer switch-Anweisung). Der Dialog mit dem Benutzer könnte so aussehen:

Test Zeichenkettenfunktionen:
-----------------------------
Eingabe 1. Zeichenkette 1
Eingabe 2. Zeichenkette 2
-----------------------------
Ausgabe 1. Zeichenkette 3
Ausgabe 2. Zeichenkette 4
-----------------------------
Kopieren 2. in die 1. 5
Anhaengen 2. an die 1. 6
Ist 2. ein Teil von 1.? 7
-----------------------------
Ende 0
-----------------------------

Das Modul zeichenketten.cpp soll folgende Prototypen der Funktionen implementieren:

// berechnet die Laenge einer Zeichenkette
[mm] size_t [/mm] laenge(const char *);

// kopiert die Zeichenkette s2 in die Zeichenkette s1
void kopiere(char *s1, const char *s2);

// liefert das Zeichen einer Zeichenkette an der angegeben Position n
// oder [mm] ’\0’, [/mm] wenn n gr"o"ser als die Laenge der Zeichenkette ist
char zeichenAn(const char *s, [mm] size_t [/mm] n);

// haengt die Zeichenkette s2 an die Zeichenkette s1 an,
// solange beide MAXLAENGE nicht ueberschreiten
void anhaengen(char *s1, const char *s2);

// ueberprueft, ob die Zeichenkette s2 ein Teil der Zeichenkette
// s1 ist. Wenn ja: liefert die Position zurueck, an der s2 beginnt,
// -1 sonst
[mm] size_t [/mm] teilVon(const char *s1, const char *s2);

// einlesen einer Zeichenkette ueber die Tastatur
void einlesen(char *s);

// ausgeben einer Zeichenkette, einschlossen in Anfuehrungszeichen
void ausgeben(const char *s);

Erläuterungen und Hinweise:
1) Der Datentyp [mm] size_t [/mm] ist ein Datentyp für Größenangaben, die nicht negativ sein können, wie z.B. die Länge von einem Array. Der Typ entspricht entweder unsigned int oder unsigned long, je nach C++-Umgebung. Die Definition steht im Header <csdtdef>.
2) Mit dem Befehl cin.getline(str, MAXLAENGE); lesen Sie eine Zeichenkette
char* str über die Tastatur ein. Die Konstante MAXLAENGE definieren Sie mit const als eine globale ganzzahlige Konstante, die die maximale Länge für Ihre Zeichenketten angibt.
3) Die Funktionen laenge() und zeichenAn() definieren sie als statische Funktionen des Moduls zeichenketten.cpp.


Hallo, ich habe ein paar Probleme die obenstehenden Funktionen zu schreiben, genauer gesagt die Funktionen kopiere(), anhaengen() und teilVon().

An teilVon() habe ich mich etwas versucht, aber irgendwie klappt das nicht so.

Ganz intuitiv würde ich anhaengen() so schreiben, dass ein String s3 einfach durch Addition aus s1 und s2 beschrieben wird. Aber das geht nicht ohne Bibliotheksfunktionen, oder?

Ganz wichtiger Hinweis: Wir sollen alles ohne die Bilbiotheksfunktionen aus <string> oder dergleichen schreiben.
(Ansonsten würde ich auch weiter kommen ;-) )

Ich würde mich sehr freuen, wenn mir jemand weiterhelfen könnte!


Hier ist mein Code:

zeichenketten.cpp:

1:
2: #include <stdio.h>
3: #include <iostream>
4: #include "zeichenketten.h"
5: #include <cstddef>
6:
7: using namespace std;
8:
9: extern const int MAXLAENGE = 30;
10:
11: //Funktionsdefinitionen
12:
13: //berechnet die Laenge einer Zeichenkette
14: static size_t laenge(const char* s1)
15: {
16: int len=0;
17: for (int i=0; s1='\0'; i++)
18: {
19: len++;
20: }
21: return len;
22: }
23:
24: //kopiert die Zeichenkette s2 in die Zeichenkette s1
25: void kopiere(char* s1, const char* s2)
26: {
27: //cout << strncpy(s1, s2, MAXLAENGE) << endl;
28:
29: }
30:
31: //Hilfsfunktion!
32: //liefert das Zeichen einer Zeichenkette an der angegebenen Position n
33: //oder '\0', wenn n groesser als die Laenge der Zeichenkette ist
34: static char zeichenAn(const char* s, size_t n)
35: {
36: //cout << strchr(s, n) << endl;
37: char zei;
38: if ( n > laenge(s) )
39: {
40: zei = '\0';
41: }
42: else
43: {
44: zei = s[n];
45: }
46: return zei;
47: }
48:
49: //haengt die Zeichenkette s2 an die Zeichenkette s1 an,
50: //solange beide MAXLAENGE nicht ueberschreiten
51: void anhaengen(char* s1, const char* s2)
52: {
53: //cout << strncat(s1, s2, MAXLAENGE-strlen(s1)) << endl;
54:
55: }
56:
57: //Ueberprueft, ob die Zeichenkette s2 ein Teil der Zeichenkette s1 ist.
58: //Wenn ja, liefert die Position zurueck, an der s2 beginnt, -1 sonst
59: size_t teilVon(const char* s1, const char* s2)
60: {
61: /*cout << strstr(s1, s2) << endl;
62: return (size_t) strstr(s1, s2);*/
63: for (int i=0,k=0; i,k<laenge(s1); )
64: {
65: if (s1[i]=s2[k])
66: {
67: i++; k++;
68: }
69: else
70: {
71: i++;
72: }
73: }
74: }
75:
76: //einlesen einer Zeichenkette ueber die Tastatur
77: void einlesen(char* s)
78: {
79: cin.getline(s, MAXLAENGE);
80: }
81:
82: //ausgeben einer Zeichenkette, eingeschlossen in Anfuehrungszeichen
83: void ausgeben(const char* s)
84: {
85: cout << "Die berechnete Zeichenkette lautet: \"" << s << "\"" << endl; //Anführungszeichen werden mit \" erzeugt
86: }


zeichenketten_main.cpp :

1:
2: #include <stdio.h>
3: #include <iostream>
4: #include "zeichenketten.h"
5:
6: using namespace std;
7:
8: extern const int MAXLAENGE = 30;
9:
10: //Main-Programm
11: int main(void)
12: {
13: char zeichenkette1[MAXLAENGE], zeichenkette2[MAXLAENGE]; //Strings als Arrays von Chars definieren
14: unsigned int wahl;
15:
16: cout << "Test Zeichenkettenfunktionen:" << endl;
17: cout << "-----------------------------" << endl;
18: cout << "Eingabe 1. Zeichenkette  1" << endl;
19: cout << "Eingabe 2. Zeichenkette  2" << endl;
20: cout << "-----------------------------" << endl;
21: cout << "Ausgabe 1. Zeichenkette  3" << endl;
22: cout << "Ausgabe 2. Zeichenkette  4" << endl;
23: cout << "-----------------------------" << endl;
24: cout << "Kopieren 2. in die 1.  5" << endl;
25: cout << "Kopieren 2. an die 1.  6" << endl;
26: cout << "Ist 2. ein Teil von 1.?  7" << endl;
27: cout << "-----------------------------" << endl;
28: cout << "Ende  0" << endl;
29: cout << "-----------------------------" << endl;
30:
31: cin >> wahl;
32:
33: switch(wahl)
34: {
35: case 1: einlesen(zeichenkette1); break;
36: case 2: einlesen(zeichenkette2); break;
37: case 3: ausgeben(zeichenkette1); break;
38: case 4: ausgeben(zeichenkette2); break;
39: case 5: kopiere(zeichenkette1, zeichenkette2); break;
40: case 6: anhaengen(zeichenkette1, zeichenkette2); break;
41: case 7: teilVon(zeichenkette1, zeichenkette2); break;
42: case 0: cout << "Ende." << endl; break;
43: default: cout << "Ungueltige Eingabe!" << endl; break;
44: }
45:
46: return 0;
47: }


zeichenketten.h :
1:
2: //Funktionsdeklarationen
3:
4: static size_t laenge(const char*);
5: void kopiere(char* s1, const char* s2);
6: static char zeichenAn(const char* s, size_t n);
7: void anhaengen(char* s1, const char* s2);
8: size_t teilVon(const char* s1, const char* s2);
9: void einlesen(char* s);
10: void ausgeben(const char* s);
11:
12: extern const int MAXLAENGE;


        
Bezug
Zeichenketten ohne Bibo (C++): Antwort
Status: (Antwort) fertig Status 
Datum: 12:00 Di 16.04.2013
Autor: Event_Horizon

Hallo!

>  
> Ganz intuitiv würde ich anhaengen() so schreiben, dass ein
> String s3 einfach durch Addition aus s1 und s2 beschrieben
> wird. Aber das geht nicht ohne Bibliotheksfunktionen,
> oder?
>  
> Ganz wichtiger Hinweis: Wir sollen alles ohne die
> Bilbiotheksfunktionen aus <string> oder dergleichen
> schreiben.
>  (Ansonsten würde ich auch weiter kommen ;-) )
>  
> Ich würde mich sehr freuen, wenn mir jemand weiterhelfen
> könnte!
>  
>
> Hier ist mein Code:
>  
> zeichenketten.cpp:
>  
> [code]
>  #include <stdio.h>
>  #include <iostream>
>  #include "zeichenketten.h"
>  #include <cstddef>
>  
> using namespace std;
>  
> extern const int MAXLAENGE = 30;
>  
> //Funktionsdefinitionen
>  
> //berechnet die Laenge einer Zeichenkette
>  static [mm]size_t[/mm]Eingabefehler: "{" und "}" müssen immer paarweise auftreten, es wurde aber ein Teil ohne Entsprechung gefunden (siehe rote Markierung)

laenge(const char* s1)

>  {
>   int len=0;
>   for (int i=0; [mm]s1='\0';[/mm]Eingabefehler: "{" und "}" müssen immer paarweise auftreten, es wurde aber ein Teil ohne Entsprechung gefunden (siehe rote Markierung)

i++)

>   {
>   len++;
>   }
>   return len;
>  }

Du meinst eher

for (int i=0; s1[i]!='\0'; i++)

denk dran: s1 ist nur ein Pointer auf das erste char im String. das Zeichen selbst bekommst du mit s1[0], alle weiteren mit s1[1], s1[2], ...

Aber das geht noch kürzer:

1:
2: int len;
3: for(len=0; s1[len]!='\0';len++){}
4: return len;





>  
> //kopiert die Zeichenkette s2 in die Zeichenkette s1
>  void kopiere(char* s1, const char* s2)
>  {
>   //cout << strncpy(s1, s2, MAXLAENGE) << endl;
>  
> }
>  

Letztendlich kannst du von der Funktion laenge() ausgehen, und die modifizieren. Hinweis:
Du kannst die Zeichen einzeln rüber kopieren: s1[i]=s2[i]
Wichtig: Wie groß darf i werden?






> //haengt die Zeichenkette s2 an die Zeichenkette s1 an,
>  //solange beide MAXLAENGE nicht ueberschreiten
>  void anhaengen(char* s1, const char* s2)
>  {
>   //cout << strncat(s1, s2, MAXLAENGE-strlen(s1)) << endl;
>  
> }
>  

Wie du selbst sagst: Einfach addieren geht nicht. Du hast zwei Bereiche im Speicher, und benötigst einen neuen, zusammenhängenden, in den beide Strings rein passen.

Leider geht sowas wie

1: size_t n=5;
2: char neuerString[n];


NICHT, denn das geht nur, wenn der Compiler bereits weiß, wir groß n ist. Wird n aber erst im laufenden Programm berechnet, geht das nicht.

In C++ machst du das daher so:

1: size_t n=5;
2: char *neuerString = new char[n];


In C so:

1: size_t n=5;
2: char *neuerString = malloc(n);



Und dann kopierst du erst den ersten String zeichenweise  da rein, und dann den zweiten da hinter. Paß hier mit dem \0 auf, das steckt ja auch irgemdwo im String, und muß auch richtig rüber!

Ich würde sagen, daß du dich hiermit erstmal beschäftigen solltest, und dann schaun wir mal, wie das mit dem String im String finden funktioniert.

Bezug
                
Bezug
Zeichenketten ohne Bibo (C++): Frage (beantwortet)
Status: (Frage) beantwortet Status 
Datum: 12:46 Di 16.04.2013
Autor: Mija

Hallo, ich habe es mal mit Hilfe deiner Beschreibungen versucht.

Wie sieht das aus?

1: #include <stdio.h>
2: #include <iostream>
3: #include "zeichenketten.h"
4: #include <cstddef>
5:
6: using namespace std;
7:
8: extern const int MAXLAENGE = 30;
9:
10: //Funktionsdefinitionen
11:
12: //berechnet die Laenge einer Zeichenkette
13: static size_t laenge(const char* s1)
14: {
15: int len=0;
16: for (int len=0; s1[len]!='\0'; len++)
17: {} //bleibt leer
18: return len;
19: }
20:
21: //kopiert die Zeichenkette s2 in die Zeichenkette s1
22: void kopiere(char* s1, const char* s2)
23: {
24: //cout << strncpy(s1, s2, MAXLAENGE) << endl;
25: if ( laenge(s1) <= laenge(s2) )
26: {
27: for (int i=0; s2[i]!='\0';i++) //oder i<laenge(s2) als Abbruchbedingung?
28: {
29: s1[i] = s2[i];
30: }
31: }
32: else
33: {
34: for (int i=0; s1[i]!='\0';i++) //oder i<laenge(s1) als Abbruchbedingung?
35: {
36: s1[i] = s2[i];
37: }
38: }
39: }
40:
41: //Hilfsfunktion!
42: //liefert das Zeichen einer Zeichenkette an der angegebenen Position n
43: //oder '\0', wenn n groesser als die Laenge der Zeichenkette ist
44: static char zeichenAn(const char* s, size_t n)
45: {
46: //cout << strchr(s, n) << endl;
47: char zei;
48: if ( n > laenge(s) )
49: {
50: zei = '\0';
51: }
52: else
53: {
54: zei = s[n];
55: }
56: return zei;
57: }
58:
59: //haengt die Zeichenkette s2 an die Zeichenkette s1 an,
60: //solange beide MAXLAENGE nicht ueberschreiten
61: void anhaengen(char* s1, const char* s2)
62: {
63: //cout << strncat(s1, s2, MAXLAENGE-strlen(s1)) << endl;
64: unsigned int i=0;
65: unsigned int n = laenge(s1)+laenge(s2);
66: char *neuerString = new char[n];
67: for (i=0; i<laenge(s1); i++)
68: {
69: neuerString[i] = s1[i];
70: }
71: for (unsigned int k=i+1, i=0; k<n; k++)
72: {
73: neuerString[k] = s1[i];
74: }
75: }
76:
77: //Ueberprueft, ob die Zeichenkette s2 ein Teil der Zeichenkette s1 ist.
78: //Wenn ja, liefert die Position zurueck, an der s2 beginnt, -1 sonst
79: size_t teilVon(const char* s1, const char* s2)
80: {
81: /*cout << strstr(s1, s2) << endl;
82: return (size_t) strstr(s1, s2);*/
83: for (int i=0,k=0; i,k<laenge(s1); )
84: {
85: if (s1[i]=s2[k])
86: {
87: i++; k++;
88: }
89: else
90: {
91: i++;
92: }
93: }
94: }
95:
96: //einlesen einer Zeichenkette ueber die Tastatur
97: void einlesen(char* s)
98: {
99: cin.getline(s, MAXLAENGE);
100: }
101:
102: //ausgeben einer Zeichenkette, eingeschlossen in Anfuehrungszeichen
103: void ausgeben(const char* s)
104: {
105: cout << "Die berechnete Zeichenkette lautet: \"" << s << "\"" << endl; //Anführungszeichen werden mit \" erzeugt
106: }


Bezug
                        
Bezug
Zeichenketten ohne Bibo (C++): Antwort
Status: (Antwort) fertig Status 
Datum: 13:48 Di 16.04.2013
Autor: Event_Horizon

Hallo!

Erstmal muß ich mich entschuldigen, ich habe eben etwas Mist geschrieben

Ich habe mich gewundert, wie das Ergebnis einer Funktion überhaupt zurück gegen werden soll, also wie die main nach dem Aufruf von anhaengen() denn an das Ergebnis kommen soll...

Letztendlich werden alle Strings mit einer Länge von MAXLAENGE angelegt.

Beim Anhängen kannst du also bei zwei Strings doch hingehen, und die Zeichen des zweiten direkt hinter die Zeichen des ersten hängen

Beispiel: Du hast zwei Zeichenketten a=eins0 und b=zwei0.

Jetzt kannst du einfach folgendes machen:

a[4]=b[0]  // =z
a[5]=b[1]  // =w
a[6]=b[2]  // =e
a[7]=b[3]  // =i
a[8]='\0';

also zusammen: einszwei0

Wichtig ist, daß hinter jedem Zeichen ja noch ein Nullbyte steht.



Genauso kannst du in der Kopierfunktion vorgehen, diesmal aber so:


a[0]=b[0]  // =z
a[1]=b[1]  // =w
a[2]=b[2]  // =e
a[3]=b[3]  // =i
a[4]='\0';



Bezug
                                
Bezug
Zeichenketten ohne Bibo (C++): Frage (beantwortet)
Status: (Frage) beantwortet Status 
Datum: 14:30 Di 16.04.2013
Autor: Mija

Ok,  danke,  das habe ich soweit verstanden.
Könntest du mir bitte noch bei der Funktion teilVon() helfen? Sehe ich das richtig,  dass es da einige Fallunterscheidungen geben muss?

Bezug
                                        
Bezug
Zeichenketten ohne Bibo (C++): Antwort
Status: (Antwort) fertig Status 
Datum: 15:48 Di 16.04.2013
Autor: Event_Horizon

Hallo!


Hmmm, ich frag mal so: Woher hast du das Code-Segment, das da in deiner TeilVon() steht?

Im Prinzip kopiert das den zweiten String in den ersten. Der Trick liegt in dem if(s1[i] = s2[k]) : Der Wert von  s2[k] wird auf jeden Fall in s1[i] geschrieben, und das if prüft nur, welcher Wert das denn ist. Sobald das Ende des Strings erreicht wird (Nullbyte) greift nur noch das else. Und das rattert s1 bis zum Ende durch, macht aber nix mehr.
Aber dieser Code sucht NICHT nach einem Teilstring.

Ich würde an deiner Stelle auch Abstand nehmen, von so merkwürdigen Sachen wie den zwei Anweisungen in der FOR-Klammer etc, sondern möglichst einfach programmieren.

Zu der Aufgabe: Angenommen, du suchst "zehn" in "dreizehn", dann schreibst du "zehn" unter "dreizehn", und schiebst es immer weiter nach rechts. Dann überprüfst du, ob die übereinander stehenden Buchstaben gleich sind:

    dreizehn
    zehn

    dreizehn
     zehn

    dreizehn
      zehn

    dreizehn
       zehn

    dreizehn
        zehn   => PASST!

Programmiertechnisch brauchst du zwei FOR-Schleifen ineinander, die eine vergleicht die vier Buchstaben des unteren Strings mit denen, die darüber liegen. Die andere sorgt für die Verschiebung.

Natürlich kann man das mit jeder Menge IF-Anweisungen spicken (zweiter String länger als erster etc.), und muß sich auch überlegen, wie man reagiert, wenn man nen Treffer landet, oder wenn der String nicht zu finden ist. Aber eins nach dem anderen!

Bezug
                                                
Bezug
Zeichenketten ohne Bibo (C++): Frage (beantwortet)
Status: (Frage) beantwortet Status 
Datum: 07:07 Mi 17.04.2013
Autor: Mija

Hallo, ich habe schonmal versucht meine Funktion teilVon() noch weiter zu schreiben.

Wie sieht das aus?
Wo und wie kann ich jetzt die Stelle zurückgeben, an der s2 in s1 beginnt?

1: #include <stdio.h>
2: #include <iostream>
3: #include "zeichenketten.h"
4: #include <cstddef>
5:
6: using namespace std;
7:
8: extern const int MAXLAENGE = 30;
9:
10: //Funktionsdefinitionen
11:
12: //berechnet die Laenge einer Zeichenkette
13: static size_t laenge(const char* s1)
14: {
15: int len=0;
16: for (int len=0; s1[len]!='\0'; len++)
17: {} //bleibt leer
18: return len;
19: }
20:
21: //kopiert die Zeichenkette s2 in die Zeichenkette s1
22: void kopiere(char* s1, const char* s2)
23: {
24: //cout << strncpy(s1, s2, MAXLAENGE) << endl;
25: if ( laenge(s1) <= laenge(s2) )
26: {
27: for (int i=0; s2[i]!='\0';i++) //oder i<laenge(s2) als Abbruchbedingung?
28: {
29: s1[i] = s2[i];
30: }
31: }
32: else
33: {
34: for (int i=0; s1[i]!='\0';i++) //oder i<laenge(s1) als Abbruchbedingung?
35: {
36: s1[i] = s2[i];
37: }
38: }
39: }
40:
41: //Hilfsfunktion!
42: //liefert das Zeichen einer Zeichenkette an der angegebenen Position n
43: //oder '\0', wenn n groesser als die Laenge der Zeichenkette ist
44: static char zeichenAn(const char* s, size_t n)
45: {
46: //cout << strchr(s, n) << endl;
47: char zei;
48: if ( n > laenge(s) )
49: {
50: zei = '\0';
51: }
52: else
53: {
54: zei = s[n];
55: }
56: return zei;
57: }
58:
59: //haengt die Zeichenkette s2 an die Zeichenkette s1 an,
60: //solange beide MAXLAENGE nicht ueberschreiten
61: void anhaengen(char* s1, const char* s2)
62: {
63: int i=0;
64: int k=laenge(s1);
65: for (i=0; i<MAXLAENGE; i++)
66: {
67: s1[k+i]=s2[i];
68: }
69: s1[k+i+1] = '\0';
70: }
71:
72: //Ueberprueft, ob die Zeichenkette s2 ein Teil der Zeichenkette s1 ist.
73: //Wenn ja, liefert die Position zurueck, an der s2 beginnt, -1 sonst
74: size_t teilVon(const char* s1, const char* s2)
75: {
76: /*cout << strstr(s1, s2) << endl;
77: return (size_t) strstr(s1, s2);*/
78: int anzTreffer=0;
79:
80: if (laenge(s2)>laenge(s1))
81: {
82: cout << s2 << " ist nicht Teil von " << s1 << endl;
83: return -1;
84: }
85: else
86: {
87: for (unsigned int i=0; i < laenge(s1); i++)
88: {
89: for (unsigned int k=0; k < laenge(s2); k++)
90: {
91: if (s1[k]==s2[k])
92: {
93: anzTreffer++;
94: }
95: }
96: }
97: }
98:
99: if (anzTreffer==laenge(s2))
100: {
101: cout << s2 << " ist Teil von " << s1 << endl;
102: }
103: }
104:
105: //einlesen einer Zeichenkette ueber die Tastatur
106: void einlesen(char* s)
107: {
108: cin.getline(s, MAXLAENGE);
109: }
110:
111: //ausgeben einer Zeichenkette, eingeschlossen in Anfuehrungszeichen
112: void ausgeben(const char* s)
113: {
114: cout << "Die berechnete Zeichenkette lautet: \"" << s << "\"" << endl; //Anführungszeichen werden mit \" erzeugt
115: }


Bezug
                                                        
Bezug
Zeichenketten ohne Bibo (C++): Antwort
Status: (Antwort) fertig Status 
Datum: 09:12 Mi 17.04.2013
Autor: Event_Horizon

Hallo!


1:
2: size_t teilVon(const char* s1, const char* s2)
3: {
4: int anzTreffer=0;
5:
6: if (laenge(s2)>laenge(s1))
7: {
8: cout << s2 << " ist nicht Teil von " << s1 << endl;
9: return -1;
10: }
11: else

Im Prinzip kann man sich das else sparen. Denn wenn die Zeile mit dem Return ausgeführt wird, wird die Funktion sofort beendet, und würde niemals bei dem else vorbei schauen. Aber das ist egal.
1:
2: {
3: for (unsigned int i=0; i < laenge(s1); i++)

Hier ein Tipp: Wennn s1 zehn Zeichen lang ist, und s2 fünf, dann macht es keinen Sinn, in s1 ab der achten Stelle noch zu suchen.  Damit kann man Rechenzeit sparen, aber der Code funktioniert auch so.
1:
2: {
3: for (unsigned int k=0; k < laenge(s2); k++)
4: {
5: if (s1[k]==s2[k])

Hier fehlt noch die Sache mit dem Verschieben. Da fehlt noch was mit einem i. Guck mal in deine Funktion anhaengen() !

Und: Beim nächsten Durchlauf der i-Schleife hat anzTreffer noch den alten Wert, und geht damit in die k-Schleife. Also: Vor der k-Schleife =0 setzen!
1:
2: {
3: anzTreffer++;
4: }
5: }
6: }
7: }
8:
9: if (anzTreffer==laenge(s2))
10: {
11: cout << s2 << " ist Teil von " << s1 << endl;

Das steht zu weit unten. Es gehört direkt unter die k-Schleife, denn genau da willst du ja prüfen, ob in beiden Strings genau so viele zeichen übereinstimmen, wie der Suchstring lang ist. In dem Fall steht die Startposition in i, das heißt, du machst ein return i; . Und die allerletzte Zeile der Funktion, vor der schließenden Klammer, sollte ein return -1; enthalten, denn wenn vorher nichts gefunden und die Funktion abgebrochen wurde, soll ja -1 zurück gegeben werden.
1:
2: }
3:


Bezug
                                                                
Bezug
Zeichenketten ohne Bibo (C++): Frage (beantwortet)
Status: (Frage) beantwortet Status 
Datum: 10:15 Mi 17.04.2013
Autor: Mija

Hallo, nach der Bearbeitung mit deinen Hinweisen sieht es nun so aus:

1: #include <stdio.h>
2: #include <iostream>
3: #include "zeichenketten.h"
4: #include <cstddef>
5:
6: using namespace std;
7:
8: extern const int MAXLAENGE = 30;
9:
10: //Funktionsdefinitionen
11:
12: //berechnet die Laenge einer Zeichenkette
13: static size_t laenge(const char* s1)
14: {
15: int len=0;
16: for (int len=0; s1[len]!='\0'; len++)
17: {} //bleibt leer
18: return len;
19: }
20:
21: //kopiert die Zeichenkette s2 in die Zeichenkette s1
22: void kopiere(char* s1, const char* s2)
23: {
24: //cout << strncpy(s1, s2, MAXLAENGE) << endl;
25:
26: for (int i=0; laenge(s2); i++)
27: {
28: s1[i] = s2[i];
29: }
30:
31: //if ( laenge(s1) <= laenge(s2) )
32: //{
33: // for (int i=0; s2[i]!='\0';i++) //oder i<laenge(s2) als Abbruchbedingung?
34: // {
35: // s1[i] = s2[i];
36: // }
37: //}
38: //else
39: //{
40: // for (int i=0; s1[i]!='\0';i++) //oder i<laenge(s1) als Abbruchbedingung?
41: // {
42: // s1[i] = s2[i];
43: // }
44: //}
45: }
46:
47: //Hilfsfunktion!
48: //liefert das Zeichen einer Zeichenkette an der angegebenen Position n
49: //oder '\0', wenn n groesser als die Laenge der Zeichenkette ist
50: static char zeichenAn(const char* s, size_t n)
51: {
52: //cout << strchr(s, n) << endl;
53: char zei;
54: if ( n > laenge(s) )
55: {
56: zei = '\0';
57: }
58: else
59: {
60: zei = s[n];
61: }
62: return zei;
63: }
64:
65: //haengt die Zeichenkette s2 an die Zeichenkette s1 an,
66: //solange beide MAXLAENGE nicht ueberschreiten
67: void anhaengen(char* s1, const char* s2)
68: {
69: unsigned int i=0;
70: unsigned int k=laenge(s1);
71: if (laenge(s1)<=MAXLAENGE && laenge(s2)<=MAXLAENGE)
72: {
73: for (i=0; i<laenge(s2); i++)
74: {
75: s1[k+i]=s2[i];
76: }
77: s1[k+i+1] = '\0';
78: }
79: }
80:
81: //Ueberprueft, ob die Zeichenkette s2 ein Teil der Zeichenkette s1 ist.
82: //Wenn ja, liefert die Position zurueck, an der s2 beginnt, -1 sonst
83: size_t teilVon(const char* s1, const char* s2)
84: {
85: /*cout << strstr(s1, s2) << endl;
86: return (size_t) strstr(s1, s2);*/
87: int anzTreffer=0;
88:
89: if (laenge(s2)>laenge(s1))
90: {
91: cout << s2 << " ist nicht Teil von " << s1 << endl;
92: return -1;
93: }
94: else
95: {
96: for (unsigned int i=0; i < laenge(s1); i++)
97: {
98: i=0;
99: for (unsigned int k=0; k < laenge(s2); k++)
100: {
101: if (s1[k+i]==s2[k])
102: {
103: anzTreffer++;
104: }
105: }
106:
107: if (anzTreffer==laenge(s2))
108: {
109: cout << s2 << " ist Teil von " << s1 << endl;
110: return i; //muss noch ersetzt werden
111: }
112: else
113: {
114: cout << s2 << " ist nicht Teil von " << s1 << endl;
115: return -1;
116: }
117: }
118: }
119: return -1;
120: }
121:
122: //einlesen einer Zeichenkette ueber die Tastatur
123: void einlesen(char* s)
124: {
125: cin.getline(s, MAXLAENGE);
126: }
127:
128: //ausgeben einer Zeichenkette, eingeschlossen in Anfuehrungszeichen
129: void ausgeben(const char* s)
130: {
131: cout << "Die berechnete Zeichenkette lautet: \"" << s << "\"" << endl; //Anführungszeichen werden mit \" erzeugt
132: }


Haut das alles so hin?

Ich kann das Programm leider noch nicht testen, da ich immer den Fehler

Fehler 1 error LNK2005: "int const MAXLAENGE" (?MAXLAENGE@@3HB) ist bereits in zeichenketten.obj [mm] definiert. H:\PR2AB\Arbeitsblatt2\Staeker_Heike_a1_1\zeichenketten_main.obj [/mm]

bekomme.
Muss ich MAXLAENGE anders nennen? (auch wenn es in der Aufgabenstellung so steht).

Bezug
                                                                        
Bezug
Zeichenketten ohne Bibo (C++): Antwort
Status: (Antwort) fertig Status 
Datum: 11:35 Mi 17.04.2013
Autor: Event_Horizon

Eingabefehler: "{" und "}" müssen immer paarweise auftreten, es wurde aber ein Teil ohne Entsprechung gefunden (siehe rote Markierung)

Hallo!

Die Zeile

extern const int MAXLAENGE

teilt dem Compiler mit, daß in dieser Datei eine variable vom Typ const int mit dem Namen MAXLAENGE benutzt wird. Diese Variable wird hier aber nicht deklariert, sondern wo anders, eben "extern"

Deshalb sollte das bei dir so aussehen:


----- In der main.cpp

const int MAXLAENGE=30;

Hiermit wird die Variable ganz normal angelegt (global!) und mit einem Wert versehen.

----- In der Zeichen.cpp

extern const int MAXLAENGE

Hiermit wird nur mitgeteilt, daß es <irgendwo anders> diese Variable schon gibt, und daß die genutzt werden soll.


Hilft das?


Ansonsten: Wie sieht deine main.cpp aus? Und es gibt noch eine zeichenkette.h. Wie sieht die aus?

Es gibt da nämlich noch ein paar andere Fallstricke.


Zum Code:

>  71: if (laenge(s1)<=MAXLAENGE && laenge(s2)<=MAXLAENGE)

Nein, eher so:

if(lange(s1)+laenge(s2) <MAXLAENGE-1)

Denn du mußt schaun, ob die beiden Strings zusammen nicht zu lang werden. Und '-1', weil du ja noch Platz für das Nullbyte brauchst.



96: for (unsigned int i=0; i < laenge(s1); i++)
97: {
98: i=0;

neee, anzTreffer=0; !


Ansonsten sehe ich jetzt nichts, aber du müßtest es jetzt schaffen, den Code zu kompilieren, und dann prüfen, ob die Funktionen auch alle das tun, was sie sollen. Für gewöhnlich tauchen dabei auch noch Fehler auf, auch wenn man den Code noch so gut durchgelesen hat.

Bezug
                                                                                
Bezug
Zeichenketten ohne Bibo (C++): Frage (beantwortet)
Status: (Frage) beantwortet Status 
Datum: 12:30 Mi 17.04.2013
Autor: Mija

Danke, ich kann das Programm jetzt richtig kompilieren und testen! :-)

Nun habe ich noch eine Frage zur zeichenketten_main.cpp.
case 5, 6 und 7 klappt noch nicht. Wie kann ich denn z.B. die Funktion kopiere() anwenden, ohne dass ich z.B. vorher zei1 = einlesen(zeichenkette1) und zei2 = einlesen(zeichenkette2) angeben muss? (denn einlesen ist ja eine void-Funktion.
Irgendwie muss ich doch die eingelesenen Zeichenketten an die Funktion kopiere() (und die anderen) übergeben.

Hier ist mein Code zur zeichenkette_main.cpp:

1: #include <stdio.h>
2: #include <iostream>
3: #include "zeichenketten.h"
4:
5: using namespace std;
6:
7: extern const int MAXLAENGE = 30;
8:
9: //Main-Programm
10: int main(void)
11: {
12: char zeichenkette1[MAXLAENGE], zeichenkette2[MAXLAENGE]; //Strings als Arrays von Chars definieren
13: unsigned int wahl;
14:
15: do
16: {
17:
18: cout << "Test Zeichenkettenfunktionen:" << endl;
19: cout << "-----------------------------" << endl;
20: cout << "Eingabe 1. Zeichenkette  1" << endl;
21: cout << "Eingabe 2. Zeichenkette  2" << endl;
22: cout << "-----------------------------" << endl;
23: cout << "Ausgabe 1. Zeichenkette  3" << endl;
24: cout << "Ausgabe 2. Zeichenkette  4" << endl;
25: cout << "-----------------------------" << endl;
26: cout << "Kopieren 2. in die 1.    5" << endl;
27: cout << "Kopieren 2. an die 1.    6" << endl;
28: cout << "Ist 2. ein Teil von 1.?  7" << endl;
29: cout << "-----------------------------" << endl;
30: cout << "Ende          0" << endl;
31: cout << "-----------------------------" << endl << endl;
32:
33: cin >> wahl;
34: cout << endl;
35:
36: switch(wahl)
37: {
38: case 1: einlesen(zeichenkette1); break;
39: case 2: einlesen(zeichenkette2); break;
40: case 3: einlesen(zeichenkette1); ausgeben(zeichenkette1); break;
41: case 4: einlesen(zeichenkette2); ausgeben(zeichenkette2); break;
42: case 5: einlesen(zeichenkette1); einlesen(zeichenkette2); kopiere(zeichenkette1, zeichenkette2); break;
43: case 6: anhaengen(zeichenkette1, zeichenkette2); break;
44: case 7: teilVon(zeichenkette1, zeichenkette2); break;
45: case 0: cout << "Ende." << endl; break;
46: default: cout << "Ungueltige Eingabe!" << endl; break;
47: }
48:
49: cout << endl << endl << endl;
50:
51: } while(wahl!=0);
52:
53: return 0;
54: }


zeichenketten.cpp:
1: #include <stdio.h>
2: #include <iostream>
3: #include "zeichenketten.h"
4: #include <cstddef>
5:
6: using namespace std;
7:
8: extern const int MAXLAENGE;
9:
10: //Funktionsdefinitionen
11:
12: //berechnet die Laenge einer Zeichenkette
13: static size_t laenge(const char* s1)
14: {
15: int len=0;
16: for (int len=0; s1[len]!='\0'; len++)
17: {} //bleibt leer
18: return len;
19: }
20:
21: //kopiert die Zeichenkette s2 in die Zeichenkette s1
22: void kopiere(char* s1, const char* s2)
23: {
24: //cout << strncpy(s1, s2, MAXLAENGE) << endl;
25: for (unsigned int i=0; i<laenge(s2); i++)
26: {
27: s1[i] = s2[i];
28: }
29:
30: //if ( laenge(s1) <= laenge(s2) )
31: //{
32: // for (int i=0; s2[i]!='\0';i++) //oder i<laenge(s2) als Abbruchbedingung?
33: // {
34: // s1[i] = s2[i];
35: // }
36: //}
37: //else
38: //{
39: // for (int i=0; s1[i]!='\0';i++) //oder i<laenge(s1) als Abbruchbedingung?
40: // {
41: // s1[i] = s2[i];
42: // }
43: //}
44: }
45:
46: //Hilfsfunktion!
47: //liefert das Zeichen einer Zeichenkette an der angegebenen Position n
48: //oder '\0', wenn n groesser als die Laenge der Zeichenkette ist
49: static char zeichenAn(const char* s, size_t n)
50: {
51: //cout << strchr(s, n) << endl;
52: char zei;
53: if ( n > laenge(s) )
54: {
55: zei = '\0';
56: }
57: else
58: {
59: zei = s[n];
60: }
61: return zei;
62: }
63:
64: //haengt die Zeichenkette s2 an die Zeichenkette s1 an,
65: //solange beide MAXLAENGE nicht ueberschreiten
66: void anhaengen(char* s1, const char* s2)
67: {
68: unsigned int i;
69: unsigned int k=laenge(s1);
70: if ( laenge(s1)+laenge(s2) < (unsigned int) MAXLAENGE-1 )
71: {
72: for (i=0; i<laenge(s2); i++)
73: {
74: s1[k+i]=s2[i];
75: }
76: s1[k+i+1] = '\0';
77: }
78: }
79:
80: //Ueberprueft, ob die Zeichenkette s2 ein Teil der Zeichenkette s1 ist.
81: //Wenn ja, liefert die Position zurueck, an der s2 beginnt, -1 sonst
82: size_t teilVon(const char* s1, const char* s2)
83: {
84: /*cout << strstr(s1, s2) << endl;
85: return (size_t) strstr(s1, s2);*/
86: int anzTreffer=0;
87:
88: if (laenge(s2)>laenge(s1))
89: {
90: cout << s2 << " ist nicht Teil von " << s1 << endl;
91: return -1;
92: }
93: else
94: {
95: for (unsigned int i=0; i < laenge(s1); i++)
96: {
97: anzTreffer=0;
98: for (unsigned int k=0; k < laenge(s2); k++)
99: {
100: if (s1[k+i]==s2[k])
101: {
102: anzTreffer++;
103: }
104: }
105:
106: if (anzTreffer==laenge(s2))
107: {
108: cout << s2 << " ist Teil von " << s1 << endl;
109: return i; //muss noch ersetzt werden
110: }
111: else
112: {
113: cout << s2 << " ist nicht Teil von " << s1 << endl;
114: return -1;
115: }
116: }
117: }
118: return -1;
119: }
120:
121: //einlesen einer Zeichenkette ueber die Tastatur
122: void einlesen(char* s)
123: {
124: cout << "Ihre Zeichenkette: ";
125: cin.get();
126: cin.getline(s, MAXLAENGE);
127: }
128:
129: //ausgeben einer Zeichenkette, eingeschlossen in Anfuehrungszeichen
130: void ausgeben(const char* s)
131: {
132: cout << endl << "Die berechnete Zeichenkette lautet: \"" << s << "\"" << endl; //Anführungszeichen werden mit \" erzeugt
133: }


Bezug
                                                                                        
Bezug
Zeichenketten ohne Bibo (C++): Antwort
Status: (Antwort) fertig Status 
Datum: 12:59 Mi 17.04.2013
Autor: Event_Horizon

Hallo!

Das mit der Übergabe ist trickreich, das stimmt.

Denk dran, zeichenkette1 ist ein char-Pointer, der die Speicheradresse  enthält, ab der die einzelnen Chars im Speicher stehen. Es enthält nicht den eigentlichen String (weil das kein echter Datentyp ist), aber man bezeichnet solche char-Pointer gerne als String.

das einlesen() bekommt genau diese Speicheradresse, und das getline() wird den eingelesenen String an genau diese Stelle schreiben.

Das heißt, nach

einlesen(zeichenkette1);

kannst du gleich

ausgeben(zeichenkette1);

aufrufen, so weit ist das richtig.

Ich sehe aber grade in deiner einlesen(), daß da ein cin.get() steht. Das ist ein Problem, du benötigst nur das cin.getline().



Aber du hast noch einen Denkfehler in der main.cpp:

in jeder Case-Anweisung soll exakt das gemacht werden, was das Menü vorgibt.

Das heißt, über die Ziffern 1 und 2 sollten die beiden Strings eingegeben werden, und über 6 sollten die vorher eingegebenen Strings aneinander gehängt werden. Der case 6 sollte daher nur aus anhaengen() bestehen, ohne eingabe()

Und: Ganz am Anfang solltest du

zeichenkette1[0]=0;

einfügen. Damit kannst du sicher sein, daß dieser String quasi leer ist. Sonst weiß man nie, was beim Aufruf von anhaengen() passiert, wenn vorher nichts eingelesen wurde...

Bezug
                                                                                                
Bezug
Zeichenketten ohne Bibo (C++): Frage (beantwortet)
Status: (Frage) beantwortet Status 
Datum: 13:12 Mi 17.04.2013
Autor: Mija

Wenn ich das cin.get() wegnehme und nur cin.getline(s, MAXLAENGE) dastehen habe, dann kann ich komischerweise nach der Eingabe von wahl keine Zeichenkette eingeben, sondern dann erscheint gleich wieder das Menü für die nächste wahl-Eingabe.

Woran liegt das?

Wenn ich das cin.get() stehen lasse, klappt das einlesen und über Punkt 3 und 4 kann ich die Zeichenketten auch wieder ausgeben lassen.
Fall 5, 6 und 7 funktionieren allerdings garnicht. Da springt er gleich wieder zum nächsten Menü.

Bezug
                                                                                                        
Bezug
Zeichenketten ohne Bibo (C++): Frage (beantwortet)
Status: (Frage) beantwortet Status 
Datum: 14:38 Mi 17.04.2013
Autor: Mija

Hallo, also ich habe das cin.get() jetzt erstmal stehengelassen.

Meine Funktion kopiere() funktioniert wunderbar.

Mit der Funktion anhaengen() habe ich das Problem, dass immer nur der erste Charakter von der ersten Zeichenkette ausgegeben wird.
Wo ist da mein Fehler?

Bei der Funktion teilVon() habe ich das Problem, dass immer rauskommt, dass die zweite Zeichenkette kein Teil der ersten ist, egal ob das tatsächlich zutrifft oder nicht. Steht vielleicht das return -1 dort vor der letzten Klammer falsch? Wenn ich das wegnehme, bekomme ich allerdings die Fehlermeldung, dass nicht alle Steuerelemente einen Wert zurückbekommen.
Ich kann mir außerdem nicht erklären, dass wir nie in die if-Schleife mit anzTreffer==laenge(s2) hineinkommen.

Wo sind da meine Fehler?

1: #include <stdio.h>
2: #include <iostream>
3: #include "zeichenketten.h"
4: #include <cstddef>
5:
6: using namespace std;
7:
8: extern const int MAXLAENGE;
9:
10: //Funktionsdefinitionen
11:
12: //funktioniert
13: //berechnet die Laenge einer Zeichenkette
14: static size_t laenge(const char* s1)
15: {
16: int len=0;
17: for (int len=0; s1[len]!='\0'; len++)
18: {} //bleibt leer
19: return len;
20: }
21:
22: //funktioniert
23: //kopiert die Zeichenkette s2 in die Zeichenkette s1
24: void kopiere(char* s1, const char* s2)
25: {
26: //for (unsigned int i=0; i<laenge(s2); i++)
27: //{
28: // s1[i] = s2[i];
29: //}
30: //cout << "Berechnete Zeichenkette: " << s1 << endl;
31:
32: if ( laenge(s1) <= laenge(s2) )
33: {
34: for (int i=0; s2[i]!='\0';i++) //oder i<laenge(s2) als Abbruchbedingung?
35: {
36: s1[i] = s2[i];
37: }
38: }
39: else
40: {
41: for (int i=0; s1[i]!='\0';i++) //oder i<laenge(s1) als Abbruchbedingung?
42: {
43: s1[i] = s2[i];
44: }
45: }
46: cout << "Berechnete Zeichenkette: " << s1 << endl;
47: }
48:
49: //funktioniert
50: //Hilfsfunktion!
51: //liefert das Zeichen einer Zeichenkette an der angegebenen Position n
52: //oder '\0', wenn n groesser als die Laenge der Zeichenkette ist
53: static char zeichenAn(const char* s, size_t n)
54: {
55: //cout << strchr(s, n) << endl;
56: char zei;
57: if ( n > laenge(s) )
58: {
59: zei = '\0';
60: }
61: else
62: {
63: zei = s[n];
64: }
65: return zei;
66: }
67:
68: //haengt die Zeichenkette s2 an die Zeichenkette s1 an,
69: //solange beide MAXLAENGE nicht ueberschreiten
70: void anhaengen(char* s1, const char* s2)
71: {
72: unsigned int i;
73: unsigned int k=laenge(s1);
74: if ( laenge(s1)+laenge(s2) < (unsigned int) MAXLAENGE-1 )
75: {
76: for (i=0; i<laenge(s2); i++)
77: {
78: s1[k+i]=s2[i];
79: }
80: s1[k+i+1] = '\0';
81: cout << "Berechnete Zeichenkette: " << s1 << endl;
82: }
83: else
84: {
85: cout << "Maximale Laenge ueberschritten!" << endl;
86: }
87: }
88:
89: //Ueberprueft, ob die Zeichenkette s2 ein Teil der Zeichenkette s1 ist.
90: //Wenn ja, liefert die Position zurueck, an der s2 beginnt, -1 sonst
91: size_t teilVon(const char* s1, const char* s2)
92: {
93: /*cout << strstr(s1, s2) << endl;
94: return (size_t) strstr(s1, s2);*/
95: int anzTreffer=0;
96:
97: if (laenge(s2)>laenge(s1))
98: {
99: cout << s2 << " ist nicht Teil von " << s1 << endl;
100: return -1;
101: }
102: else
103: {
104: for (unsigned int i=0; i < laenge(s1); i++)
105: {
106: anzTreffer=0;
107: for (unsigned int k=0; k < laenge(s2); k++)
108: {
109: if (s1[k+i]==s2[k])
110: {
111: anzTreffer++;
112: }
113: }
114:
115: if (anzTreffer==laenge(s2))
116: {
117: cout << s2 << " ist Teil von " << s1 << endl;
118: cout << s2 << " beginnt an der Stelle " << i << " von " << s1 << endl;
119: return i;
120: }
121: else
122: {
123: cout << s2 << " ist nicht Teil von " << s1 << endl;
124: return -1;
125: }
126: }
127: }
128: cout << s2 << " ist nicht Teil von " << s1 << endl; //Wo muss das
129: return -1; // und das hin?
130: }
131:
132: //einlesen einer Zeichenkette ueber die Tastatur
133: void einlesen(char* s)
134: {
135: //cin.clear();
136: cout << "Ihre Zeichenkette: ";
137: cin.get();
138: cin.getline(s, MAXLAENGE);
139: }
140:
141: //funktioniert
142: //ausgeben einer Zeichenkette, eingeschlossen in Anfuehrungszeichen
143: void ausgeben(const char* s)
144: {
145: cout << endl << "Die berechnete Zeichenkette lautet: \"" << s << "\"" << endl; //Anführungszeichen werden mit \" erzeugt
146: }


Bezug
                                                                                                                
Bezug
Zeichenketten ohne Bibo (C++): Mitteilung
Status: (Mitteilung) Reaktion unnötig Status 
Datum: 16:17 Mi 17.04.2013
Autor: Mija

Hallihallo!

In der Funktion laenge() hatte ich einen kleinen Fehler. Dort ist dann immer 0 als Länge rausgekommen.
Ich habe das korrigiert und nun funktioniert meine Funktion anhaengen().

Mit der Funktion teilVon() habe ich aber nach wie vor immer noch die gleichen Probleme wie im letzten Post beschrieben.
anzTreffer wird warum auch immer in der zweiten for-Schleife in der if-Schleife nicht erhöht.

Ich würde mich freuen, wenn mir dabei jemand noch weiterhelfen könnte und dann bin ich hoffentlich fertig! :-)


1: #include <stdio.h>
2: #include <iostream>
3: #include "zeichenketten.h"
4: #include <cstddef>
5:
6: using namespace std;
7:
8: extern const int MAXLAENGE;
9:
10: //Funktionsdefinitionen
11:
12: //funktioniert
13: //berechnet die Laenge einer Zeichenkette
14: static size_t laenge(const char* s1)
15: {
16: int len=0;
17: for (len=0; s1[len]!='\0'; len++)
18: {} //bleibt leer
19: return len;
20: }
21:
22: //funktioniert
23: //kopiert die Zeichenkette s2 in die Zeichenkette s1
24: void kopiere(char* s1, const char* s2)
25: {
26: for (unsigned int i=0; i<laenge(s2); i++)
27: {
28: s1[i] = s2[i];
29: }
30: cout << "Berechnete Zeichenkette: " << s1 << endl;
31:
32: //kann eigentlich weg
33: /*
34: if ( laenge(s1) <= laenge(s2) )
35: {
36: for (int i=0; s2[i]!='\0';i++) //oder i<laenge(s2) als Abbruchbedingung?
37: {
38: s1[i] = s2[i];
39: }
40: }
41: else
42: {
43: for (int i=0; s1[i]!='\0';i++) //oder i<laenge(s1) als Abbruchbedingung?
44: {
45: s1[i] = s2[i];
46: }
47: }
48: cout << "Berechnete Zeichenkette: " << s1 << endl;
49: */
50: }
51:
52: //funktioniert
53: //Hilfsfunktion!
54: //liefert das Zeichen einer Zeichenkette an der angegebenen Position n
55: //oder '\0', wenn n groesser als die Laenge der Zeichenkette ist
56: static char zeichenAn(const char* s, size_t n)
57: {
58: //cout << strchr(s, n) << endl;
59: char zei;
60: if ( n > laenge(s) )
61: {
62: zei = '\0';
63: }
64: else
65: {
66: zei = s[n];
67: }
68: return zei;
69: }
70:
71: //haengt die Zeichenkette s2 an die Zeichenkette s1 an,
72: //solange beide MAXLAENGE nicht ueberschreiten
73: void anhaengen(char* s1, const char* s2)
74: {
75: unsigned int i, j=0;
76: unsigned int k=laenge(s1);
77:
78: if ( laenge(s1)+laenge(s2) < (unsigned int) MAXLAENGE-1 )
79: {
80: for (i=0; i<laenge(s2); i++)
81: {
82: //s1[k+i]=zeichenAn(s2,i);
83: s1[k+i]=s2[i];
84: }
85:
86: s1[k+i+1] = '\0';
87: cout << "Berechnete Zeichenkette: " << s1 << endl;
88: }
89: else
90: {
91: cout << "Maximale Laenge ueberschritten!" << endl;
92: }
93: }
94:
95: //Ueberprueft, ob die Zeichenkette s2 ein Teil der Zeichenkette s1 ist.
96: //Wenn ja, liefert die Position zurueck, an der s2 beginnt, -1 sonst
97: size_t teilVon(const char* s1, const char* s2)
98: {
99: int anzTreffer=0;
100:
101: if (laenge(s2)>laenge(s1))
102: {
103: cout << s2 << " ist nicht Teil von " << s1 << endl;
104: return -1;
105: }
106: else
107: {
108: for (unsigned int i=0; i < laenge(s1); i++)
109: {
110: anzTreffer=0;
111: for (unsigned int k=0; k < laenge(s2); k++)
112: {
113: if (s1[k+i]==s2[k])
114: {
115: anzTreffer++;
116: }
117: }
118:
119: if (anzTreffer==laenge(s2))
120: {
121: cout << s2 << " ist Teil von " << s1 << endl;
122: cout << s2 << " beginnt an der Stelle " << i << " von " << s1 << endl;
123: return i;
124: }
125: else
126: {
127: cout << s2 << " ist nicht Teil von " << s1 << endl;
128: return -1;
129: }
130: }
131: }
132: //cout << s2 << " ist nicht Teil von " << s1 << endl; //Wo muss das
133: //return -1; // und das hin?
134: return 0;
135: }
136:
137: //einlesen einer Zeichenkette ueber die Tastatur
138: void einlesen(char* s)
139: {
140: //cin.clear();
141: cout << "Ihre Zeichenkette: ";
142: cin.get();
143: cin.getline(s, MAXLAENGE);
144: }
145:
146: //funktioniert
147: //ausgeben einer Zeichenkette, eingeschlossen in Anfuehrungszeichen
148: void ausgeben(const char* s)
149: {
150: cout << endl << "Die berechnete Zeichenkette lautet: \"" << s << "\"" << endl; //Anführungszeichen werden mit \" erzeugt
151: }

Bezug
                                                                                                                
Bezug
Zeichenketten ohne Bibo (C++): Antwort
Status: (Antwort) fertig Status 
Datum: 21:57 Mi 17.04.2013
Autor: Event_Horizon

Hallo!

Schön, daß du den Bug selbst gefunden hast. Wie gesagt, sowas, was man partout nicht sieht, merkt man erst nach dem Kompilieren.

Zu dem einen Problem mit teilVon():

Nach dem ersten Duchlauf der i-Schleife prüfst du, ob anzTreffer=laenge(s2) ist.
Wenn JA, hast du einen treffer gelandet, und gibst mit return i; die Position zurück.
Wenn NEIN, solltest du einfach mit dem nächsten i weiter machen. Stattdessen gibst du sofort -1 zurück, und die i-Schleife läuft niemals weiter.
Mach also den kompletten else-Block weg, und setz das return -1 ganz nach unten, unter die i-Schleife.

Ich wette, wenn du "zwei" in "zweiundzwanzig" suchst, funktioniert die funktion, (weil Treffer bei i=0 im ersten Durchlauf).

Gut, ich markiere die anderen Fragen erstmal als beantwortet, denn das scheint ja jetzt erstmal alles klar zu sein.

Bezug
                                                                                                        
Bezug
Zeichenketten ohne Bibo (C++): Antwort
Status: (Antwort) fertig Status 
Datum: 22:08 Mi 17.04.2013
Autor: Event_Horizon

Hmmm, das ist merkwürdig.

Ich vermute, du gibst bei Wahl sowas wie 2[return] ein.Das cin.get() liest aber nur die 2, lässt das return aber noch im Eingangspuffer stehen.
Wenn dann eingabe() aufgerufen wird, wird das cin.getline sofort das return sehen, und einen leeren String liefern. Benutzt du vorher das cin.get(), wird das das return aus dem Puffer holen.

Kannst du aus dem get() mal ein
cout<<  cin.get()<<endl;

machen?

Dann solltest du vor der Eingabe eine einzelne Zahl gezeigt bekommen. Kannst du mir sagen, welche das ist?



Bezug
                                                                                                                
Bezug
Zeichenketten ohne Bibo (C++): Mitteilung
Status: (Mitteilung) Reaktion unnötig Status 
Datum: 20:37 Do 18.04.2013
Autor: Mija

Ich bekomme dann eine 10 ausgegeben, also den ASCII-Wert für den Zeilenvorschub.

Ganz ganz lieben Dank für deine ausführlichen Hilfestellungen und Erklärungen! Du hast mir super weitergeholfen! :-)

Bezug
                                
Bezug
Zeichenketten ohne Bibo (C++): Frage (beantwortet)
Status: (Frage) beantwortet Status 
Datum: 18:46 Di 16.04.2013
Autor: Mija

Hallo, also vom Sinn her habe ich es verstanden. Ich habe nur immer etwas Probleme, das dann auch in Code umzusetzen (vor allem, wenn es um Strings geht).

Wie gut bin ich denn auf dem Weg zur richtigen Lösung in den Funktionen kopiere(), anhaengen() und teilVon() ?

teilVon() muss noch einen Wert zurückgeben. Wo genau kann ich das nun machen? Es müsste ja irgendwie außerhalb der Schleifen sein..

Mein Code sieht momentan so aus:
1: #include <stdio.h>
2: #include <iostream>
3: #include "zeichenketten.h"
4: #include <cstddef>
5:
6: using namespace std;
7:
8: extern const int MAXLAENGE = 30;
9:
10: //Funktionsdefinitionen
11:
12: //berechnet die Laenge einer Zeichenkette
13: static size_t laenge(const char* s1)
14: {
15: int len=0;
16: for (int len=0; s1[len]!='\0'; len++)
17: {} //bleibt leer
18: return len;
19: }
20:
21: //kopiert die Zeichenkette s2 in die Zeichenkette s1
22: void kopiere(char* s1, const char* s2)
23: {
24: //cout << strncpy(s1, s2, MAXLAENGE) << endl;
25: if ( laenge(s1) <= laenge(s2) )
26: {
27: for (int i=0; s2[i]!='\0';i++) //oder i<laenge(s2) als Abbruchbedingung?
28: {
29: s1[i] = s2[i];
30: }
31: }
32: else
33: {
34: for (int i=0; s1[i]!='\0';i++) //oder i<laenge(s1) als Abbruchbedingung?
35: {
36: s1[i] = s2[i];
37: }
38: }
39: }
40:
41: //Hilfsfunktion!
42: //liefert das Zeichen einer Zeichenkette an der angegebenen Position n
43: //oder '\0', wenn n groesser als die Laenge der Zeichenkette ist
44: static char zeichenAn(const char* s, size_t n)
45: {
46: //cout << strchr(s, n) << endl;
47: char zei;
48: if ( n > laenge(s) )
49: {
50: zei = '\0';
51: }
52: else
53: {
54: zei = s[n];
55: }
56: return zei;
57: }
58:
59: //haengt die Zeichenkette s2 an die Zeichenkette s1 an,
60: //solange beide MAXLAENGE nicht ueberschreiten
61: void anhaengen(char* s1, const char* s2)
62: {
63: int i=0;
64: int k=laenge(s1);
65: for (i=0; i<MAXLAENGE; i++)
66: {
67: s1[k+i]=s2[i];
68: }
69: s1[k+i+1] = '\0';
70: }
71:
72: //Ueberprueft, ob die Zeichenkette s2 ein Teil der Zeichenkette s1 ist.
73: //Wenn ja, liefert die Position zurueck, an der s2 beginnt, -1 sonst
74: size_t teilVon(const char* s1, const char* s2)
75: {
76: /*cout << strstr(s1, s2) << endl;
77: return (size_t) strstr(s1, s2);*/
78: for (unsigned int i=0; i < laenge(s1); i++)
79: {
80: for (unsigned int k=0; k < laenge(s2); k++)
81: {
82: if (s1[k]==s2[k])
83: {
84: cout << "Treffer" << endl;
85: }
86: }
87: }
88: }
89:
90: //einlesen einer Zeichenkette ueber die Tastatur
91: void einlesen(char* s)
92: {
93: cin.getline(s, MAXLAENGE);
94: }
95:
96: //ausgeben einer Zeichenkette, eingeschlossen in Anfuehrungszeichen
97: void ausgeben(const char* s)
98: {
99: cout << "Die berechnete Zeichenkette lautet: \"" << s << "\"" << endl; //Anführungszeichen werden mit \" erzeugt
100: }



Bezug
                                        
Bezug
Zeichenketten ohne Bibo (C++): Antwort
Status: (Antwort) fertig Status 
Datum: 09:21 Mi 17.04.2013
Autor: Event_Horizon

Hallo!


Zu teilVon() habe ich dir grade zu der anderen Frage ausführlich geantwortet, daher hier nur zu den anderen:

Die kopiere() ist zu kompliziert. Du nimmst einfach die Länge des zu kopierenden Strings als Abbruchbedingung.

zwei0
sieben0

führt zu

zwei0n0

Das n0 stammt noch von der "sieben", weil das wort länger als "zwei" ist. Das ist aber egal, denn das Ende wird bereits von der  hinter "zwei" festgelegt, alles dahinter ist egal.



zu Anhaengen() :

>  for (i=0; i<MAXLAENGE; i++)

i sollte durch die Länge von s2 begrenzt werden, mehr mußt du ja nicht anhängen.

So bekommst du auf jeden Fall ein Problem, denn wenn der erste String ne Länge von 10 hat, schreibst du so auch an die Position MAXLAENGE+10, und dann kracht es.
Am Anfang der Funktion würde ich evtl prüfen, ob beide Strings zusammen nicht länger als MAXLAENGE sind, und die Arbeit sonst verweigern.



Aber sonst bsit du auf einem guten Weg!

Bezug
Ansicht: [ geschachtelt ] | ^ Forum "Praxis"  | ^^ Alle Foren  | ^ Forenbaum  | Materialien


^ Seitenanfang ^
www.vorhilfe.de