Skąd te teksty są wczytywane? Jeśli z pliku to możesz sobie zmapować do pamięci (mmap na Linuksie, CreateFileMapping na Windowsie). Wtedy wystarczy przepisać wskaźniki do kolejnych linijek. Przed każdą linijką pliku możesz sobie dopisać jej długość i wtedy nawet nie będziesz musiał na piechotę liczyć ich długości.
Jeśli wczytujesz ze strumienia to chyba jest to tylko o tyle trudniejsze, że nie znasz z góry docelowej długości wszystkich tekstów, chyba, że zostaną podane w nagłówku. Dalej już analogicznie. W każdym razie nie ma potrzeby nic przepisywać.
Program wczytujący ze standardowego wejścia z nagłówkiem zawierającym ilość linii i całkowity rozmiar danych mógłby wyglądać tak:
Kopiuj
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char** argv) {
size_t amount,total;
fread(&amount, sizeof(size_t), 1, stdin);
fread(&total, sizeof(size_t), 1, stdin);
char* string_buff = malloc(total);
fread(string_buff, 1, total, stdin);
char **strings = malloc(amount * sizeof(char*));
char *cur = string_buff;
for(size_t i = 0; i < amount; i++) {
strings[i] = cur + sizeof(size_t);
size_t len = *((size_t*)cur);
cur += len + sizeof(size_t);
}
printf("amount: %lu\ntotal: %lu\n", amount, total);
for(size_t i = 0; i < amount; i++) {
printf("%s\n", strings[i]);
}
free(strings);
free(string_buff);
}
Natomiast program generujący dane testowe tak:
Kopiuj
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
FILE* output = fopen("out.dat", "w");
size_t amount = 0;
size_t total = 0;
fwrite(&amount, sizeof(size_t), 1, output);
fwrite(&total, sizeof(size_t), 1, output);
char buff[2048];
while(fgets(buff, 2048, stdin)) {
size_t len = strlen(buff);
buff[len-1] = 0;
fwrite(&len, sizeof(size_t), 1, output);
fwrite(buff, 1, len, output);
total += len + sizeof(size_t);
amount++;
}
fseek(output, 0, SEEK_SET);
fwrite(&amount, sizeof(size_t), 1, output);
fwrite(&total, sizeof(size_t), 1, output);
fclose(output);
}
Dla łatwości pisania i czytania, pominąłem obsługę błędów. Tak samo pominąłem przypadek w którym mamy linię dłuższą niż 2048. Poza tym, program nie zakłada (a jeśli dane miałyby chodzić po sieci, należałoby), że nadawca ma inną architekturę niż odbiorca (inne długości typów, inną kolejność bajtów).
W przypadku braku nagłówka z długością danych, należałoby by używać realloc, żeby progresywnie powiększać bufor.
Jako ciekawostkę dodam, że w standardzie C99 można deklarować tablice o zmiennym rozmiarze, więc deklaracja strings w pierwszym kodzie mogłaby wyglądać tak:
Kopiuj
char *strings[amount];
Wówczas należy pominąć free(strings). Na gcc działa.