verkehrte string und speicherverwaltung

Heinzi1991

Erfahrenes Mitglied
Aufgabenstellung:
Es sollen von der Konsole (stdin) Zeichen eingelesen werden, bis das Ende des Eingabestreams (EOF) erreicht ist. Beim Testen kann man den Stream mit dem Tastenkürzel Strg+D (in Windows Strg+Z) beenden, oder man leitet als Eingabe für das Programm eine Datei auf stdin des Programms um. Das sieht mit der Datei input.txt zum Beispiel so aus:
Code:
./hw5 < input.txt

Eingelesen werden soll in einen dynamisch reserviertem Speicher (malloc), der wenn er voll ist vergrößert wird (realloc). Sobald der Eingabestream zu Ende ist, werden die eingelesenen Zeichen rückwärts wieder ausgegeben und mit einem "\n" abgeschlossen.

Im Falle eines Fehlers soll die Fehlermeldung "Error: Out of memory!\n" ausgegeben werden und das Programm mit dem Fehlercode 1 ohne weitere Ausgaben beendet werden.


Beispielaufruf:
Code:
% ./hw5
Hallo Welt!\n
Jetzt noch ein Zeilenumbruch und dann EOF.\n[EOF]
\n
.FOE nnad dnu hcurbmunelieZ nie hcon tzteJ\n
!tleW ollaH\n

mein code ist jetzt ein bisschen anders, aber er funktioniert so einigermaßen, will es aber natürlich richtig machen, aber ehrlich gesagt hab ich keinen plan was ich machen soll, genau!
kann mir jemand schriftlich, also punkt für punkt (kann auch grob sein) zusammenfassen was ich machen soll!

PS: codeabschnitte sind natürlich erlaubt!

Vielen Dank im voraus!
 
Hallo Heinzi1991

Wie sieht denn dein Code aus?

Grundsätzlich: Mit fgetc(stdin) die einzelnen Zeichen in einer Schlaufe einlesen, bis der Rückgabewert EOF ist. Die Zeichen in einem char-Array, der sich dynamisch erweitert, abspeichern.

C:
int main(int argc, char* argv[])
{
    char* speicher = NULL;
    char* tmp = NULL;
    size_t size = 0;
    char c = 0;
    while((c = fgetc(stdin)) != EOF)
    {
        size++;
        tmp = (char*)malloc(size);
        if(tmp == NULL)
        {
            printf("Error: Out of memory!\n");
            return 1;
        }
        memcpy(tmp,speicher,size);
        speicher = (char*)realloc(speicher,size);
        if(speicher == NULL)
        {
            printf("Error: Out of memory!\n");
            return 1;
        }
        memcpy(speicher,tmp,size);
        speicher[size] = c;
        free(tmp);
    }
    //Nun zur Ausgabe
    for(size_t i = size;i>0;i--)
    {
        printf("%c",speicher[i]);
    }
    printf("\n");
    free(speicher);
    return 0;
}

Ungetestet und ohne Abbruchmechanismen.

Gruss
cwriter
 
Hi

zeig doch mal deinen "anderen" Code, dann kann man beim Verbessern helfen

Pseudocode:
Code:
uint fill=0, gesamt=10;
char *array;
char c;
array=malloc(gesamt);
wenn mallocfehler dann fehler-printf und exit 1
while 1
{
    c =getc();
    if(c == -1)
        break;
    array[fill++] = c;
    wenn fill >= gesamt
    {
        gesamt *= 2;
        realloc(array, gesamt);
        wenn reallocfehler dann fehler-printf und exit 1
    }
}
for(--fill;fill >= 0;fill--)
    putc(array[fill]);
putc('\n');
free(array);

edit: Ok, einen fertigen Code hast du ja auch schon bekommen :D
 
