"Christmas - the time to fix the computers of your loved ones" « Lord Wyrm

stringtables in c befüllen aus filestream

charmin 05.03.2016 - 17:31 2207 7
Posts

charmin

Super Moderator
Muper Soderator
Avatar
Registered: Dec 2002
Location: aut_sbg
Posts: 13979
hi, oc.at

Bin wieder mal zu dumm.

Bitte um Hilfe.

Ich versteh nicht, warum ich meine einzelnen eingelesenen zeilen nicht in meine stringtabelle schön reinbring. Er speichert immer nur den letzten reinkopierten inputstring, ich möcht aber Zeile 1 in bigstring[1] drinhaben, zeile 2 in bigstring[2] usw, usf.

Hätte mich daran orientiert:

http://openbook.rheinwerk-verlag.de..._zeiger_009.htm

Code: C
/* ptrptr5.c */
#include <stdio.h>
#include <stdlib.h>

int main(void) {
   char *text[500];
   char str1[] = "Text1";
   char str2[] = "Text2";
   char str3[] = "Text3";

   text[0] = str1;
   text[1] = str2;
   text[2] = str3;

   printf("%s %s %s\n", text[0], text[1], text[2]);
   return EXIT_SUCCESS;
}


Nur dass ich meine einzelnen strings mit den einzeln eingelesenen Zeilen einer datei befüllen will.

Code: C
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <windows.h>
#define P 100




/***************************************************************************************************************/
/* DynamicText - Ein Programm, welches die Zeilen einer Datei in den Speicher einliest. Die Zeilen werden als  */
/* String-Array gespeichert und das String-Array dynamisch verwaltet. Verwendet werden dazu die Funktionen     */
/* malloc() und realloc(). Dadurch ist es möglich eine Datei in den Speicher zu laden, ohne vorher zu wissen   */
/* wie groß diese Datei ist.                                                                                   */
/* Autor:                                                    */
/* Datum: 2016-03-05                                                                                           */
/***************************************************************************************************************/



                                               /****************************************************************/
                                               /* Main Funktion                                                */
                                               /****************************************************************/
