PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C und die Strings



Bääääär
16.05.2009, 17:06
Hallo Ihr!

Ich versuche grade für meine SD-Karte eine Art pseudo-xml zu realisieren. Nach dem Muster
<tagname=wert>
sind da Werte drauf. Allerdings habe ich arge probleme mit den Strings in C. Folgendes funktioniert irgendwie nicht.


// Findet das nächste Zeichen mit dem übergebenen Wert in einer Datei, ansonsten wird 0 zurückgegeben
unsigned long int tpx_find_char(char s) {
unsigned long int count=0;
unsigned long int seek=file.length;
char p;
do {
count++;
p = ffread();
} while (!((--seek<0) || (p==s)));
return count;
}

int tpx_read_tag(char* name, char* value) {
char *s;
int count;
int i=0;

// Wenn keine Datei offen ist, abbrechen
if (!fileopened) {
return 1;
}

// Beginn des tags finden
tpx_find_char('<');
// Zeichen bis zum Ende des Namens (also bis zum '=') zählen
count = (int) tpx_find_char('=') -1;
// zurück setzen
file.seek -= count;

// Daten Einlesen...
s = (char*) malloc(count+1);

for (i=0; i<count; i++) {
s[i] = ffread();
s[i+1] = '\0';
}
// und ausgeben.
strcpy(name, s);
free(s);

// Zeichen bis zum Ende des Tags (also bis zum '>') zählen
count = (int) tpx_find_char('>');
// zurück setzen
file.seek -= count;

// Daten Einlesen...
s = (char*) malloc(count+1);

for (i=0; i<count; i++) {
s[i] = ffread();
s[i+1] = '\0';
}
for (i=0; i<count; i++) {
s[i] = ffread();
}
// und ausgeben.
strcpy(value, s);
free(s);

return 0;
}

tpx_find_char geht ganz gut, aber das einlesen der Zeichen von der SD in einen String funktioniert nicht ansatzweise...

Danke für Hilfe,
Bääääär

sternst
16.05.2009, 18:55
Ich verstehe nicht so ganz, warum du das so kompliziert machst. Die Ergebnisse werden doch letztlich nach name und value geschrieben, wobei die Funktion einfach davon ausgeht, dass dort schon jeweils genug Platz vorhanden sein wird. Wozu also dieses komplizierte Zwischenspeichern mit Längenermittlung fürs malloc etc? Warum schreibst du die Zeichen nicht gleich direkt nach name und value?

Pseudocode:

skip bis '<'
while (zeichen aus file nicht '=')
schreibe zeichen nach name
terminiere name
while (zeichen aus file nicht '>')
schreibe zeichen nach value
terminiere value

Bääääär
17.05.2009, 11:46
Hmm, habs jetzt so versucht aber in den Rückgabewerten steh nur Müll und der Compiler gibt mir bei strcat Warnungen aus, weil ich aus einem unsigned char einen (char*) mache...

Funktionen:
// Findet das nächste Zeichen mit dem übergebenen Wert in einer Datei, ansonsten wird -1 zurückgegeben
unsigned long int tpx_find_char(char s) {
unsigned long int count=-1;
unsigned long int seek=file.length;
char p;

do {
count++;
p = ffread();

} while (!((--seek<0) || (p==s)));

return count;
}

int tpx_read_tag(char* name, char* value) {
char s;

// Wenn keine Datei offen ist, abbrechen
if (!fileopened) {
return 1;
}

// Beginn des tags finden
tpx_find_char('<');

unsigned long int seek=file.length;
s = ffread();
seek--;
do {
strcat(name, (char*) s);
s = ffread();
} while ((s=='=') || !(seek--));

s = ffread();
seek--;
do {
strcat(value, (char*) s);
s = ffread();
} while ((s=='>') || !(seek--));


return 0;
}

Und der Aufruf:
int main(void) {

char *tag;
char *value;

lcd_init();
lcd_clear();

sd_init();

lcd_clear();

tag = malloc(30);
value = malloc(30);
tag[0] = '\0';
value[0] = '\0';

char file[] = "testdat.txt";
fat_str(file);
ffopen(file);
lcd_clear();
tpx_read_tag(tag, value);
lcd_string("T: ");
lcd_string(tag);
lcd_set_cursor(0,1);
lcd_string("V: ");
lcd_string(value);
_delay_ms(1000);
lcd_clear();

tag[0] = '\0';
value[0] = '\0';

tpx_read_tag(tag, value);
lcd_string("T: ");
lcd_string(tag);
lcd_set_cursor(0,1);
lcd_string("V: ");
lcd_string(value);
_delay_ms(1000);

ffclose();

return 0;
}

sternst
17.05.2009, 12:28
unsigned long int seek=file.length;
s = ffread();
seek--;
// Ich vermute, damit willst du erreichen, nicht über das Ende der Datei "hinauszulesen".
// Geht so aber nicht, weil du nicht berücksichtigst, wo in der Datei du gerade bist.
do {
strcat(name, (char*) s);
// Schon wieder zu kompliziert gedacht (und das Gedachte auch falsch realisiert).
// Warum nicht einfach *name++ = s; ?
// (dann aber nach der Schleife die Terminierung nicht vergessen: *name = 0; )
s = ffread();
} while ((s=='=') || !(seek--));
// while heißt "während" und nicht "bis".
// Deine Bedingung hat die falsche Logik.