INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
File-Lese-Funktion mir Rückgabe wert ANSI C string: wie?
16.02.2015, 20:08 (Dieser Beitrag wurde zuletzt bearbeitet: 16.02.2015 22:35 von HaWe.)
Beitrag #1
File-Lese-Funktion mir Rückgabe wert ANSI C string: wie?
hallo,
ich möchte eine Funktion programmieren, die aus einem geöffneten File ein Stück liest, bis ein Komma oder ein '\n' gelesen wird und dann den entsprechenden Null-terminierten C-ANSI-String als Teilstring zurückgibt.

Die Funktion soll heißen:
freads();

ich will sie NICHT als Erweiterung der SD File-Klasse programmieren, weil ich mich mit C++ Klassen nicht auskenne.

1. Frage: wie definiere ich den Rückgabestring?
Idee: *char[] freads(); Huh

2. Frage: wie mache ich das mit dem Übergabewert, nämlich dem File?
Am Anfang des Programms definiere ich ja
File MyFile.
Nun kann der aktuelle File ja auch anders heißen, z.B.
File SDfile
Idee: ich übergebe den Datentyp File mit der entspr. Instanziierung, also z.B
freads(File & xfile)
oder
freads(File *xfile)
und greife dann in der Funktion lokal auf die File-Methoden zurück, also z.B
xfile.read()

3. Frage: ist dadurch sichergestellt, dass der in der Unterfunktion weitergerückte Lesezeiger dann auch für andere anschließend aufgerufene Funktionen entsprechend weitergerückt ist?

wird das gehen?

Oder komme ich um ein Aufbohren der File-Klasse nicht herum ? Dodgy

ps, edit:
noch etwas:
wenn man Zahlen als string per sprintf() umformatiert, erhält man ja einen
uint8_t array[]
mit "unsigned" Bytes 0-255 (NICHT chars -128-+127 !!!) der am Schluss Null-terminiert ist.
Sketch verwendet aber komischerweise immer signed chars, was ziemlich bescheuert ist, denn das gibt Datenmist, aber Sketch ist da beratungsresistent.
Lesen will ich und muss ich aber definitiv unsigned, nicht signed - muss ich dann tatsächlich bei signed char bleiben?
(für ARMs wird ja (signed) char automatisch zu (unsigned) Byte, aber nicht für AVRs !)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
21.02.2015, 15:27
Beitrag #2
RE: File-Lese-Funktion mir Rückgabe wert ANSI C string: wie?
niemand eine Idee?
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
21.02.2015, 18:39
Beitrag #3
RE: File-Lese-Funktion mir Rückgabe wert ANSI C string: wie?
(16.02.2015 20:08)HaWe schrieb:  1. Frage: wie definiere ich den Rückgabestring?
Idee: *char[] freads(); Huh
Tja, Dein prinzipielles Problem hier ist, dass Du für sowas den Speicherplatz innerhalb der Funktion fread() allokieren müsstest. Dann könntest Du einen Zeiger darauf zurückgeben (also char* fread()). Dummerweise gibt es aber keine automatische Garbage Collection (kann bei C prinzipiell nicht gehen). Das bedeutet, dass Du dann jedesmal neuen Speicher anfordern würdest und so ganz schnell ein Memory Leak produzierst.
Du müsstest es also analog zum echten fread machen, in etwa:
Code:
int fread ( void * ptr, int maxsize, File* stream );
Das würde dann die gelesene Länge zurückgeben. Die Zeichenkette steht dann in (*ptr).

Zitat:2. Frage: wie mache ich das mit dem Übergabewert, nämlich dem File?
Siehe oben. Innerhalb der Funktion würdest Du dann sowas wie xfile->read() sagen können.

Zitat:3. Frage: ist dadurch sichergestellt, dass der in der Unterfunktion weitergerückte Lesezeiger dann auch für andere anschließend aufgerufene Funktionen entsprechend weitergerückt ist?
Normalerweise sollte sich das die File-Instanz merken. Durch die Übergabe eines Zeigers hat die Funktion ja dieselbe Instanz wie Du "außen" hast.

Zitat:wenn man Zahlen als string per sprintf() umformatiert, erhält man ja einen
uint8_t array[]
mit "unsigned" Bytes 0-255 (NICHT chars -128-+127 !!!)
Ist das so?
C++: http://www.cplusplus.com/reference/cstdio/sprintf/
ANSI-C: http://info.baeumle-courth.eu/c05.html
Die sagen beide, dass char* verwendet wird.

