Leerzeichen aus einem String löschen?

Gast #1960024
Lesenswert?

Hi Leute!

Ich hab folgendes Problem. Ich soll aus einem String (ich benutze dafür 
Sätze) die evtl. darinstehenden Leerzeichen löschen. Dass man direkt 
eine Stelle eines Arrays nicht löschen kann ist mir klar. Jetzt hab ich 
es so versucht:
1
#include<stdio.h>
2
#include<string.h>
3
#include<ctype.h>
4
#include<iostream>
5
using namespace std;
6

7

8
int main()
9
{
10
 char satzpalindrom[30], satzohneleerzeichen[30], dummy[30], dummy2[30];
11
 int sp_size, i, j, k;
12

13
 printf("Bitte Satz eingeben: ");
14
 cin.getline(satzpalindrom, 30);
15

16

17
 sp_size = strlen(satzpalindrom);
18

19

20
j = 0;
21
for(i=0; i<sp_size; i=i+1)
22
{
23
  if(satzpalindrom[i] == ' ')
24
  {
25
    dummy2[j] = i;
26
    j = j + 1;
27
  }
28
  else
29
  {
30

31
  }
32
} 
33
 
34
system("pause");
35
return 0;
36
}

Das Programm liest mir eine Zeichenkette ein und schreibt mir in das 
array "Dummy2" die Stellen des Strings als Zahl rein, in denen ein 
Leerzeichen ist. Jetzt weiß ich zumindestens schon mal wie viel 
Leerzeichen drin sind und an welchen Stellen. Nur wie bekomme ich jetzt 
mit diesem gewonnenen Wissen die Leerzeichen aus meiner Zeichenkette 
"satzpalindrom"?

Ich kann bisher nur Schleifen, Funktionen, Felder und Zeichenketten. Die 
Funktion isalpha dürfen wir benutzen. Pointer oder ähnliches haben wir 
noch nicht durchgenommen...

Könnt ihr mir helfen?
#1960031
Lesenswert?

Tobias Mehrl schrieb:

> Könnt ihr mir helfen?

Du gehst das falsch an.

Stell dir einfach vor, du müsstest den String umkopieren. Und du 
kopierst einfach nur die Buchstaben um, die keine Leerzeichen sind.

Ooops. Fertig. Das Ergebnis ist dein Eingabstring ohne Leerzeichen.

Das umkopieren kann man auf 2 Arten machen: Entweder in ein neues 
Character Array, oder aber eleganter in dasselbe Character Array. Aber 
da du in deinem Programm sowieso schon dafür ein extra Array vorgesehen 
hast, ist die erste Version fein.

vergiss nicht auf Tabulatoren und Satzzeichen. Die werden m.W. bei 
Palindromen ebenfalls ignoriert :-)
Gast #1960036
Lesenswert?

Tobias Mehrl schrieb:
> Könnt ihr mir helfen?

Ich würds so probieren (ohne Gewähr)
1
char mitleer[30];
2
char ohneleer[30];
3

4
char *quelle = mitleer;
5
char *ziel = ohneleer;
6

7
for(  ;*quelle != '\0'; *quelle++)  //solange mitleer nicht zu ende
8
{
9
  if(*quelle != ' ')
10
   *ziel++ = *quelle;
11
}
12
*ziel = '\0';  //abschließendes Nullbyte
:-)
#1960044
Lesenswert?

Floh schrieb:
> Sorry les erst jetzt das du keine Pointer hast.
> allerdings lässt sich in diesem Fall der Pointer auch durch Zugriffe auf
> das Array ersetzen.
> :-)

Macht nichts.
er soll's ja selber lernen. Und so schwer ist das nicht. Er hatte nur zu 
kompliziert gedacht.

