mikrocontroller.net

Forum: Compiler & IDEs Stringspielerei


Autor: M. Bub (massi)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Klaus Wachtler (mfgkw)
Datum:

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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: M. Bub (massi)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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?)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. Bub schrieb:
> Das mit dem k++;

nein, k--

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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ß :-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: M. Bub (massi)
Datum:

Bewertung
0 lesenswert
nicht 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;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Über Geschmack kann man streiten, über Stil sowieso.

Trotzdem mal ein Vorschlag, den ich deutlich lesbarer finde:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// kopiert String auf sich selbst, und fügt dabei je (nSperrung)
// Leerzeichen ein:
char *sperrungEinfuegen( char s[], int nSperrung, int max )
{
  int  iQuelle;
  int  iZiel = 0;
  char hilfsv[max];  // geht so nur bei gcc, kein ANSI-C!

  if( max > (((strlen(s)-1)*(nSperrung+1))+1) )
  {
    for( iQuelle=0; iQuelle<strlen(s); iQuelle++ )
    {
      int  iSperrung;
      hilfsv[iZiel++] = s[iQuelle];
      for( iSperrung=0; iSperrung<nSperrung; ++iSperrung )
      {
        hilfsv[iZiel++] = ' ';
      }
    }
    hilfsv[iZiel++] = '\0';  // terminieren
    strcpy( s, hilfsv );     // zurückkopieren
    return s;
  }
  else
  {
    fprintf( stderr, "Fehler: String zu lang zum Sperren\n" );
    return NULL;
  }
}

int main()
{
  char s[200]="Wie gehts?";

  sperrungEinfuegen( s, 2, sizeof(s) );
  printf( "%s\n", s );

  return 0;
}

Autor: M. Bub (massi)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Darüber

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

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

Autor: M. Bub (massi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da hast du Recht Klaus!

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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 
:-)

Autor: M. Bub (massi)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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...)

Autor: M. Bub (massi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja Klaus genauso hab ich es auch gerechnet.

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
   len = strlen(s)

   needed = len  +                       // wir brauchen: Platz für den Originalstring                       
            ( len - 1 ) * nSperrung  +   //                für jeden Zwischenraum
            1;                           //                und noch ein '\0'


  if( max < needed ) {
    printf( "Fehler" );
    return;
  }

  ...
dann ist das auch in 2 Monaten noch auf einen Blick nachvollziehbar.

Autor: M. Bub (massi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja da sieht man deine Erfahrung...
Hab leider nur nen Crashkurs

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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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):
   x + ( x - 1 ) * nSperrung + 1 + (x-1) - (x-1)
   x + (x-1)*nSperrung + (x-1)*1 + 1 - (x-1)
   x + (x-1)*(nSperrung+1) + 1 - (x-1)
   (x-1)*(nSperrung+1) + x + 1 - (x-1)
   (x-1)*(nSperrung+1) + 1 - (-1)
   (x-1)*(nSperrung+1) + 2

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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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):
>
>    x + ( x - 1 ) * nSperrung + 1 + (x-1) - (x-1)
>    x + (x-1)*nSperrung + (x-1)*1 + 1 - (x-1)
>    x + (x-1)*(nSperrung+1) + 1 - (x-1)
>    (x-1)*(nSperrung+1) + x + 1 - (x-1)
>    (x-1)*(nSperrung+1) + 1 - (-1)
>    (x-1)*(nSperrung+1) + 2
> 
>
> 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.

Autor: Klaus Wachtler (mfgkw)
Datum:

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.