Zitat:Sketch verwendet aber komischerweise immer signed chars, was ziemlich bescheuert ist, denn das gibt Datenmist, aber Sketch ist da beratungsresistent.
Lesen will ich und muss ich aber definitiv unsigned, nicht signed - muss ich dann tatsächlich bei signed char bleiben?
Ich glaube sogar, dass die meisten C Implementierungen per Default signed char haben. D.h. char sind eigentlich immer signed. Allerdings ist das eigentlich egal. Zumindest wüsste ich keinen Fall, wo das ein Problem macht.

Zitat:(für ARMs wird ja (signed) char automatisch zu (unsigned) Byte, aber nicht für AVRs !)
Was meinst Du denn damit?

Falls ich mit einer Antwort helfen konnte, wuerde ich mich freuen, ein paar Fotos oder auch ein kleines Filmchen des zugehoerigen Projekts zu sehen.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
21.02.2015, 19:41 (Dieser Beitrag wurde zuletzt bearbeitet: 22.02.2015 11:16 von HaWe.)
Beitrag #4
RE: File-Lese-Funktion mir Rückgabe wert ANSI C string: wie?
hallo,
danke schon mal für deine Antwort!

erstmal das nachrangige Problem, zur char-Problematik:
Diese ist hier zunächst für das Lesen aus einem File nicht direkt betroffen, Probleme entstehen erst bei ASCII-Zeichen > 127 in einem Zeichenstring.
auf AVR Plattformen (Uno, Mega) übersetzt Sketch char mit signed char,
aber auf (der) ARM Plattform (Due) wird char mit unsigned char übersetzt.
Üblicherweise kann man hier diese Problematik ausschließen, indem man explizit signed vs. unsigned oder int8_t vs. uint8_t deklariert.
Das geht aber nicht mit char[], wenn es für Serial.print verwendet wird, denn dieser verlangt zwingend den (doppeldeutigen) Typ char[]. char[] ist aber AVR automatisch, implizit signed.
In einem Zeichenstring kann es aber keine negativen Zeichen geben. Stattdessen haben Zeichen einen Wert von 0 bis 255, davon sind 0 bis 127 Standard-ASCII, darüber stehen Sonderzeichen.
Jeder Versuch, hier char explizit als unsigned zu deklarieren und dann per Serial auszugeben , geht aber schief (Compiler error: Datentypen nicht kompatibel).
Das führt zu unlogischen Ergebnissen:
In jedem Falle müssten
char a=125;
char b=129; // (Überlauf !)
char c=-127;

Serial.println(a);
Serial.println(b);
Serial.println(c );

Serial.println(125);
Serial.println(129);
Serial.println(-127);
ein und dasselbe Ergebnis bringen, denn es sind ja identische Zahlen - tut es aber nicht.
Aber wie gesagt, für die Funktion ist es zunächst nicht wichtig, sondern erst dann, was man vorher oder nachher noch andere Zeichen in den String hineinpackt.







jetzt aber das primäre Problem:



zur Rückgabe:
ich hatte vor, in der aufrufenden Funktion z.B. zu deklarieren
char sbuf[60];
und dann aufrufen
sbuf= freads();

wie mache ich das dann am besten mit dem Rückgabewert von freads() ?

ps,

ich sah gerade:
fgets ist eigentlich eher das, was ich meinte:

char * fgets ( char * str, int num, FILE * stream );

Zitat:Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.

A newline character makes fgets stop reading, but it is considered a valid character by the function and included in the string copied to str.

A terminating null character is automatically appended after the characters copied to str.

Notice that fgets is quite different from gets: not only fgets accepts a stream argument, but also allows to specify the maximum size of str and includes in the string any ending newline character.

den gelesenen "newline character" würde ich aber im Rückgabestring NICHT haben wollen, denn der stört ja bei der Rückformatierung als Zahlenwert.
ob man das so in Sketch hinkriegt ?

fgets kennt Sketch ja überhaupt nicht.

versuche ich aber, das genau so zu deklarieren, steigt der Compiler mit Fehlermeldungen aus:
Code:
#include <SPI.h>
#include <SD.h>

#define SD_CSpin 4
File myFile;
char fname[64];