(PS: Strings geht man besser mit einer while Schleife durch
    while( *quelle != '\0' ) {
  oder do .... while( *quelle )
 meistens hat man dann weniger Sonderfälle.)
#1960057
Lesenswert?

nein, weil die würde die Leerzeichen mitkopieren.
Du musst strcpy() nachbauen, mit der kleinen Änderung.

Ein sinnvolle Vorübung wäre m.E. deshalb, strcpy() nachzubauen
und dann anschließend zu ändern - wobei du in diesem Fall
in die gleiche Stelle kopieren kannst, von der du auch liest.
Gast #1960076
Lesenswert?

strcpy nachbauen? Ich würde es so machen:
1
#include<stdio.h>
2
#include<string.h>
3
#include<iostream.h>
4
using namespace std;
5

6

7
int main()
8
{
9
 char satzpalindrom[30], text[30];
10
 int i, len;
11

12
 printf("Bitte Satz eingeben: ");
13
 cin.getline(satzpalindrom, 30);
14

15

16
 len = strlen(satzpalindrom);
17
 
18
 
19
 for(i=0; i<=len; i=i+1)
20
 {
21
  text[i] = satzpalindrom[i];
22
 }
23
          
24
 printf("%s", text);
25
 
26
 
27

28
return 0;
29
}

Probleme hab ich mit der kleinen Änderung... Ich will ja echte Zeichen 
umkopieren. Irgendwie raff ich das an der Stelle nicht...

Könnt ihr mir vielleicht schrittweise helfen wie ich nun mein Problem in 
meine nachgebaut strcpy implementiere?
#1960079
Lesenswert?

Tobias Mehrl schrieb:
> strcpy nachbauen? Ich würde es so machen:

Sieht nicht schlecht aus.

> Probleme hab ich mit der kleinen Änderung... Ich will ja echte Zeichen
> umkopieren. Irgendwie raff ich das an der Stelle nicht...

Warum nicht?

satzpalindrom[i] ist das Zeichen an der Stelle i im String.
Es wird nur dann umkopiert, wenn es kein Leerzeichen ist.

Aber: Du kannst es nicht an die Stelle i in Text kopieren. Den das Ziel 
kann ja eine ganz andere Indexnummer haben. Du wirst daher noch eine 
2.te Variable brauchen, nennen wir sie j, in der steht wo denn in Text 
das Zeichen satzpalindrom[i] abgelegt werden soll, wenn es denn kopiert 
werden müsste.

Einfach mal auf dem Papier probieren.
Der Satz sei "He du"

  satzpalindrom
  +---+---+---+---+---+---+
  | H | e |   | d | u | \0|
  +---+---+---+---+---+---+

  text
  +---+---+---+---+---+---+
  |   |   |   |   |   |   |
  +---+---+---+---+---+---+

und los gehts.
erstes Zeichen  satzpalindrom[0]: H
ist kein Leerzeichen, wird also umkopiert. Wo genau hin? An text[0]

  satzpalindrom
  +---+---+---+---+---+---+
  | H | e |   | d | u | \0|
  +---+---+---+---+---+---+

  text
  +---+---+---+---+---+---+
  | H |   |   |   |   |   |
  +---+---+---+---+---+---+


nächstes Zeichen, satzpalindrom[1]: e
wieder: kein Leerzeichen, wird also umkopiert.
Wohin? nach text[1]

  satzpalindrom
  +---+---+---+---+---+---+
  | H | e |   | d | u | \0|
  +---+---+---+---+---+---+

  text
  +---+---+---+---+---+---+
  | H | e |   |   |   |   |
  +---+---+---+---+---+---+

Nächstes Zeichen, satzpalindrom[2]:
Ist ein Leerzeichen, nichts weiter passiert

Nächstes Zeichen, satzpalindrom[3]:  d
kein Leerzeichen, wird umkopiert
Wohin? nach text[2], denn zuletzt wurde ja text[1] beschrieben

  satzpalindrom
  +---+---+---+---+---+---+
  | H | e |   | d | u | \0|
  +---+---+---+---+---+---+

  text
  +---+---+---+---+---+---+
  | H | e | d |   |   |   |
  +---+---+---+---+---+---+

Nächstes Zeichen, satzpalindrom[4]:  u
kein Leerzeichen, wird umkopiert
Wohin, nach text[3]

  satzpalindrom
  +---+---+---+---+---+---+
  | H | e |   | d | u | \0|
  +---+---+---+---+---+---+

  text
  +---+---+---+---+---+---+
  | H | e | d | u |   |   |
  +---+---+---+---+---+---+

Und dann bleibt noch das abschliessende \0, das ja ebenfalls nicht als 
Leerezeichen gilt und daher auch umkopiert wird

  satzpalindrom
  +---+---+---+---+---+---+
  | H | e |   | d | u | \0|
  +---+---+---+---+---+---+

  text
  +---+---+---+---+---+---+
  | H | e | d | u | \0|   |
  +---+---+---+---+---+---+


Das Eregbnis sieht richtig aus. Alle Leerzeichen sind verschwunden.
Gast #1960089
Lesenswert?

Nehmen wir mal als Beispiel den satz: Hallo du da! (ist zwar kein 
Palindrom aber er hat Leerzeich und um die gehts ja.)

So, nun kopiere ich 'H' an meine 0te Stelle in meinem neuen Array; 
genauso verfahre ich nun bis ich zum 'o' komme. Nun kommt aber an der 5. 
Stellen ein Leerzeichen. Woher weiß nun aber die for-Schleife (mit der 
ich ja umkopiere) das hier nun ein Leerezeichen kommt, welches sie nicht 
kopieren darf?
#1960095
Lesenswert?

Tobias Mehrl schrieb:
> Nehmen wir mal als Beispiel den satz: Hallo du da! (ist zwar kein
> Palindrom aber er hat Leerzeich und um die gehts ja.)
>
> So, nun kopiere ich 'H' an meine 0te Stelle in meinem neuen Array;
> genauso verfahre ich nun bis ich zum 'o' komme. Nun kommt aber an der 5.
> Stellen ein Leerzeichen. Woher weiß nun aber die for-Schleife (mit der
> ich ja umkopiere)

Die for-Schleife weiss das auch nicht. DIe interessiert das auch nicht 
weiter. Aber du kannst ja innerhalb des for noch ein if machen. Niemand 
hindert dich daran. Und du musst den Buchstaben, wenn du ihn umkopierst 
auch nicht nach text[i] kopieren
Gast #1960118
Lesenswert?

So Leute, ich glaub ich hab fertig:

hier mein code:
1
#include<stdio.h>
2
#include<string.h>
3
#include<iostream.h>
4
using namespace std;
5

6

7
int main()
8
{
9
 char satzpalindrom[30], text[30];
10
 int i, j, len;
11

12
 printf("Bitte Satz eingeben: ");
13
 cin.getline(satzpalindrom, 30);
14

15

16
 len = strlen(satzpalindrom);
17
 
18
 j = 0;
19
 for(i=0; i<=len; i=i+1)
20
 {
21
  if(satzpalindrom[i] != ' ')
22
  {
23
   text[j] = satzpalindrom[i];
24
   j = j + 1;
25
  }
26
  else
27
  {
28
   
29
  }
30
 }
31
          
32
 printf("%s", text);
33
 
34
 
35
system("pause");
36
return 0;
37
}

Könnt ihr mal gucken ob das so jetzt passt? mein compiler meckert nicht 
und auch das ergebnis passt...
#1960135
Lesenswert?

Was mir gefällt:
Du hast bereits angefangen einen Formatier-Stil zu entwickeln. Noch 
etwas zaghaft, aber das wird mit der Zeit.
Mach weiter so.


PS:
Wenn in einem else nichts steht, dann lass es besser weg. Code 
übersichtlich zu machen ist eine Sache. Aber ihn ohne Not in die Länge 
zu ziehen geht in die falsche Richtung
1
 for(i=0; i<=len; i=i+1)
2
 {
3
  if(satzpalindrom[i] != ' ')
4
  {
5
   text[j] = satzpalindrom[i];
6
   j = j + 1;
7
  }
8
 }

ist genausogut, wenn nicht sogar besser weil nicht so in die Länge 
gezogen. Je näher die abschliessende } zur jeweils öffnenden { steht, 
umso leichter ist es den Überblick zu behalten, wie die einzelnen Teile 
ineinander geschachtelt sind.
Gast #1960207
Lesenswert?

Ich verstehe nicht, warum ich hier eine 149 len2 stehen hab bei einer 
Zeichenkette von 31...

Hier mein Code:
1
len1 = strlen(satzpalindrom);
2
 j = 0;              //Leerzeichen entfernen
3
 for(i=0; i<=len1; i=i+1)
4
 {
5
  if(isalpha(satzpalindrom[i]))
6
  {
7
   ohneleer[j] = satzpalindrom[i];
8
   j = j + 1;
9
  }
10
 }
11
 len2 = strlen(ohneleer);
12
 ohneleer[len2] = satzpalindrom[len1];    //0-Terminierung an die richtige Stelle ins Array
Gast #1960218
Lesenswert?

Sorry, wenn ich das etwas unverständlich geschrieben hab.

Ich gebe z.B. eine Zeichenkette von 7 Zeichen ein. len1 passt noch das 
gibt 7 aus. len2 ist aber dann unverständlicherweise 115... Was is'n da 
jetzt falsch?
#1960224
Lesenswert?

Tobias Mehrl schrieb:
> Ich gebe z.B. eine Zeichenkette von 7 Zeichen ein. len1 passt noch das
> gibt 7 aus. len2 ist aber dann unverständlicherweise 115... Was is'n da
> jetzt falsch?

Durch das isalpha wird die abschließende 0 nicht mitkopiert,
also ist der erzeugte String nicht terminiert.
Ein strlen() darauf zählt also bis zur ersten zufällig im Speicher
stehenden 0.
#1960239
Lesenswert?

> Durch das isalpha wird die abschließende 0 nicht mitkopiert,
> also ist der erzeugte String nicht terminiert.

Genau.

Und deshalb ist das hier
1
 len2 = strlen(ohneleer);
2
 ohneleer[len2] = satzpalindrom[len1];    //0-Terminierung an die richtige Stelle ins Array
so nicht möglich.

strlen ist darauf angewiesen, dass die 0-Terminierung schon am richtigen 
Platz ist. Du musst daher deine 0-Terminierung auf einem anderen Weg an 
die richtige Stelle schreiben. Und erst dann kannst du irgendeine der 
str... Funktionen benutzen.

Du hast hier versucht, das Pferd von hinten aufzuzäumen.
Gast #1960256
Lesenswert?

So siehts aus:
1
 len1 = strlen(satzpalindrom);
2
 j = 0;              //Leerzeichen entfernen
3
 for(i=0; i<=len1; i=i+1)
4
 {
5
  if(isalpha(satzpalindrom[i]))
6
  {
7
   ohneleer[j] = satzpalindrom[i];
8
   j = j + 1;
9
  }
10
 }
11
 ohneleer[j] = satzpalindrom[len1];    //0-Terminierung an die richtige Stelle ins Array


Geht aber auch nicht. In ohneleer steht nach wie vor keine 0
#1960268
Lesenswert?

Tobias Mehrl schrieb:
> So siehts aus:
>
>
1
>  len1 = strlen(satzpalindrom);
2
>  j = 0;              //Leerzeichen entfernen
3
>  for(i=0; i<=len1; i=i+1)
4
>  {
5
>   if(isalpha(satzpalindrom[i]))
6
>   {
7
>    ohneleer[j] = satzpalindrom[i];
8
>    j = j + 1;
9
>   }
10
>  }
11
>  ohneleer[j+1] = satzpalindrom[len1];    //0-Terminierung an die
12
> richtige Stelle ins Array
>
>
> Geht aber auch nicht. In ohneleer steht nach wie vor keine 0

Wenn du ohnehin weißt, dass du das Zeichen '\0' dort reinbugsieren 
musst, warum schreibst du es dann nicht einfach als '\0' sondern 
versuchst es dir aus satzpalindrom zu holen? Und dann dort auch noch von 
der falschen Stelle.

Wenn du dir nicht sicher bist (da ist dann noch ein Fehler), dann spiels 
auf einem Stück Papier durch

Gegeben sei der String

   +---+---+---+---+---+---+     +---+---+---+---+---+---+---+---+
   | H | e |   | d | u | \0|     |   |   |   |   |   |   |   |   |
   +---+---+---+---+---+---+     +---+---+---+---+---+---+---+---+

den du nach rechts umkopieren musst.
Welche Werte haben in jedem Schleifendurchgang i und j, was passiert 
innerhalb der Schleife


    i      j       Aktion
  -------------------------
    0      0        H umkopieren, j wird 1
   +---+---+---+---+---+---+     +---+---+---+---+---+---+---+---+
   | H | e |   | d | u | \0|     | H |   |   |   |   |   |   |   |
   +---+---+---+---+---+---+     +---+---+---+---+---+---+---+---+

    1      1


(du machst weiter)
Gast #1960276
Lesenswert?

Jetzt hab ich's so: (ich hab's auch auf dem papier durchgespielt.... da 
passts)
1
len1 = strlen(satzpalindrom);
2
 j = 0;              //Leerzeichen entfernen
