Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem Čtení řetězců v Céčku

Ahoj, jak mohu v céčku efektivně načítat řetězce znaků?

Mám na mysli dynamicky alokované místo tak, aby to šetřilo paměť. Například mám místo pouze pro 10 znakový řetězec, ale kdybych náhodou chtěl načítat řetězec s >10 znaky, tak se místo třeba zdvojnásobí a když ani to nebude vyhovovat, tak se znovu zdvojnásobí.

dám příklad - chci uložit do 3 proměnných 3 slova ze vstupu.txt (jejich velikost dopředu neznám)

vstup.txt
{

auto
dinosaurusREX
pcporadnajenejlepsiporadna

}

-začínám s omezením na 10 znaků

načítám "auto" do proměnné A =>okej

načítám "dinosaurusREX" do proměnné B=>musí se zdvojnásobit paměť, pak se uloží

načítám "pcporadnajenejlepsiporadna" do proměnné C=>musí se dvakrát zdvojnásobit paměť(uvažuji, že omezení na 10 znaků je nějaká neměnná konstanta, šablona)

díky moc :-)

Předmět Autor Datum
Môžeš použiť funkciu getline, ktorá za teba spraví alloc a prípadne realloc.
moose 03.03.2019 22:23
moose
Mohl bys mi prosím Tě napsat ten kus kódu, já jsem v céčku nováček a z těch pointerů a tak jsem zatí…
Holy99 03.03.2019 22:25
Holy99
V uvedenom odkaze je príklad. S čím konkrétne potrebuješ pomôcť? Ďalší príklad je tu: https://stacko…
moose 03.03.2019 22:28
moose
Moc se nevím rady s tím, jak to použít pro více proměnných char.
Holy99 03.03.2019 22:46
Holy99
Ak potrebuješ viacero premenných s reťazcom, tak si musíš skopírovať načítanú hodnotu do nejakej vyh…
moose 03.03.2019 22:50
moose
No, chtěl bych to udělat tak, jako jsem to popsal v dotazu, čili mám textový soubor se slovy, každé…
Holy99 03.03.2019 23:12
Holy99
No však prebehneš celý súbor riadok po riadku. Počas toho každý riadok načitaš do dočasnej pamäte ce…
moose 03.03.2019 23:18
moose
Intuitivně chápu, jak to myslíš, ale problém je, že to s mým momentálním skillem prostě nenapíšu; pr…
Holy99 03.03.2019 23:24
Holy99
Lol, to vyzerá, že si si neprišiel po radu ako to napísať, ale po riešenie. Tá možnosť 2 by mohla v… poslední
moose 04.03.2019 00:51
moose

No, chtěl bych to udělat tak, jako jsem to popsal v dotazu, čili mám textový soubor se slovy, každé slovo je na jedné řádce. A já bych si ty 3 slova chtěl odděleně uložit a poté s nimi pracovat. Akorát u nich předem neznám délku, a tak bych chtěl dynamicky alokovat pamět charu pro každé z nich, aby se neplýtvalo s pamětí. V céčku jsem fakt úplně lajk, tvojich rad si velice cením, ale i tak jsem mimo.

No však prebehneš celý súbor riadok po riadku. Počas toho každý riadok načitaš do dočasnej pamäte cez getline. Keď už ho máš v tej dočasnej premennej, tak poznáš jeho dĺžku, takže si alokuješ miesto pre nový reťazec a tam si ho prekopíruješ. Výhodou je, že si do pamäte odložíš len to, čo potrebuješ.

Druhá možnosť je, že načítaš celý súbor do pamäte. To potom prebehneš a uložíš si smerníky na začiatky riadkov. Konce riadkov nahradíš nulovým znakom. V takomto prípade bude výhodou, že budeš robiť len jednu alokáciu. V prípade, že potrebuješ mať všetky riadky aj tak v pamäti, tak táto druhá možnosť je asi lepšia.

Lol, to vyzerá, že si si neprišiel po radu ako to napísať, ale po riešenie.

Tá možnosť 2 by mohla vyzerať takto:

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

char* get_line(char** start) {
	char* result = *start;
	char* c = *start;
	if (!*c) {
		return NULL;
	}
	while (*c) {
		switch (*c) {
			case '\r':
				*c++ = '\0';
				if (*c == '\n') {
					++c;
				}
				*start = c;
				return result;

			case '\n':
				*c++ = '\0';
				*start = c;
				return result;

			default:
				++c;
				break;
		}
	}
	return result;
}

int main() {
	FILE* fp = fopen("vstup.txt", "rb");
	if (!fp) {
		perror("Failed to open file 'vstup.txt'");
		return EXIT_FAILURE;
	}

	if (fseek(fp, 0, SEEK_END) != 0) {
		perror("Failed to seek the end of file");
		return EXIT_FAILURE;
	}

	long fsize = ftell(fp);
	if (fsize == -1L) {
		perror("Failed to get file position");
		return EXIT_FAILURE;
	}

	rewind(fp);

	char *file_content = malloc(fsize + 1);
	if (file_content == NULL) {
		perror("Failed to allocate memory for file content");
		return EXIT_FAILURE;
	}

	if (fread(file_content, 1, fsize, fp) != fsize) {
		perror("Failed to read file content");
		return EXIT_FAILURE;
	}

	fclose(fp);

	file_content[fsize] = 0;

	char *start = file_content;
	char *a = get_line(&start);
	char *b = get_line(&start);
	char *c = get_line(&start);
	char *d = get_line(&start);

	printf("a = %s\n", a);
	printf("b = %s\n", b);
	printf("c = %s\n", c);
	printf("d = %s\n", d);

	free(file_content);
}

Výstup pre tvoj vstupný súbor potom vyzerá takto:

a = auto
b = dinosaurusREX
c = pcporadnajenejlepsiporadna
d = (null)

Čítam binárne, lebo chcem mať v pamäti presne to, čo je v súbore. Mohol by si to čítať aj textovo, ale to vyžaduje pár úprav (get_line bude jednoduchší, ale fread bude trochu zložitejší, pretože nerozlišuje medzi chybou a koncom súboru - viď dokumentácia).

Zpět do poradny Odpovědět na původní otázku Nahoru