@sheel
"Fertig"... Ich könnte wetten, dass es da noch ein paar schöne Memory Leaks drin hat ;-)
Ich bin gerade etwas unsicher: Realloc garantiert ja nicht, dass der Speicherbereich erweitert wird. Müsste bei deinem Pseudocode nicht noch ein temporärer Speicher erstellt werden?

@Heinzi1991
Entschuldige bitte, dass es kein Ausschnitt ist. Ich konnte einfach nicht widerstehen :-(
Gibt es noch irgendwelche Vorgaben, WIE der Speicher erweitert werden soll? Mein Code bietet eher langsame Einzelschritte, verbraucht aber nur den benötigten Speicher, während sheels Variante schneller ist, aber auch "zu viel" Speicher (Vielleicht 10 Bytes mehr) verbrauchen kann.

Gruss
cwriter
 
Müsste bei deinem Pseudocode nicht noch ein temporärer Speicher erstellt werden?
Da hast du Recht.
Wenn man den größeren Speicher nicht bekommt braucht man zumindest noch was zum free´n.


(
Andererseits...
"Wenn reallocfehler dann mach blabla"
Wie diese Prüfung erfolgt bleibt offen.
Da steht nirgends, dass keine zusätzliche Variable dazugehört :D
)
 
genau; also es besteht keine weitere prüfung oder so! alles ganz easy; mein code bestand darin die datei input.txt zu lesen und dann auszugeben! aber dann hab ich gelesen das man das eig nicht darf!
werde jetzt einmal deine lösung checken wegen den angeblichen leaks und so und werde bescheid geben wenn alles passt oder eine fehelerkorrektur durchführen und dann in fehlerlosen code posten!
Aber danke vielmals
 
@cwriter: Mir will nicht in den Kopf, wozu ein voll reservierte tmp
und die Kopiererei gut ist...jedenfalls, zu den Speicherlecks :)D):

Zeile 16 erst nach 17, weil zuerst das Array noch zu klein ist.
Bei den beiden Error-returns zuerst freigeben, was vorhanden ist.
Zeile 24 ist ein ungültiger Index.
Und die Schleife auf 28 zählt um eins verschoben.
 
Ohoh, stimmt natürlich.
C:
memcpy(tmp, speicher, size-1); //line 16
Zeile 17 muss nicht vor Zeile 16, da ja auch ein Speicherbereich alloziert werden könnte, der die Daten nicht beinhaltet.
Zur Kopiererei: Gut möglich, dass ich irre, aber kopiert realloc den content gleich auch zur neuen Destination? Ich meine, dass das eben nicht geben ist, und daher wollte ich da nichts riskieren.
C:
speicher[size-1] = c; //line 24
Bei der for-Schlaufe sollte es reichen, alle Konstanten -1 zu nehmen.

Gruss cwriter
 
Gut möglich, dass ich irre, aber kopiert realloc den content gleich auch zur neuen Destination?
Ich meine, dass das eben nicht geben ist, und daher wollte ich da nichts riskieren.
Sollte es schon machen
(falls überhaupt eine Verschiebung nötig ist.
Eventuell kann man das Array ja auch am alten Platz lassen
und nur die Reservierung nach hinten raus vergrößern oÄ.
Impl.abhängig)
 
ok es schaut verdammt gut aus! jetzt gibt es nur noch vier Probleme!

1. Problem: Der erste Buchstabe wird nicht ausgespuckt und in der ausgabe! Also bei "hallo welt" gibt er "tlew olla" aus!

2. Problem: er beendet das Einlesen nicht bei [EOF] ich muss das Programm immer selbstständig abbrechen, bzw das einlesen!

3. Problem: size_t ist nur in C99 möglich, aber wir benutzen keine Ahnung welches C! also ich benutze Ubuntu 12.04 LTS und die vorigen Aufgaben haben reibungslos funktioniert!

4. Problem:
Warnung: Implizierte Deklaration der Funktion >>memcpy<<
Warnung: Unverträgliche implizite Deklaration in der eingebauten Funktion >>memcpy<<
 

Neue Beiträge

Zurück