#define TimerMS() millis()

char * fgets ( char * str, int num, FILE * stream ) { ; }

char sbuf[60];


//================================================================================​=====
void setup() {
   myFile = SD.open(fname);
   sbuf= fgets(sbuf, 20, myFile);  // berichtigt!
}
//================================================================================​=====




//================================================================================​=====
void loop() {
  

}
//================================================================================​=====

Zitat:sketch_feb21a.ino: In function 'void setup()':
sketch_feb21a.ino:22:33: error: cannot convert 'File' to '__file*' for argument '3' to 'char* fgets(char*, int, __file*)'
Fehler beim Übersetzen
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
21.02.2015, 20:38
Beitrag #5
RE: File-Lese-Funktion mir Rückgabe wert ANSI C string: wie?
(21.02.2015 19:41)HaWe schrieb:  Das geht aber nicht mit char[], wenn es für Serial.print verwendet wird, denn dieser verlangt zwingend den (doppeldeutigen) Typ char[]. char[] ist aber AVR automatisch, implizit signed.
Na und?

Zitat:In einem Zeichenstring kann es aber keine negativen Zeichen geben. Stattdessen haben Zeichen einen Wert von 0 bis 255, davon sind 0 bis 127 Standard-ASCII, darüber stehen Sonderzeichen.
Es kommt dann darauf an, wie die Funktion (z.B. print) die Zahlen von -128 bis -1 interpretiert. Hast Du das ausprobiert?

Zitat:Das führt zu unlogischen Ergebnissen:
In jedem Falle müssten
char a=125;
char b=129; // (Überlauf !)
char c=-127;

Serial.println(a);
Serial.println(b);
Serial.println(c );

Serial.println(125);
Serial.println(129);
Serial.println(-127);
ein und dasselbe Ergebnis bringen, denn es sind ja identische Zahlen - tut es aber nicht.
Nein, das muss ganz und gar nicht dasselbe sein. println ist eine überladene Methode. D.h. dass abhängig vom Datentyp unterschiedliche Dinge passieren. Hier ein kleiner Ausschnitt aus Print.h:
Code:
void println(char, int = BYTE);
void println(int, int = DEC);
Bei Deinen ersten drei Aufrufen wird das erste println aufgerufen. Bei Deinen nächsten Aufrufen verwendest Du Zahlenkonstanten, die als int interpretiert werden. D.h. es wird die zweite Variante vom println aufgerufen.

Zitat:Aber wie gesagt, für die Funktion ist es zunächst nicht wichtig, sondern erst dann, was man vorher oder nachher noch andere Zeichen in den String hineinpackt.
Mach mal ein Beispiel dazu...

Zitat:ich hatte vor, in der aufrufenden Funktion z.B. zu deklarieren
char sbuf[60];
und dann aufrufen
sbuf= freads();
Das ist Quatsch. Durch die Deklaration von sbuf wird ein Speicherbereich von 60 Byte reserviert. sbuf ist dann ein Zeiger, der auf diese 60 Byte zeigt. (Das ist langweiliges Standard-C...)
Deine Zuweisung überschreibt dann den Zeiger sbuf mit was-auch-immer die Funktion freads zurückliefert.

Zitat:wie mache ich das dann am besten mit dem Rückgabewert von freads() ?
Gar nicht.

Zitat:fgets ist eigentlich eher das, was ich meinte:
char * fgets ( char * str, int num, FILE * stream );[/b]
Den Rückgabewert kann man bei fgets eigentlich nur verwenden, um eine "Erfolgsprüfung" zu machen. Auf gar keinen Fall sollte man sowas machen:
Code:
str = fgets(str, 10, &myFile);
Das würde nämlich im Fehlerfall str mit dem Nullpointer überschreiben. Der Speicherbereich, den man vorher reserviert hat, ist dann nicht mehr erreichbar. Ich halte daher schon die Definition von fgets für dämlich. Besser wäre es, die Anzahl der gelesenen Zeichen zurückzugeben. Dann kann so ein Blödsinn nicht passieren.

Zitat:den gelesenen "newline character" würde ich aber im Rückgabestring NICHT haben wollen, denn der stört ja bei der Rückformatierung als Zahlenwert.
ob man das so in Sketch hinkriegt ?
Klar, wo sollte da das Problem sein?