int main (int argc, char *argv[])
{

    // Speichere alte Farben der Konsole
    HANDLE h = GetStdHandle ( STD_OUTPUT_HANDLE );
    WORD wOldColorAttrs;
    CONSOLE_SCREEN_BUFFER_INFO csbiInfo;

    GetConsoleScreenBufferInfo(h, &csbiInfo);
    wOldColorAttrs = csbiInfo.wAttributes;




                                                                                        /*************************/
                                                                                        /* Variablendeklaration  */
                                                                                        /*************************/

    // Einlesestring
    char inputstring[P];

    // String, welcher die ganze Eingabe speichert
    char **bigstring;

    // Größe des Strings für Speicherallozierung
    int size=100;

    //Filepointer
    FILE *fp;

    // Zählervariable für Zeilen
    int k=0;



                                                                                    /*************************/
                                                                                    /* Ausgabe Programminfo  */
                                                                                    /*************************/
    // Ausgabe in der Farbe Rot
    SetConsoleTextAttribute ( h, FOREGROUND_RED | FOREGROUND_INTENSITY );

    printf("-----------------------------------------------------------------------------\n");
    printf("| AnalyzeText - Ein Programm AnalyzeText, welches deine Datei zeichenweise  |");
    printf("\n| einliest. Das Programm sucht nach einem XML-Tag und gibt den Elementnamen |");
    printf("\n| und gibt den Inhalt auf die Standardausgabe aus.                          |");
    printf("\n| Version 1.0                                                               |");
    printf("\n| Autor:                        |");
    printf("\n| Datum: 2016-03-05                                                         |\n");
    printf("-----------------------------------------------------------------------------\n\n");

    // Ausgabe in Standardfarben
    SetConsoleTextAttribute ( h, wOldColorAttrs);


    // Bildschirmwechsel
    system("PAUSE");
    system("cls");


    // Filesttream öffnen im "read only" Modus
    fp=fopen("uebtext.txt", "r");

    // Wenn Speicher nicht alloziert werden könnte, dann Fehlermeldung und Fehlercode 1 Rückmelden
    if (!bigstring)
    {
        fprintf(stderr,"\nError");
        return -1;
    }

    // Speicher allozieren für String
    bigstring = (char *) calloc(size, sizeof(char));

    printf("\n-----------------------------------------------------------------------------\n");
    printf("|                       Lese Text aus Datei ein                             |\n");
    printf("-----------------------------------------------------------------------------\n\n");


    //Wenn fp 0 zurückliefert, also Datei unlesbar oder nicht auffindbar, dann Fehlermeldung
    if (fp == NULL)
    {
        fprintf(stderr,"Datei kann nicht zum Lesen geoeffnet werden\n");
    } else
    {
        int i=0;

        // solange Fileende nicht erreicht, auslesen und ausgabe
        while (fgets(inputstring,P,fp)!=NULL)
        {

            // Benötigter neuer Speicher
            size += strlen(inputstring);

            // Erweitere benötigten Speicher um die exakte Anzahl des eingelesenen Strings
            bigstring = (char *) realloc(bigstring, size*sizeof(int));

            // Wenn Speicher nicht alloziert werden könnte, dann Fehlermeldung und Fehlercode 1 Rückmelden
            if (!inputstring)
            {
                    fprintf(stderr,"\nError");
                    return -1;
            }
            // Zähler, wieviele Zeilen gelesen wurden
            k++;
            i++;
            bigstring[i] = inputstring;

            // Ausgabe
            printf("%s",bigstring[i]);

        }

    }
    printf("\nEs wurden %i Zeilen eingelesen\n",k);


    printf("\n bigstring[1] = %s", bigstring[1]);
    printf("\n bigstring[2] = %s", bigstring[2]);
    printf("\n bigstring[3] = %s", bigstring[3]);
    printf("\n bigstring[4] = %s", bigstring[4]);
    printf("\n bigstring[5] = %s", bigstring[5]);
    printf("\n bigstring[6] = %s", bigstring[6]);
    printf("\n bigstring[7] = %s", bigstring[7]);

    // Filestream schließen
    fclose(fp);

    // Speicher freigeben
    free(inputstring);




        printf("\n\n-----------------------------------------------------------------------------\n");
        printf("|                                  ENDE                                     |\n");
        printf("-----------------------------------------------------------------------------\n\n");


                                                                                     /*************************/
                                                                                     /* Programmende          */
                                                                                     /*************************/

    system("PAUSE");


    return 0;
}


Ich checks nicht, warum ich nicht einfach die einzelnen zeilen abspeichern kann in meiner stringtabelle.

Code: C
bigstring[i] = inputstring;

// Ausgabe
printf("%s", bigstring[i]);

Ziel ist, dass ich über bigstring[1], bigstring[2], bigstring[3], ..... einfach auf meine einzelnen eingelesenen Zeilen hinzugreifen kann.

tia! :(
Bearbeitet von charmin am 05.03.2016, 17:33

PuhBär

Schau ned so genau
Avatar
Registered: Sep 2002
Location: .
Posts: 1201
InputString hat ja immer die gleiche Adresse. Du müsstest für jede eingelesene Zeile Memory allozieren und dann den Pointer in das Array schreiben.

Oder du kopierst direkt dir Adresse aus strdup von InputString.
Bearbeitet von PuhBär am 05.03.2016, 17:46

charmin

Super Moderator
Muper Soderator
Avatar
Registered: Dec 2002
Location: aut_sbg
Posts: 13979
ja stimmt, inputstring hat immer dieselbe Adresse und die Größe P.

Für jede Zeile Memory allozieren will ich ja, aber im bigstring, nicht im inputstring.

will quasi bigstring[1] mit dem aktuellen zeile im inputstring befüllen.
Eine Runde weiter hat inputstring bereits den inhalt der nächsten Zeile statt der Ersten Zeile und die will ich dann in bigstring[2] reinkopieren.

ich will später eben die eingelesenen Zeilen einzeln aufrufen können mit bigstring[1...n]

PuhBär

Schau ned so genau
Avatar
Registered: Sep 2002
Location: .
Posts: 1201
Deshalb musst du den Speicher ja auch kopieren, den du einliest, und nicht immer in InputString liegenlassen bzw. beim nächsten Mal überschreiben.

Am Ende deines Programmes zeigen alle bigstring[i] auf den gleichen Speicher; deshalb siehst du immer nur die zuletzt eingelesene Zeile.

Mit
Code: C
bigstring[i] = inputstring
kopierst du nichts; damit weist du nur die Adresse von inputstring einem Eintrag in deinem Array zu. Versuch mal
Code: C
bigstring[i] = strdup(inputstring)
Und du musst dann am Schluss noch einmal durch bigstring iterieren und
Code: C
free(bigstring[i])
aufrufen, sonst leakst du Speicher.
Bearbeitet von PuhBär am 05.03.2016, 18:09

charmin

Super Moderator
Muper Soderator
Avatar
Registered: Dec 2002
Location: aut_sbg
Posts: 13979
alles klar, probier ich dann gleich aus.

danke schonmal ;)


edit: wow, thx :D haut jetzt hin. auf sowas wär ich nie gekommen, bzw erst nach zig stunden. hab an völlig falscher stelle gesucht jetzt und habs einfach nicht hingebracht.

danke!
Bearbeitet von charmin am 05.03.2016, 18:25

11Fire01

Here to stay
Registered: Dec 2002
Location: austria
Posts: 2417
da wünsche ich dir bei größeren programmen viel spaß :D

that

Moderator
Hoffnungsloser Optimist
Avatar
Registered: Mar 2000
Location: MeidLing
Posts: 11326
Zitat von charmin
Zitat von Bogus
btw :scnr: i'd vote for sanders. y? take a look

click to enlarge

Wieso "P"? Waren die sprechenden Namen schon aus? :p

Code: C
    // String, welcher die ganze Eingabe speichert
    char **bigstring;

Das ist kein String, es ist ein Stringarray.

Code: C
    // Größe des Strings für Speicherallozierung
    int size=100;

Schon wieder 100?

Code: C
    // Wenn Speicher nicht alloziert werden könnte, dann Fehlermeldung und Fehlercode 1 Rückmelden
    if (!bigstring)
    {
        fprintf(stderr,"\nError");
        return -1;
    }

Abgesehen davon, dass dein Returnwert nicht mit dem Kommentar zusammenpasst, ist bigstring an dieser Stelle uninitialisiert.

Code: C
    // Speicher allozieren für String
    bigstring = (char *) calloc(size, sizeof(char));

Du musst dich entscheiden, ob bigstring ein String oder ein Stringarray sein soll. sizeof(char) ist konstant 1 - willst du hier Speicher für einen String mit 100 Zeichen oder Platz für 25 oder 12,5 Stringpointer anlegen?

Code: C
        int i=0;

Was ist der Unterschied zwischen i und k?

Code: C
            // Benötigter neuer Speicher
            size += strlen(inputstring);

            // Erweitere benötigten Speicher um die exakte Anzahl des eingelesenen Strings
            bigstring = (char *) realloc(bigstring, size*sizeof(int));

Siehe oben - du musst dich entscheiden, ob du Platz für Stringpointer oder für die Inhalte anlegen willst. Wenn du die eingelesenen Strings mit strdup ins Array kopierst, brauchst du k * sizeof(char*) Bytes Speicher für die Pointer.

Code: C
            // Wenn Speicher nicht alloziert werden könnte, dann Fehlermeldung und Fehlercode 1 Rückmelden
            if (!inputstring)
            {
                    fprintf(stderr,"\nError");
                    return -1;
            }

inputstring ist ein Array, das kann nicht NULL sein.

Code: C
    // Speicher freigeben
    free(inputstring);

inputstring ist ein Array, das kannst du nicht mit free freigeben. Stattdessen willst du alle eingelesenen Strings in einer Schleife freigeben und dann das Array.
Bearbeitet von that am 05.03.2016, 20:53

charmin

Super Moderator
Muper Soderator
Avatar
Registered: Dec 2002
Location: aut_sbg
Posts: 13979
danke, dass du dir Zeit genommen hast!
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz