Forum: Compiler & IDEs Stringspielerei


von M. B. (massi)


Lesenswert?

Kämpfe jetzt schon seit 2 Tagen daran dieses Programm zum Laufen zu 
bringen, jedoch finde ich meinen Fehler nicht.

Aufgabenstellung:

Durch Eingabe des Strings "Wie gehts?" und einer Sperrung (leerzeichen 
zwischen den einzelnen Buchstaben)
soll ein neuer String erzeugt werden solange es kleiner ist wie die 
maximale Byteeingabe in der main-funktion.

Bsp:

Sperrung: 3

"Wie gehts?"
"W   i   e     g   e   h   t   s   ?"


############################################################


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void aenderung(char *s[],int sperrung,int max){


int i,j=0,k;
char hilfsv[max-1];

     if(max>(((strlen(s)-1)*(sperrung+1))+1)){

         for (i=0;i<strlen(s);i++){
             hilfsv[j]=*s[i];
             k=sperrung+1;
               while(k-1){
                  j++;
                  hilfsv[j]=' ';}}
                  strcpy(s,hilfsv);

                   return s;
                          }
          else
              printf("Fehler!\n");
}

int main()
{
    int sl=2;
    int max=60;
    char s[]="Wie gehts?";
    aenderung(&s,sl,max);
    printf("%s",s);


    return 0;
}

####################################################

Kann mir einer erklären wo mein Fehler liegt?

von Klaus W. (mfgkw)


Lesenswert?

Abgesehen davon, daß dein Quelltext gruselig zu lesen ist,
sowie deine Fehlerbeschreibung keine ist,
überschreibst du wahrscheinlich nicht nur s[] (das nur 11
Zeichen lang ist), sondern auch den Speicher dahinter?

von Klaus W. (mfgkw)


Lesenswert?

Eben weil der Quelltext so grottig ist, sieht man auch kaum,
daß du k nicht weiterzählst.

von Klaus W. (mfgkw)


Lesenswert?

hilfsv[j]=*s[i];
soll wohl heißen:
hilfsv[j]=s[i];

Entsprechend:
char *s[]
soll wohl heißen:
char s[]
oder
char *s

Hat das eigentlich mal ein Compiler so übersetzt?

Wieso verheimlichst du dann die Fehlermeldungen?

von M. B. (massi)


Lesenswert?

Das mit dem k++;
hab ich vergessen da hast du recht.

Also mein Compiler hat es übersetzt und keine Fehlermeldungen gebracht.
Jedoch hat er sich aufgehängt.
Deshalb weiß ich die Fehler nicht...

von Klaus W. (mfgkw)


Lesenswert?

Eine abschließende 0 sollte man an den String vielleicht auch anhängen.
(Hast du in den zwei Tagen mal in ein C-Buch reingesehen?)

von Klaus W. (mfgkw)


Lesenswert?

M. Bub schrieb:
> Das mit dem k++;

nein, k--

von Klaus W. (mfgkw)


Lesenswert?

M. Bub schrieb:
> Also mein Compiler hat es übersetzt und keine Fehlermeldungen gebracht.
> Jedoch hat er sich aufgehängt.

Dann hat er etwas übertrieben, sooo schlimm ist der Quelltext
ja auch nicht, daß man sich aufhängen muß :-)

von Karl H. (kbuchegg)


Lesenswert?

M. Bub schrieb:
> Das mit dem k++;
> hab ich vergessen da hast du recht.
>
> Also mein Compiler hat es übersetzt und keine Fehlermeldungen gebracht.

Das kann ich mir ehrlich nicht vorstellen

was passt zb hier nicht zusammen

void aenderung(char *s[],int sperrung,int max){
****

....

                   return s;

Mal ganz abgesehen davon, dass das so sowieso nicht geht.
So kann man keinen String zurückgeben.

von M. B. (massi)


Lesenswert?

Ja danke für das ironische Kompliment ;-)

Jetzt gibt er mir wenigstens was aus.

H o !
#############################################################

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void aenderung(char *s[],int sperrung,int max){


int i,j=0,k;
char hilfsv[max-1];

     if(max>(((strlen(s)-1)*(sperrung+1))+1)){

         for (i=0;i<strlen(s);i++)  {
             hilfsv[j]=s[i];
             k=sperrung+1;

               while(k-1)
                  {
                  j++;
                  hilfsv[j]=' ';
                  k--;
                  }
                                    }
               hilfsv[j+1]='\0';
              strcpy(s,hilfsv);
              return s;
                                              }
          else
              printf("Fehler!\n");
}

int main()
{
    int sl=2;
    int max=60;
    char s[]="Hallo du!";
    aenderung(&s,sl,max);
    printf("%s",s);


    return 0;
}

von Karl H. (kbuchegg)


Lesenswert?

Tipp

Der Datentyp von s in

void aenderung(char *s[],int sperrung,int max){

ist Blödsinn.
Du hast kein Array von Pointern, du hast ein Array von Charactern.

Und wenn du s dann später etwas mittels strcpy zuweisen willst, dann 
wäre es ganz gut, wenn s auch tatsächlich groß genug dafür ist (und 
genau dafür ist nämlich das max da, damit die Funktion das auch 
überprüfen kann)

Dieses Array, welches du versuchst in die Funktion reinzugeben

   char s[]="Hallo du!";
    aenderung(&s,sl,max);

ist es ganz sicher nicht. Das ist nur 10 Zeichen gross. Da wirst du mit 
deinem gesperrtem Text nicht weit kommen.

Und im übrigen ist es ganz gut, wenn man seine Funktionen nicht anlügt.
Wenn das Argument nur Platz für 10 Zeichen bietet, dann ist es keine 
gute Idee, der Funktion weiszumachen, dass 60 Zeichen Platz hätten.

Dein Aufruf soll so aussehen

    char s[40]="Hallo du!";
    aenderung( s, sl, sizeof( s ) );

dann wid auch niemand angelogen und kein Array geht über.

von Klaus W. (mfgkw)


Lesenswert?

Über Geschmack kann man streiten, über Stil sowieso.

Trotzdem mal ein Vorschlag, den ich deutlich lesbarer finde:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
5
// kopiert String auf sich selbst, und fügt dabei je (nSperrung)
6
// Leerzeichen ein:
7
char *sperrungEinfuegen( char s[], int nSperrung, int max )
8
{
9
  int  iQuelle;
10
  int  iZiel = 0;
11
  char hilfsv[max];  // geht so nur bei gcc, kein ANSI-C!
12
13
  if( max > (((strlen(s)-1)*(nSperrung+1))+1) )
14
  {
15
    for( iQuelle=0; iQuelle<strlen(s); iQuelle++ )
16
    {
17
      int  iSperrung;
18
      hilfsv[iZiel++] = s[iQuelle];
19
      for( iSperrung=0; iSperrung<nSperrung; ++iSperrung )
20
      {
21
        hilfsv[iZiel++] = ' ';
22
      }
23
    }
24
    hilfsv[iZiel++] = '\0';  // terminieren
25
    strcpy( s, hilfsv );     // zurückkopieren
26
    return s;
27
  }
28
  else
29
  {
30
    fprintf( stderr, "Fehler: String zu lang zum Sperren\n" );
31
    return NULL;
32
  }
33
}
34
35
int main()
36
{
37
  char s[200]="Wie gehts?";
38
39
  sperrungEinfuegen( s, 2, sizeof(s) );
40
  printf( "%s\n", s );
41
42
  return 0;
43
}

von M. B. (massi)


Lesenswert?

Ja super dankeschön für ausführliche Erklärung!
jetzt funktionierts ;)

von Karl H. (kbuchegg)


Lesenswert?

Darüber

     if(max>(((strlen(s)-1)*(sperrung+1))+1)){

muss ich noch brüten, aber ich denke das ist falsch.

von M. B. (massi)


Lesenswert?

Da hast du Recht Klaus!

von Klaus W. (mfgkw)


Lesenswert?

Karl heinz Buchegger schrieb:
> Darüber
>
>      if(max>(((strlen(s)-1)*(sperrung+1))+1)){
>
> muss ich noch brüten, aber ich denke das ist falsch.

Sicher?
Da sehe ich ausnahmsweise keine dunklen Wolken.
Ich würde fast sagen, das war die einzige richtige Stelle im Programm 
:-)

von M. B. (massi)


Lesenswert?

Ich glaube das ist richtig

-----   if(max>(((strlen(s)-1)*(sperrung+1))+1)){   ------

Das ist die Rechnung für die Bytes nach der Änderung.
Die soll nämlich kleiner sein als die max. zugewiesen Anzahl

von Klaus W. (mfgkw)


Lesenswert?

((strlen(s)-1)*(sperrung+1))+1 ist tatsächlich die Anzahl der
Nutzbytes. Dazu kommt noch 1 für die abschließende 0, aber durch
max>... klappt es gerade so.

(Wenn ich mich jetzt nicht verzählt habe.
Mal sehen, was KHB noch ausbrütet...)

von M. B. (massi)


Lesenswert?

Ja Klaus genauso hab ich es auch gerechnet.

Mathematik ist eher meine Stärke als Programmieren aber da muss man halt 
durch...

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> Sicher?

Ich bin mir noch nicht sicher. Auf jeden Fall ist es mir deutlich zu 
kompliziert geschrieben.

Was ist die Idee?
Abzutesten ob der Platz ausreicht.

Wieviel PLatz braucht man.

   zunächst mal den Platz für den Originalstring
   dann für jeden Zwischenraum noch einmal nSperrung Zeichen
   und natürlich +1 für das '\0'

Zwischenräume gibt es Anzahl Zeichen - 1

Also wird benötigt

   len = strlen(s)

   len  +  ( len - 1 ) * nSperrung  +  1

ich seh da jetzt nicht, wie man von dem auf

   ( len - 1 ) * ( nSperrung + 1 ) + 1

kommen könnte. Man zählt um 1 zu wenig.
Auf der anderen Seite fragt er auf größer ab.

Also: Könnte richtig sein.

Für meinen Geschmack ist der Originalausdruck zu undurchsichtig und ich 
würde das wie gezeigt in die Einzelteile aufdröseln. Schön mit 
Zeilenumbruch und einem Kommentar daneben
1
   len = strlen(s)
2
3
   needed = len  +                       // wir brauchen: Platz für den Originalstring                       
4
            ( len - 1 ) * nSperrung  +   //                für jeden Zwischenraum
5
            1;                           //                und noch ein '\0'
6
7
8
  if( max < needed ) {
9
    printf( "Fehler" );
10
    return;
11
  }
12
13
  ...
dann ist das auch in 2 Monaten noch auf einen Blick nachvollziehbar.

von M. B. (massi)


Lesenswert?

Ja da sieht man deine Erfahrung...
Hab leider nur nen Crashkurs

trotzdem danke an euch
dass es nicht noch mehr Nächte wurden ;)

von Klaus W. (mfgkw)


Lesenswert?

Karl heinz Buchegger schrieb:
> len  +  ( len - 1 ) * nSperrung  +  1
>
> ich seh da jetzt nicht, wie man von dem auf
>
>    ( len - 1 ) * ( nSperrung + 1 ) + 1

Bei dir ist schon Platz für die abschließende 0 enthalten?

Wenn ich nicht vertan habe, geht es so (statt len nehme ich
mal x, ist kürzer):
1
   x + ( x - 1 ) * nSperrung + 1 + (x-1) - (x-1)
2
   x + (x-1)*nSperrung + (x-1)*1 + 1 - (x-1)
3
   x + (x-1)*(nSperrung+1) + 1 - (x-1)
4
   (x-1)*(nSperrung+1) + x + 1 - (x-1)
5
   (x-1)*(nSperrung+1) + 1 - (-1)
6
   (x-1)*(nSperrung+1) + 2

Das ist um 1 größer als der Term aus dem Quelltext.

von Klaus W. (mfgkw)


Lesenswert?

Karl heinz Buchegger schrieb:
> Für meinen Geschmack ist der Originalausdruck zu undurchsichtig und ich
> würde das wie gezeigt in die Einzelteile aufdröseln.

Das ist natürlich richtig, das sehe ich auch so.

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> Karl heinz Buchegger schrieb:
>> len  +  ( len - 1 ) * nSperrung  +  1
>>
>> ich seh da jetzt nicht, wie man von dem auf
>>
>>    ( len - 1 ) * ( nSperrung + 1 ) + 1
>
> Bei dir ist schon Platz für die abschließende 0 enthalten?
>
> Wenn ich nicht vertan habe, geht es so (statt len nehme ich
> mal x, ist kürzer):
>
1
>    x + ( x - 1 ) * nSperrung + 1 + (x-1) - (x-1)
2
>    x + (x-1)*nSperrung + (x-1)*1 + 1 - (x-1)
3
>    x + (x-1)*(nSperrung+1) + 1 - (x-1)
4
>    (x-1)*(nSperrung+1) + x + 1 - (x-1)
5
>    (x-1)*(nSperrung+1) + 1 - (-1)
6
>    (x-1)*(nSperrung+1) + 2
7
>
>
> Das ist um 1 größer als der Term aus dem Quelltext.

Eben.
Und da er auf größer abfrägt, passt es wieder.
Also Entwarnung, da hat mein Gefühl getrogen.

von Klaus W. (mfgkw)


Lesenswert?

Wie meinte Loriot so schön?
"Mit deinem Gefühl stimmt etwas nicht."

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.