Zitat:versuche ich aber, das genau so zu deklarieren, steigt der Compiler mit Fehlermeldungen aus:
[code]
File myFile;
char fname[64];

char * fgets ( char * str, int num, FILE * stream ) { ; }

char sbuf[60];

void setup() {
myFile = SD.open(fname);
fname= fgets(sbuf, 20, myFile);
}
Klar, "File" ist ja auch nicht "FILE". Außerdem müsste es &myFile heißen, weil Du einen Zeiger übergeben musst.
Das "fname= fgets(sbuf, 20, myFile);" ist übrigens auch nicht so toll. Das ist das, was ich oben schon erklärt habe. fname zeigt danach (im Erfolgsfall) auf denselben Speicherbereich wie sbuf. Der Speicherbereich, den Du mit "char fname[64]" reserviert hast ist damit verloren gegangen.
All das ist übrigens C-Basiswissen. Das hat gar nichts mit "Sketch" zu tun.

Gruß,
Thorsten

Falls ich mit einer Antwort helfen konnte, wuerde ich mich freuen, ein paar Fotos oder auch ein kleines Filmchen des zugehoerigen Projekts zu sehen.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
21.02.2015, 20:43 (Dieser Beitrag wurde zuletzt bearbeitet: 21.02.2015 21:01 von HaWe.)
Beitrag #6
RE: File-Lese-Funktion mir Rückgabe wert ANSI C string: wie?
wüsste ich, wie es geht, würde ich nicht fragen.
Ich möchte aber den String als Rückgabewert haben, so wie ihn fgets als Rückgabewert liefern würde.
(Der Grund ist, dass ich den Rückgabe-String direkt in einer anderen Funktion weiterverwenden kann.)

(Man könnte ja z.B. auch in der Funktion eine Fehlerprüfung machen, die die Rückgab eine Nullpointers verhindert.)

Also wie geht es mit dem string als Rückgabewert?

ps, in dem Code war ein Tippfehler, es hätte heißen müssen:

sbuf= fgets(sbuf, 20, myFile);
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
21.02.2015, 21:59
Beitrag #7
RE: File-Lese-Funktion mir Rückgabe wert ANSI C string: wie?
(21.02.2015 20:43)HaWe schrieb:  Ich möchte aber den String als Rückgabewert haben, so wie ihn fgets als Rückgabewert liefern würde.
Dann mach's doch so:
Code:
char* fgets ( char* str, int num, File * stream ) {
...
...
...
  return str;
}

Zitat:(Der Grund ist, dass ich den Rückgabe-String direkt in einer anderen Funktion weiterverwenden kann.)
Das geht aber auch so:
Code:
fgets ( str, 10, &myFile );
irgendeineFunktion(str);
Damit spart man sogar ein paar Zeichen.

Falls ich mit einer Antwort helfen konnte, wuerde ich mich freuen, ein paar Fotos oder auch ein kleines Filmchen des zugehoerigen Projekts zu sehen.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
21.02.2015, 23:10
Beitrag #8
RE: File-Lese-Funktion mir Rückgabe wert ANSI C string: wie?
danke, das werde ich probieren!
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  String / HTTP Request Marc2014 2 44 Heute 09:05
Letzter Beitrag: amithlon
  No such file Brother Tak 3 104 21.11.2016 10:24
Letzter Beitrag: Brother Tak
  String zusammensetzen Mathias 13 547 01.09.2016 21:15
Letzter Beitrag: Mathias
  String-Array füllen? torsten_156 9 451 08.07.2016 20:07
Letzter Beitrag: amithlon
  String in EEPROM Speichern BennIY 2 415 27.06.2016 10:23
Letzter Beitrag: BennIY
  Funktion mit Parameterübergabe - u8g torsten_156 8 400 22.06.2016 18:53
Letzter Beitrag: Pit
  String - Buchstabenposition auswerten scritch 5 662 01.04.2016 16:25
Letzter Beitrag: rkuehle
  Funktion in Loop einmalig ausführen Haustechno 4 646 09.03.2016 22:43
Letzter Beitrag: Haustechno
  String nach UTF16 konvertieren (UTF-16) ThoEngel 0 301 20.02.2016 19:22
Letzter Beitrag: ThoEngel
  HC-05 Modul auf Funktion prüfen. arduinofan 2 365 03.02.2016 19:18
Letzter Beitrag: arduinofan

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste