String zurückgeben

Gast #1443997
Hallo,
ich versuche gerade eine funktion zu schreiben die einen String 
zurückgibt, klappt leider nicht.
1
char *uart_gets()
2
{
3
  char string[20];
4
  char c;
5
  int i=1;
6
  c = uart_getc();
7
  if(!(c & UART_NO_DATA))
8
  {
9
  string[0] = c;
10
  do {
11
    c = uart_getc();
12
    string[i] = c;
13
    i++;
14
    }while(c != '\0');
15
  //uart_puts(string);
16
  return string;
17
  }
18
}
Geht das irgendwie ohne String als Zeiger zu deklarieren?
Gruß
Bart
Bart schrieb:
> Hallo,
> ich versuche gerade eine funktion zu schreiben die einen String
> zurückgibt, klappt leider nicht.
>
1
char *uart_gets()
2
> {
3
>   char string[20];
4
>   char c;
5
>   int i=1;
6
>   c = uart_getc();
7
>   if(!(c & UART_NO_DATA))
8
>   {
9
>   string[0] = c;
10
>   do {
11
>     c = uart_getc();
12
>     string[i] = c;
13
>     i++;
14
>     }while(c != '\0');
15
>   //uart_puts(string);
16
>   return string;
17
>   }
18
> }
> Geht das irgendwie ohne String als Zeiger zu deklarieren?

Nein.
Dein Problem:
Du gibst die Adresse einer lokalen Variable zurück.
In C ist das ein absolutes NoNo.
Die Variable existiert nicht mehr, nachdem die Funktion verlassen wurde. 
Der Aufrufer hat daher die Adresse einer Variablen, die es nicht mehr 
gibt.

Abhilfe:
Gib in die Funktion die Adresse des char Arrays hinein, in die die 
Funktion schreiben darf.
Gast
Morgen
1
char string[20];

ist nur bis zum ende der Funktion gültig und nach dem verlassen weg!
man macht so was anders:

1) man arbeitet über einen globalen Puffer <- hier glaub ich besser
2) man übergibt der Funktion einen Pointer auf den Puffer wo die Werte 
rein geschrieben werden

mfg
Stephan
Persönliche Seite
überlegen wir doch mal...

du legst am Anfang der Fkt. deinen String an (entspricht einem 
Speicherbereich) und arbeitest damit.

Am Ende der Fkt. wird dieser Speicher wieder freigegeben, weil denn dann 
ja rein theoretisch keiner mehr brauch...

Daher kann dein Ansatz nicht funktionieren...

Du könntest den String global machen oder eine Zeiger auf einen String 
übergeben und dann dann wieder zurückgeben

Ach ja:
>Geht das irgendwie ohne String als Zeiger zu deklarieren?
Das machst du da oben schon ohne Ende...[]= zeiger in C
Gast
Danke euch, mir fehlt irgendwie echt die Disziplin für C ;)
1
void uart_gets(char *test)
2
{
3
  char string[20];
4
  char c;
5
  int i=1;
6
  c = uart_getc();
7
  if(!(c & UART_NO_DATA))
8
  {
9
  *test = c;
10
  do {
11
    test++;
12
    *test = uart_getc();
13
    }while(*test != '\0');
14
  }
15
}
 So läufts falls es jemandem weiterhilft.
Bart schrieb:
> Danke euch, mir fehlt irgendwie echt die Disziplin für C ;)
>
1
void uart_gets(char *test)
2
> {
3
>   char string[20];
4
>   char c;
5
>   int i=1;
6
>   c = uart_getc();
7
>   if(!(c & UART_NO_DATA))
8
>   {
9
>   *test = c;
10
>   do {
11
>     test++;
12
>     *test = uart_getc();
13
>     }while(*test != '\0');
14
>   }
15
> }
16
>
 So läufts falls es jemandem weiterhilft.

Ähm. schau dir bitte die Funktion noch einmal genau an.
Vor allem der 2.te Aufruf der uart_getc() bzw. die Auswertung dessen was 
er retourniert ist nicht koscher. Stell dir einfach vor, du hast einen 
Schweizer, der etwas langsamer tippt, am anderen Ende der Leitung.
Auch die Steuerung der do-while Schleife ist ... gelinde gesagt: Mist. 
Was muss denn ein Benutzer drücken, damit die uart_gets das als 
Stringende interpretiert?

Und wie kriegt ein Benutzer eigentlich einen leeren String an deine 
Funktion durch?

Wozu benötigt deine Funktion die lokalen Variablen string und i?

Und weißt du, was an der C-Standardfunktion gets() schlecht designed 
ist? So schlecht, dass diese Funktion nicht benutzt werden sollte, 
sondern statt dessen immer fgets() benutzt werden muss?
Gast
Oh, harsche Kritik...
1
void uart_gets(char *test)
2
{
3
  char c;
4
  c = uart_getc();
5
  if(!(c & UART_NO_DATA))
6
  {
7
  *test = c;
8
  do {
9
    test++;
10
    *test = uart_getc();
11
    }while(*test != '\0');
12
  }
13
}
Die Kritik mit dem Bufferoverflow verstehe ich ja noch, aber was ist an 
der Schleife so schlecht? \0 ist das End of Stringzeichen, und damit 
werden die gesendeten Strings immer abgeschlossen. Leere Strings werden 
nicht gesendet, das wird auf PC-Seite so gemanaged.
Bart schrieb:

> der Schleife so schlecht? \0 ist das End of Stringzeichen, und damit
> werden die gesendeten Strings immer abgeschlossen.

Dann musst du dazu sagen, WER denn die Strings sendet!
Ist die Funktion so universell geschrieben, dass das egal ist, dann 
braucht man nichts dazusagen. Aber wenn eine Funktion nur in bestimmten 
Sonderfällen funktioniert, dann sollte man das auch dazusagen.

1
  do {
2
    test++;
3
    *test = uart_getc();
4
    }while(*test != '\0');

Das wird bei langsamen Baudraten wahrscheinlich immer noch die 
uart_getc() outperformen und entweder ein vorzeitiges Stringende 
anzeigen oder aber den zuletzt empfangenen Character entsprechend oft 
duplizieren oder den String mit UART_NO_DATA fluten.
Je nachdem wie uart_getc den Fall behandelt: Ich hab noch nichts weiter 
gekriegt. Dass es den Fall behandelt sieht man ein paar Zeilen darüber. 
Da liefert die Funktion einen Fehler UART_NO_DATA
Gast
Du kannst die lokle string Variable auch als static deklarieren, dann 
wird die Variable nicht temporär auf dem Stack abgelegt sondern bleibt 
am "leben" auch wenn die Funktion verlassen wird...
1
char *uart_gets()
2
{
3
  static char string[20];   //nicht auf dem Stack...
4
  char c;
5
  int i=1;
6
  c = uart_getc();
7
  if(!(c & UART_NO_DATA))
8
  {
9
  string[0] = c;
10
  do {
11
    c = uart_getc();
12
    string[i] = c;
13
    i++;
14
    }while(c != '\0');
15
  //uart_puts(string);
16
  return string;
17
  }
18
}
Gast
Peter schrieb:

> Du kannst die lokle string Variable auch als static deklarieren,

Womit die Funktion nicht mehr reentrant ist. Das mag auf einem 
Mikrocontroller meist keine Rolle spielen, auf grossen Systemen geht's 
spaetestens mit Threads uebel schief.
Peter schrieb:
> Du kannst die lokle string Variable auch als static deklarieren, dann
> wird die Variable nicht temporär auf dem Stack abgelegt sondern bleibt
> am "leben" auch wenn die Funktion verlassen wird...

Aber Vorsicht mit dieser Technik. Sowas geht ganz schnell ins Auge:
1
   char* FirstString;
2
   char* SecndString;
3

4
   FirstString = uart_gets();
5
   SecndString = uart_gets();

Und dann such mal schön, warum FirstString immer identisch ist zu 
SecndString :-)

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.