Pobieranie wiersza z pliku i alokowanie dla niego tablicy dynamicznej

0

**Dodam tu fragment polecenia z którym mam problem: **

program odczytuje plik i zapisuje go w pamięci, traktując każdy linijkę jako napis (Uwaga: dla uproszczenia programu można założyć, że znamy ograniczenie na długość linijki (powiedzmy 1023 znaki) i znamy ograniczenie na liczbę linii (powiedzmy 2048), ale spodziewamy się, że długości poszczególnych linijek mogą się bardzo różnić, więc pamięć dla poszczególnych linijek alokujemy dynamicznie w czasie czytania, zapisując w tablicy adresy kolejnych napisów)

Trochę nie bardzo rozumiem jak to napisać, mam fragment kodu, który pobiera jedną linijkę, ale nie wiem jak go teraz przerobić aby, pobierał linijki tekstu i tworzył dla nich kolejne tablice, których wskaźniki wsadzałby do kolejnej tablicy

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAXLINE 1023
#define ROW 32

int main()
{
    FILE *fp;
    char *array;
    size_t csize = ROW;
    size_t cpos = 0;
    int ch;
    fp = fopen("plik.txt", "r");
    
    array = malloc(ROW);
    
    while((ch = fgetc(fp))!='\n'&& ch!='\r')
    {
        array[cpos++] = ch;
         if(cpos == csize)
            {
                csize += ROW;
                array = realloc(array, csize);
            }
           
    }
           array[cpos] = 0;
    
   
    fclose(fp);
    free(array);
    return 0;
}
2

Wydaje mi się, że funkcja getline, robi wszystko co Chcesz:

int main(void)
{
    FILE * fp;
    char * line = NULL;
    size_t len = 0;
    ssize_t read;

    fp = fopen("test.txt", "r");
    if (fp == NULL)
        exit(EXIT_FAILURE);

    while ((read = getline(&line, &len, fp)) != -1) {
        printf("Retrieved line of length %zu:\n", read);
        printf("%s", line);
    }

    fclose(fp);
    if (line)
        free(line);
    exit(EXIT_SUCCESS);
}

Źródło: https://stackoverflow.com/questions/3501338/c-read-file-line-by-line#3501681

1

1 Możesz zadeklarować pamięć na wszystkie linie (ma być max 2048) oraz na linię tymczasową (pamiętaj aby potem zwolnić tą pamięć)

rows = (char **)malloc(sizeof(char *) * ROWS);
line_tmp = (char *)malloc(MAXLINE);

2 Następnie fgetsem odczytujesz linie z pliku w pętli, jak fgets zwróci NULL to kończysz czytanie:

fgets(line_tmp,MAXLINE,file)

3 Potem alokujesz pamięć na linię (masz w zadaniu) i dodajesz do rowsów (również w pętli):

rows[number_of_line] = (char *)malloc(line_size); // line size możesz pobrać funkcją strlen
//tutaj kopiowanie z line_tmp do rows[number_of_line]

I to tyle, nie zapomnij wyczyścić pamięci po wszystkim.

0

@malencki:

O coś takiego chodzi?

   FILE * fp;
        char ** rows;
        char * line_tmp;
        int number_of_line,i;
        long  row_size;
       
        number_of_line = 0;
        fp = fopen("plik.txt", "r");
        if (fp == NULL)
            exit(EXIT_FAILURE);
    
    
    rows = (char **)malloc(sizeof(char *) * ROWS);
    line_tmp = (char *)malloc(MAXLINE);
   
    while(fgets(line_tmp, MAXLINE, fp)!=NULL)
    {
       
        row_size = strlen(line_tmp);
        
        rows[number_of_line] = (char *)malloc(row_size);
        
        for(i=0; i<row_size; i++)
        {
            rows[number_of_line][i] = line_tmp[i];
            
        }
        number_of_line++;
    }
    ```
1

size_t strlen(const char *s);
Funkcja strlen() oblicza długość łańcucha wskazanego przez s, nie licząc kończącego znaku null ('\0')

Oznacza to że powinieneś do długości znaków dodać jeszcze jeden kończący.
Może wiesz lub nie, stringi w C kończą się znakiem '\0'. Strlen podaje Tobie wielkość bez tego znaku.

Do kopiowania pamięci możesz użyć memcpy lub strncpy, ale tutaj szybsze będzie memcpy :

#include <string.h>
memcpy(rows[number_of_line],line_tmp,row_size);

W pętli gdzie odczytujesz należałoby dodatkowo sprawdzać czy number_of_line nie jest większy od ROWS :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1