3
 for(i=0; i<len1; i=i+1)
4
 {
5
  if(isalpha(satzpalindrom[i]))
6
  {
7
   ohneleer[j] = satzpalindrom[i];
8
   j = j + 1;
9
  }
10
 }
11
 ohneleer[j] = '\0';    //0-Terminierung an die richtige Stelle ins Array
#1960278
Lesenswert?

Karl heinz Buchegger schrieb:
> Tobias Mehrl schrieb:
>> So siehts aus:
>>
>>
1
>>  len1 = strlen(satzpalindrom);
2
>>  j = 0;              //Leerzeichen entfernen
3
>>  for(i=0; i<=len1; i=i+1)
4
>>  {
5
>>   if(isalpha(satzpalindrom[i]))
6
>>   {
7
>>    ohneleer[j] = satzpalindrom[i];
8
>>    j = j + 1;
9
>>   }
10
>>  }
11
>>  ohneleer[j+1] = satzpalindrom[len1];    //0-Terminierung an die
12
>> richtige Stelle ins Array
>>
>>
>> Geht aber auch nicht. In ohneleer steht nach wie vor keine 0
> ...

Wo kommt jetzt ohneleer[j+1] = satzpalindrom[len1]; her?
Eben hieß es noch richtigerweise ohneleer[j] = satzpalindrom[len1];
#1960282
Lesenswert?

