Array von Pointern übergeben...



  • Mein Problem ist folgendes. Ich habe eine Funktion die aus einer Textdatei liest, in einen Puffer speichert, und der Puffer inhalt wird dann in ein Array von Zeigern übergibt:

    void TextArray(char* paZeile, char dateiname[])
    {
        int n=0;
        char puffer[80];
        FILE *datei_ptr;
    
    if((datei_ptr = fopen(dateiname,"r")) != NULL)
        {
        while(!feof(datei_ptr) && n<5)
        {
        fgets(puffer,Groesse,datei_ptr);
        (*(paZeile+n)) = puffer;
        printf("%s\n",paZeile[n]);
        n++;
        }
    flcose(datei_ptr);
    }
    else
        printf("Fehler");
    }
    

    Bis dahin alles ok, auch der Inhalt scheint übernommen zu sein in das Array von Zeigern, da ich das gleich mit printf teste in Zeile 12.

    So sieht der Aufruf in der main aus.

    int main (void()
    {
        char dateiname[80] = "text.txt";					
        char* paZeile[MAX];
        TextArray(paZeile, dateiname);
    
        int a=0;
        for(a = 0; a < 5; a++)
            printf("%s\n", paZeile[a]
    
    return EXIT_SUCCES;
    }
    

    Um zu testen ob alles in mein Array von Zeigern übernommen wurde, mache ich auch in der main zu sicherheit auch den Test. doch hier spuckt er nur noch Müll aus, bzw. irgendeinen Inhalt. Was mach ich falsch? Liegt es and der Parameterübergaben, oder wie ich die Strings in das Array kopiere?

    Mfg 😉

    Zoro



  • Das kann / sollte / wird Dir schon in
    void TextArray(char* paZeile, char dateiname[]) um die Ohren fliegen.

    Du hast ein zwar ein Array aus Zeigern auf Char in der Main, aber diese Zeiger zeigen eben nur auf EIN char , bzw. sind nur ein Zeiger auf Char. Da kannst so keinen String drin speichern. Du brauchst für jeden Zeiger in dem Array Malloc um Speicher für die Zeichenkette zu reservieren.



  • kalio20 schrieb:

    Was mach ich falsch? Liegt es and der Parameterübergaben, oder wie ich die Strings in das Array kopiere?

    Beides ist falsch.
    Du hast Fehler beim Abschreiben des Code gemacht, das compiliert nie.
    Die Definition des Zeigerarrays

    char* paZeile[MAX];
    

    ist korrekt, es spricht nichts dagegen, das identisch als Parameter zu deklarieren:

    void textArray(char* paZeile[MAX], const char *dateiname)
    

    - MAX nennt man keine globalen Konstanten
    - feof nach fopen verwendet man nicht
    - sinnvoll ist die Rückgabe der Anzahl der gültigen Zeiger im Array, damit in main kein Zugriff auf evtl. undefinierte Speicherbereiche erfolgt



  • Ändere mal das %s beim printf in main in %p um.
    Damit gibst du den Wert vom Pointer aus.

    Oder

    printf("%p: <%s>\n", paZeile[n], paZeile[n]);
    

    Was siehst du?



  • Ich bin aber leider der Weltschlechteste "Erklärer", aber es sind hier echte Profis unterwegs.
    Meines Erachtens ist auch die Übergabe an deine Funktion falsch. Doppelpointer kämen da ins Spiel.



  • Erster Kompilierversuch:

    xxx.c: In Funktion »TextArray«:
    xxx.c:5:5: Fehler: unbekannter Typname: »FILE«
    
    #include <stdio.h>
    

    hinzugefügt.

    Zweiter Kompilierversuch:

    xxx.c: In Funktion »TextArray«:
    xxx.c:13:18: Fehler: »Groesse« nicht deklariert (erste Benutzung in dieser Funktion)
    

    Erst Mal die komplette Einrückung korrigiert. Groesse wird als Parameter für einen fgets -Call verwendet.

    #define MY_BUFFER_LINE (80)
    #define MY_BUFFER_MAX (1000)
    

    Als Konstanten hinzugefügt.

    Dritter Kompilierversuch:

    xxx.c: In Funktion »TextArray«:
    xxx.c:17:19: Warnung: Zuweisung erzeugt Ganzzahl von Zeiger ohne Typkonvertierung [standardmäßig aktiviert]
    

    In der Zeile machst du:

    (*(paZeile+n)) = puffer;
    

    Damit weißt du das erste

    Egal, wird ignoriert. Nächste Warnung:

    xxx.c:18:4: Warnung: Format »%s« erwartet Argumenttyp »char *«, aber Argument 2 hat Typ »int« [-Wformat]
    

    Wegen dieser Zeile:

    printf("%s\n",paZeile[n]);
    

    paZeile[n] ist ein char . Kein char* . Kein String. Sondern nur ein Zeichen.

    Egal, wird auch ignoriert. jetzt die Fehlermeldung:

    xxx.c:28:1: Fehler: expected »;«, »,« or »)« before »{« token
    
    int main(void()
    

    Interessanter Funktionsheader. 🙂

    Vierter Kompilierversuch:

    xxx.c:37:2: Fehler: expected »)« before »return«
    xxx.c:38:1: Fehler: expected »;« before »}« token
    
    printf("%s\n", paZeile[a] /*Fehlende abschließende Klammer, fehlendes Semikolon.*/
    

    Fünfter Kompilierungsversuch:

    xxx.c:37:9: Fehler: »EXIT_SUCCES« nicht deklariert (erste Benutzung in dieser Funktion)
    xxx.c:37:9: Anmerkung: jeder nicht deklarierte Bezeichner wird nur einmal für jede Funktion, in der er vorkommt, gemeldet
    
    return EXIT_SUCCES;
    

    Durch EXIT_SUCCESS ersetzt, stdlib.h eingebunden.

    Sechster Kompilierungsversuch:

    /tmp/ccLbVux6.o: In function `TextArray':
    xxx.c:(.text+0xa8): undefined reference to `flcose'
    collect2: Fehler: ld gab 1 als Ende-Status zurück
    

    Du meinst wohl eher fclose . 😉

    Siebter Kompilierungsversuch klappt dann.
    Programm stürzt ab:

    Nov 30 03:51:33 asgard kernel: [105596.317414] xxxx[6853]: segfault at 0 ip 00007f9ed9b900aa sp 00007fff01459b28 error 4 in libc-2.19.so[7f9ed9b08000+19d000]
    

    Yummy.

    Erst mal prüfen, gibt es einen Check, ob die Datei vorhanden ist? Ja, gibt es. Und dann machst du auch eine Fehlermeldung. Das Problem ist aber, dass die Ausgabe gepuffert wird, und die wird erst ausgegeben, wenn ein "\n" reinkommt. Also printf("Fehler") durch printf("Fehler\n") ersetzt.

    Achter Kompilierungsversuch:

    Fehler
    Speicherzugriffsfehler
    

    OK, meine Datei existiert nicht. Anstatt zu sagen "dann mach doch eine", will ich dich auf etwas aufmerksam machen:

    char* paZeile[MY_BUFFER_MAX];
    

    Damit reservierst du ein Array von MY_BUFFER_MAX Elementen vom Typ "Zeiger auf char ". Aber worauf zeigen diese? Ins Nirvana, um es höflich auszudrücken. Du reservierst ja nie Speicher für sie.

    #define MY_LINES_COUNT (5)
    
    /*...*/
    
    char paZeile[MY_LINES_COUNT*MY_BUFFER_LINE];
    memset(paZeile,0,sizeof(paZeile));
    TextArray(paZeile, dateiname);
    
    for(a=0;a<5;a++)
        printf("%d. Zeile: \"%s\"\n",a+1,&paZeile[a]);
    
    Fehler
    1. Zeile: ""
    2. Zeile: ""
    3. Zeile: ""
    4. Zeile: ""
    5. Zeile: ""
    

    Yeah, kein Segfault mehr. Jetzt können wir mal die Datei anlegen und nochmal testen:

    Erste Zeile
    Zweite Zeile
    Dritte Zeile
    Vierte Zeile
    Fünfte Zeile
    

    Programm rennt wieder in einen Segfault.

    Nov 30 04:05:15 asgard kernel: [106418.813974] xxxx[6909]: segfault at ffffffc0 ip 00007fb4ae4e96b0 sp 00007fff0d3cae00 error 4 in libc-2.19.so[7fb4ae49b000+19d000]
    

    Kurz in die TextArray geschaut ... hm, den Puffer brauchen wir nicht:

    while(!feof(datei_ptr) && n<5)
    {
        fgets(&paZeile[n*MY_BUFFER_LINE],MY_BUFFER_LINE,datei_ptr);
        printf("%s\n",&paZeile[n*MY_BUFFER_LINE]);
        n++;
    }
    fclose(datei_ptr);
    

    Zehnter Kompilierungsversuch funktioniert. Ausgabe:

    $ ./xxxx
    Erste Zeile
    
    Zweite Zeile
    
    Dritte Zeile
    
    Vierte Zeile
    
    Fünfte Zeile
    
    1. Zeile: "Erste Zeile
    "
    2. Zeile: "Zweite Zeile
    "
    3. Zeile: "Dritte Zeile
    "
    4. Zeile: "Vierte Zeile
    "
    5. Zeile: "Fünfte Zeile
    "
    

    Der finale code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
    
    #define MY_LINES_COUNT (5)
    #define MY_BUFFER_LINE (80)
    #define CONVERT_LINE_POS(x) ((x)*MY_BUFFER_LINE)
    
    void TextArray(char*paZeile,const char*dateiname)
    {
            size_t n=0;
            FILE*datei_ptr;
    
            if(!(datei_ptr = fopen(dateiname,"r")))
            {
                    printf("Fehler beim Öffnen der Datei: %s\n",dateiname);
                    return;
            }
            while(!feof(datei_ptr) && n<MY_LINES_COUNT)
            {
                    fgets(&paZeile[CONVERT_LINE_POS(n)],MY_BUFFER_LINE,datei_ptr);
                    printf("%s\n",&paZeile[CONVERT_LINE_POS(n)]);
                    n++;
            }
            fclose(datei_ptr);
    }
    
    int main(void)
    {
            size_t a;
            const char*dateiname="text.txt";                   
            char paZeile[MY_LINES_COUNT*MY_BUFFER_LINE];
    
            memset(paZeile,0,sizeof(paZeile));
            TextArray(paZeile,dateiname);
    
            for(a=0;a<MY_LINES_COUNT;a++)
                    printf("%lu. Zeile: \"%s\"\n",a+1,&paZeile[CONVERT_LINE_POS(a)]);
    
            return EXIT_SUCCESS;
    }
    

Log in to reply