Karl heinz Buchegger schrieb:
> Klaus Wachtler schrieb:
>> Karl heinz Buchegger schrieb:
>>> Und dann dort auch noch von der falschen Stelle.
>>
>> Daß es besser gleich als '\0' genommen werden könnte, ist natürlich
>> korrekt.
>> Aber wenn ich jetzt keinen Aussetzer habe, nimmt er es schon
>> von der richtigen Stelle (len1).
>
>
> Nope
>>  len1 = strlen(satzpalindrom);

Arrgh.
Ja, du hast recht. War jetzt im Eifer des Gefechts.
#1960287
Lesenswert?

Tobias Mehrl schrieb:
> Jetzt hab ich's so: (ich hab's auch auf dem papier durchgespielt.... da
> passts)
>
>
1
len1 = strlen(satzpalindrom);
2
>  j = 0;              //Leerzeichen entfernen
3
>  for(i=0; i<len1; i=i+1)
4
>  {
5
>   if(isalpha(satzpalindrom[i]))
6
>   {
7
>    ohneleer[j] = satzpalindrom[i];
8
>    j = j + 1;
9
>   }
10
>  }
11
>  ohneleer[j] = '\0';    //0-Terminierung an die richtige Stelle ins
12
> Array
13
>


Ja, so passts.
j ist nach der Schleife gleich der Anzahl der umkopierten Buchstaben und 
damit auch gleichzeitig die Länge des Strings. Nur der String muss das 
auch noch wissen :-) Und dafür hast du jetzt korrekterweise gesorgt.
Ab jetzt steht in ohneleer wieder ein korrekter C-String mit dem man 
weiterarbeiten kann.
Gast #1960296
Lesenswert?

Leute nochmal kurz für mich:

Ich hab jetzt den Code:
1
len1 = strlen(satzpalindrom);
2
 j = 0;              //Leerzeichen entfernen
3
 for(i=0; i<len1; i=i+1)
4
 {
5
  if(isalpha(satzpalindrom[i]))
6
  {
7
   ohneleer[j] = satzpalindrom[i];
8
   j = j + 1;
9
  }
10
 }
11
 ohneleer[j] = '\0';

Wenn ich mir jetzt in Visual Studio 2010 die Strings ansehe, dann steht 
in ohneleer zwar keine Leerzeichen mehr drin und nur noch die buchstaben 
aber keine 0...
#1960300
Lesenswert?

Tobias Mehrl schrieb:
> Leute nochmal kurz für mich:
>
> Ich hab jetzt den Code:
>
> [c]
> len1 = strlen(satzpalindrom);
>  j = 0;              //Leerzeichen entfernen
>  for(i=0; i<len1; i=i+1)
>  {
>   if(isalpha(satzpalindrom[i]))
>   {
>    ohneleer[j] = satzpalindrom[i];
>    j = j + 1;
>   }
>  }
>  ohneleer[j] = '\0';
> [c]
>
> Wenn ich mir jetzt in Visual Studio 2010 die Strings ansehe, dann steht
> in ohneleer zwar keine Leerzeichen mehr drin und nur noch die buchstaben
> aber keine 0...

Keine Sorge. Es steht eines drinnen.
Aber auch Visual Studio weiß, dass es sich bei einem char Array um einen 
String handelt und zeigt dir den auch als String an.
Oder wo genau siehst du nach? Wenn du VS dazu zwingst, dir das Ding 
einfach nur als Array zu präsentieren, dann findet sich dort auch wieder 
das \0 Byte
#1960301
Lesenswert?

Ja, aber sonst sieht es doch schon nett aus.

Eigentlich gehört das noch in eine Funktion, aber dafür braucht
man Zeiger zwecks Übergabe, und x=x+1 könnte man verkürzen, und
dann wäre da noch die Sache mit der do...while-Schleife.

Aber das ist letztlich alles Makulatur.
#1960306
Lesenswert?

Klaus Wachtler schrieb:
> Ja, aber sonst sieht es doch schon nett aus.
>
> Eigentlich gehört das noch in eine Funktion, aber dafür braucht
> man Zeiger zwecks Übergabe, und x=x+1 könnte man verkürzen, und
> dann wäre da noch die Sache mit der do...while-Schleife.
>
> Aber das ist letztlich alles Makulatur.

Ich denke so weit sind sie noch nicht im Unterricht. Also Funktionen und 
so.

Aber, wenn ich das richtig interpretiere ist ja die Aufgabe noch nicht 
fertig. Noch wissen wir ja nicht, ob die Eingabe ein Palindrom ist oder 
nicht.
Gast #1960308
Lesenswert?

Hier mal noch mein vollständiger Code, bzw. ich lasse nur bis dahin 
ausführen...
1
#include<stdio.h>
2
#include<string.h>
3
#include<iostream>
4
#include<ctype.h>
5
using namespace std;
6

7

8
int main()
9
{
10
 char satzpalindrom[100], ohneleer[100], kleinzeichen, satzpalindrom_klein_ohneleer[100], ruckwartspalindrom[100];
11
 int i, j, len1, len2;
12

13

14
 printf("Bitte Satz eingeben: ");
15
 cin.getline(satzpalindrom, 100);
16

17

18
 len1 = strlen(satzpalindrom);
19
 j = 0;              //Leerzeichen entfernen
20
 for(i=0; i<len1; i=i+1)
21
 {
22
  if(isalpha(satzpalindrom[i]))
23
  {
24
   ohneleer[j] = satzpalindrom[i];
25
   j = j + 1;
26
  }
27
 }
28
 ohneleer[j] = '\0';    //0-Terminierung an die richtige Stelle ins Array
#1960312
Lesenswert?

Tobias Mehrl schrieb:
> Leute nochmal kurz für mich:
>
> Ich hab jetzt den Code:
>
>
1
> len1 = strlen(satzpalindrom);
2
>  j = 0;              //Leerzeichen entfernen
3
>  for(i=0; i<len1; i=i+1)
4
>  {
5
>   if(isalpha(satzpalindrom[i]))
6
>   {
7
>    ohneleer[j] = satzpalindrom[i];
8
>    j = j + 1;
9
>   }
10
>  }
11
>  ohneleer[j] = '\0';
12
>
>
> Wenn ich mir jetzt in Visual Studio 2010 die Strings ansehe, dann steht
> in ohneleer zwar keine Leerzeichen mehr drin und nur noch die buchstaben
> aber keine 0...

Wenn du dir das ansiehst, wo steht der gelbe Pfeil/Punkt vom Debugger im 
Code?
Auf der Zeile
   ohneleer[j] = '\0';
oder dahinter?

Die gelbe Markierung zeigt dir immer die Zeile, die als nächstes 
ausgeführt wird aber noch nicht abgearbeitet wurde.
#1960328
Lesenswert?

Den/die Minuspunkt(e) kriegt von mir sein Lehrer.
Und zwar aus verschiedenen Gründen. Der wichtigste davon: Er kann sich 
nicht entscheiden ob er C++ oder C unterrichten soll. Statt dessen 
veranstaltet er da einen Mischmasch.

Wenn C, dann haben die C++ Header, cin und using nichts verloren.

Wenn C++, dann std::string anstelle von C-String Verarbeitung. Die kommt 
später, viel später. In der Zwischenzeit sich an den Segnungen von 
Objekten die auf sich selbst aufpassen erfreuen und zügig im Stoff 
weiterkommen.
Gast #1960340
Lesenswert?

Ich hab fertig: Mein Programm für den Vergleich von Satzpalindromen 
sieht so aus:
1
#include<stdio.h>
2
#include<string.h>
3
#include<iostream>
4
#include<ctype.h>
5
using namespace std;
6

7

8
int main()
9
{
10
 char satzpalindrom[100], ohneleer[100], kleinzeichen, satzpalindrom_klein_ohneleer[100], ruckwartspalindrom[100];
11
 int i, j, len1, len2;
12

13

14
 printf("Bitte Satz eingeben: ");
15
 cin.getline(satzpalindrom, 100);
16

17

18
 len1 = strlen(satzpalindrom);
19
 j = 0;              //Leerzeichen entfernen
20
 for(i=0; i<len1; i=i+1)
21
 {
22
  if(isalpha(satzpalindrom[i]))
23
  {
24
   ohneleer[j] = satzpalindrom[i];
25
   j = j + 1;
26
  }
27
 }
28
 ohneleer[j] = '\0';    //0-Terminierung an die richtige Stelle ins Array
29

30

31

32

33

34

35
 len2 = strlen(ohneleer);
36
 j = 0;
37
 for(i=0; i<len2; i=i+1)      //alle Buchstaben klein schreiben
38
 {
39
  kleinzeichen = tolower(ohneleer[i]);
40
  satzpalindrom_klein_ohneleer[j] = kleinzeichen;
41
  j = j + 1;
42
 }
43
 satzpalindrom_klein_ohneleer[len2] = '\0';
44

45

46

47

48
 j = 0;
49
 for(i=(len2-1); i>=0; i=i-1)    //String umdrehen
50
 {
51
  ruckwartspalindrom[j] = satzpalindrom_klein_ohneleer[i];
52
  j = j + 1;
53
 }
54
 ruckwartspalindrom[len2] = '\0';
55

56

57

58
 if(strcmp(ruckwartspalindrom, satzpalindrom_klein_ohneleer) == 0)    //Vergleich der beiden Zeichenketten
59
 {
60
  printf("Ja, ist ein Palindrom!\n");
61
 }
62
 else
63
 {
64
  printf("Nein, ist KEIN Palindrom!\n");
65
 }
66

67

68

69
system("pause");
70
return 0;
71
}

Jetzt möchte ich noch einzelne Programmteile in Funktionen auslagern 
(das haben wir schon durchgemacht) aber ich denke, dass mach ich dann 
lieber morgen. Kann ich mich morgen dazu wieder melden?

Das iostream brauch ich doch für cin.getline, oder?
#1960354
Lesenswert?

Tobias Mehrl schrieb:
> Ich hab fertig: Mein Programm für den Vergleich von Satzpalindromen
> sieht so aus:

Okaaay

> Jetzt möchte ich noch einzelne Programmteile in Funktionen auslagern
> (das haben wir schon durchgemacht) aber ich denke, dass mach ich dann
> lieber morgen.

Ehe du das tust, schau dein Programm noch mal durch.
Da kann man noch viel tun

> Kann ich mich morgen dazu wieder melden?

Klar

>
> Das iostream brauch ich doch für cin.getline, oder?

Schon. Aber was macht eigentlich cin in einem "C" Programm?
#1960359
Lesenswert?

Karl heinz Buchegger schrieb:

>> Jetzt möchte ich noch einzelne Programmteile in Funktionen auslagern
>> (das haben wir schon durchgemacht) aber ich denke, dass mach ich dann
>> lieber morgen.
>
> Ehe du das tust, schau dein Programm noch mal durch.
> Da kann man noch viel tun

zb hier
1
len2 = strlen(ohneleer);
2
 j = 0;
3
 for(i=0; i<len2; i=i+1)      //alle Buchstaben klein schreiben
4
 {
5
  kleinzeichen = tolower(ohneleer[i]);
6
  satzpalindrom_klein_ohneleer[j] = kleinzeichen;
7
  j = j + 1;
8
 }
9
 satzpalindrom_klein_ohneleer[len2] = '\0';

Wozu der strlen? Du kennst doch die Länge des Strings schon aus dem 
vorhergehenden Teil.
Wozu brauchst du das j hier. j hat immer denselben Wert wie i.
Wozu die zusätzliche Variable 'kleinzeichen'
1
 len2 = j;    // wenns schon eine Variable len2 braucht.
2
              // ALternativ hätte man ja auch das j weiter oben
3
              // gleich len2 nennen können
4

5
 for(i=0; i<len2; i=i+1)      //alle Buchstaben klein schreiben
6
 {
7
   satzpalindrom_klein_ohneleer[j] = tolower(ohneleer[i]);
8
 }
9
 satzpalindrom_klein_ohneleer[len2] = '\0';

Man hätte allerdings das tolower auch gleich in die erste SChleife mit 
aufnehmen können:
1
 len1 = strlen(satzpalindrom);
2
 j = 0;              //Leerzeichen entfernen
3
 for(i=0; i<len1; i=i+1)
4
 {
5
  if(isalpha(satzpalindrom[i]))
6
  {
7
   satzpalindrom_klein_ohneleer[j] = tolower( satzpalindrom[i] );
8
   j = j + 1;
9
  }
10
 }
11
 ohneleer[j] = '\0';    //0-Terminierung an die richtige Stelle ins Array

dann fällt schon mal Code weg, es fallen Variablen weg, etc.

Aber es ist ok.
Zum jetzigen Zeitpunkt zählt 'funktioniert' noch ein wenig mehr.
#1960432
Lesenswert?

Karl heinz Buchegger schrieb:
> Oder präsentieren wir ihm die Alternative? Ich denk es wäre
> vertretbar, weil die Denkweise dann doch ganz anders ist.

Tobias, bitte weglesen  :)

unsigned int i,j;
...
// 0x20 raus
i=j=0;
while(text[i] = satzpalindrom[j++])
  if (text[i] != ' ') i++;
// vergleich (i zeigt auf ende /0)
j=0;
while(j<i)
  if (text[j++] != text[--i])
    { i++; j--; break; }
// ergebnis
if (j>=i)
  printf("Ist 'n palidings");
else
  printf("Ist keins");

Ich hoffe da ist jetzt (abgesehen vom Stil) kein logischer Fehler 
drin...
#1960475
Lesenswert?

Torsten K. schrieb:

> Ich hoffe da ist jetzt (abgesehen vom Stil) kein logischer Fehler
> drin...

Ich denke es müsste stimmen. (das tolower ist geschenkt)

Ich krieg die 2.te Schleife nicht weg, die ich brauch um einen Pointer 
ans Stringende zu kriegen. Keine Chance. Mit weniger als 2 mal durch den 
String gehts nicht. Ich wollte die Blanks 'on the fly' beim Durchmarsch 
bis zur Mitte überspringen. Aber ich brauch 2 Pointer. Einen von vorne, 
einen von hinten. Aber für den von hinten muss ich durch den String 
durch.
Gast #1961259
Lesenswert?

@kbuchegg:

"Wozu der strlen? Du kennst doch die Länge des Strings schon aus dem
vorhergehenden Teil.
Wozu brauchst du das j hier. j hat immer denselben Wert wie i.
Wozu die zusätzliche Variable 'kleinzeichen'"

Das muss aber schon so heißen, oder?
1
for(i=0; i<len2; i=i+1)      //alle Buchstaben klein schreiben
2
 {
3
   satzpalindrom_klein_ohneleer[j] = tolower(ohneleer[i]);
4
 }
5
 satzpalindrom_klein_ohneleer[len2] = '\0';

Wenn ich das j lasse, dann kopiere ich ab der 4. Stelle ins array

Hier mal mein verbesserter und kürzere Code:
1
#include<stdio.h>
2
#include<string.h>
3
#include<iostream>
4
#include<ctype.h>
5
using namespace std;
6

7

8
int main()
9
{
10
 char satzpalindrom[100], satzpalindrom_klein_ohneleer[100], ruckwartspalindrom[100];
11
 int i, j, len, k;
12

13

14

15
 printf("Bitte Satz eingeben: ");
16
 cin.getline(satzpalindrom, 100);
17

18

19

20
 len = strlen(satzpalindrom);
21
 j = 0;              //Leerzeichen entfernen
22
 for(i=0; i<len; i=i+1)
23
 {
24
  if(isalpha(satzpalindrom[i]))
25
  {
26
   satzpalindrom_klein_ohneleer[j] = tolower(satzpalindrom[i]);    //alle Buchstaben klein machen
27
   j = j + 1;
28
  }
29
 }
30
 satzpalindrom_klein_ohneleer[j] = '\0';    //0-Terminierung an die richtige Stelle ins Array
31

32

33

34
 k = 0;
35
 for(i=(j-1); i>=0; i=i-1)    //String umdrehen
36
 {
37
  ruckwartspalindrom[k] = satzpalindrom_klein_ohneleer[i];
38
  k = k + 1;
39
 }
40
 ruckwartspalindrom[j] = '\0';
41

42

43

44
 if(strcmp(ruckwartspalindrom, satzpalindrom_klein_ohneleer) == 0)    //Vergleich der beiden Zeichenketten
45
 {
46
  printf("Ja, ist ein Palindrom!\n");
47
 }
48
 else
49
 {
50
  printf("Nein, ist KEIN Palindrom!\n");
51
 }
52

53

54

55
system("pause");
56
return 0;
57
}
Gast #1961262
Lesenswert?

So, nun möchte ich nch mein Programm in Funktionen auslagern. Ich hab 
hier ja drei Programmteile, nämlich "Leerzeichen entfernen", "String 
umdrehen" und "Strings vergleichen". Die sollten sich doch jetzt ganz 
einfach in Funktionen auslagern lassen, oder? Ich meine, abhängig sind 
doch die 3 Funktionen doch eh nur von dem einmal ganz am anfang 
eingegebenen string satzpalindrom, richtig?
Moderator #1961440
Lesenswert?

Bei der Übergabe von Strings an Funktionen siehst du von den Pointern
normalerweise gar nichts, da du die Strings wie char-Arrays behandelst,
z.B. so:
1
#include <stdio.h>
2
#include <string.h>
3
#include <ctype.h>
4

5
int ispalindrom(char s[]) {
6
  int i=0, j=strlen(s)-1;
7

8
  while(i < j) {
9
    if(!isalpha(s[i]))
10
      i++;
11
    else if(!isalpha(s[j]))
12
      j--;
13
    else if(tolower(s[i++]) != tolower(s[j--]))
14
      return 0;
15
  }
16
  return 1;
17
}
18

19
int main(void) {
20
  char line[100];
21

22
  printf("Bitte einen Satz eingeben:\n");
23
  fgets(line, sizeof line, stdin);
24
  if(ispalindrom(line))
25
    printf("Ja, ist ein Palindrom!\n");
26
  else
27
    printf("Nein, ist KEIN Palindrom!\n");
28
}
#1961841
Lesenswert?

Yalu X. schrieb:
> Bei der Übergabe von Strings an Funktionen siehst du von den Pointern
> normalerweise gar nichts, da du die Strings wie char-Arrays behandelst,
> z.B. so:
>
>
1
> #include <stdio.h>
2
> #include <string.h>
3
> #include <ctype.h>
4
> 
5
> int ispalindrom(char s[]) {
6
>   int i=0, j=strlen(s)-1;
7
> 
8
>   while(i < j) {
9
>     if(!isalpha(s[i]))
10
>       i++;
11
>     else if(!isalpha(s[j]))
12
>       j--;
13
>     else if(tolower(s[i++]) != tolower(s[j--]))
14
>       return 0;
15
>   }
16
>   return 1;
17
> }
18
>

oder rekursiv (nicht ganz, wer will bekommt aber das strlen auch noch 
raus)
1
bool isPalindrome(const char* inputStr, int first, int last) {
2
  if ((last - first) < 1) return true; 
3

4
  if (!isalpha(inputStr[first])) isPalindrome(inputStr, first + 1, last);
5
  if (!isalpha(inputStr[last])) isPalindrome(inputStr, first, last - 1);
6
  if (tolower(inputStr[first]) != tolower(inputStr[last])) {
7
    return false;
8
  } else {
9
    return isPalindrome(inputStr, first + 1, last - 1);
10
  }
11
}
12

13
char text[] = "Ein Esel lese nie";
14
bool res = isPalindrome(text, 0, strlen(text) - 1);
#1961869
Lesenswert?

Tobias Mehrl schrieb:
> @kbuchegg:
>
> "Wozu der strlen? Du kennst doch die Länge des Strings schon aus dem
> vorhergehenden Teil.
> Wozu brauchst du das j hier. j hat immer denselben Wert wie i.
> Wozu die zusätzliche Variable 'kleinzeichen'"
>
> Das muss aber schon so heißen, oder?
>
>
1
> for(i=0; i<len2; i=i+1)      //alle Buchstaben klein schreiben
2
>  {
3
>    satzpalindrom_klein_ohneleer[j] = tolower(ohneleer[i]);
4
>  }
5
>  satzpalindrom_klein_ohneleer[len2] = '\0';
6
>
>
> Wenn ich das j lasse, dann kopiere ich ab der 4. Stelle ins array

Du hast mich erwischt. War ein Copy&Paste Fehler.
Da j bei dir ja immer denselben Wert wie i hatte (an dieser Stelle) war 
natürlich gemeint
1
  for(i=0; i<len2; i=i+1)      //alle Buchstaben klein schreiben
2
  {
3
    satzpalindrom_klein_ohneleer[i] = tolower(ohneleer[i]);
4
  }
5
  satzpalindrom_klein_ohneleer[len2] = '\0';

Das hast du absolut richtig erkannt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren