Pole stringov C

Programovacie jazyky, rady, poradňa...
dunno
Star
Star
Príspevky: 622
Registrovaný: 17 júl 2014, 11:04
Bydlisko: KE

Pole stringov C

Príspevok od používateľa dunno »

Preco toto nefunguje?

Kód: Vybrať všetko

char *slova[50];

FILE * fp;
       		char * line = NULL;
       		size_t len = 0;
       		ssize_t read;

       		fp = fopen("mena.txt", "r");
       		if (fp == NULL)
           	exit(EXIT_FAILURE);
		int pocitadlo;
		pocitadlo=0;
       		while ((read = getline(&line, &len, fp)) != -1) {
           			printf("Retrieved line of length %zu :\n", read);
           			printf("%s", line);
				slova[pocitadlo] = line;
				pocitadlo++;
       		}

       		fclose(fp);
       		if (line)
           		free(line);
		
		}
Pole je pri vypise prazdne...
Pritom ten printf vypise nacitany riadok.
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8217
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: Pole stringov C

Príspevok od používateľa harrison314 »

Chyba je v tom, ze sa snzis pripradit daco co nejde,
ty musis alkovat dvojrozemne pole a tringy donho kopirovat.

Kód: Vybrať všetko

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

int main()
{
             char slova[50][50];
             char * line = NULL;
             size_t len = 0;
             ssize_t read;

            FILE * fp = fopen("mena.txt", "r");
             if (fp == NULL)
            {
              exit(EXIT_FAILURE);
             }
      int pocitadlo = 0;

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

             fclose(fp);
             return 0;
      }
}

//autoeditácia príspevku (11 Nov 2014, 17:20)
tu je zdroj http://www.cplusplus.com/reference/cstring/strcpy/
dunno
Star
Star
Príspevky: 622
Registrovaný: 17 júl 2014, 11:04
Bydlisko: KE

Re: Pole stringov C

Príspevok od používateľa dunno »

Aha, a neda sa to nejak s tym char *slova[50]; ?

Lebo ak priradujem takto:
slova[0] = "slovo";

Tak to funguje. Ale ked to uz robim v tom cykle ako: slova[pocitadlo] = line; tak uz to nejde, pole je prazdne.
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8217
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: Pole stringov C

Príspevok od používateľa harrison314 »

ked spravis slova[0] = "slovo"; tak sa do pola na indexe 0 priradi pointer na zaciatok retazca "slovo", ale ten je nacitany v pameti stale.
len teraz sa pozeram ze to mas cele cudne, to getline sa mi nejak nepaci, pouzi radcej http://www.cplusplus.com/reference/cstdio/fgets/

Kód: Vybrať všetko

 char slova[50][50];
 FILE* f = fopen("mena.txt", "r");
 int index = 0;
 while(fgets(slova[i],50,f)!=NULL)
{
   printf("Nacital som %s\n",slova[i]);
   i++;
}
fclose(f);
dunno
Star
Star
Príspevky: 622
Registrovaný: 17 júl 2014, 11:04
Bydlisko: KE

Re: Pole stringov C

Príspevok od používateľa dunno »

problem je, ze mal som to predtym takto:

Kód: Vybrať všetko

const char  *slova[20] = {
	"slovo1",
	"slovo2",
	atd. dalsie slova
	NULL
};
a snazim sa toto staticky definovane pole spravit ako nacitanie zo suboru, lenze ked to spravim tak ako radite, nezbehne mi zvysok programu dobre, kedze neviem jak by som tam napchal na koniec hodnotu NULL.
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8217
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: Pole stringov C

Príspevok od používateľa harrison314 »

V taom pripade, si musi dynamicky alokovat miesto pre jednotlive stringy
dunno
Star
Star
Príspevky: 622
Registrovaný: 17 júl 2014, 11:04
Bydlisko: KE

Re: Pole stringov C

Príspevok od používateľa dunno »

hm, vies mi s tym helpnut ?
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8217
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: Pole stringov C

Príspevok od používateľa harrison314 »

viem, ale az zajtra
n0b0dy
Light Expert
Light Expert
Príspevky: 45
Registrovaný: 16 nov 2006, 9:09
Bydlisko: Považská Bystrica
Kontaktovať používateľa:

Re: Pole stringov C

Príspevok od používateľa n0b0dy »

Pokial poznas pocet slov a ich maximalnu dlzku este pred prekladom tak ti staci definovat pole tak ako ti to napisal harrison314: "char slova[50][50];".
To znamena ze by si mohol mat 50 slov s dlzkou maximalne 49 znakov (nezabudnut na ukoncovaci znak '\0') potom v cykle uz len iterovat a kopirovat stringy ako "strcpy(slova[pocitadlo], line);"

Ak nepoznas velkost ani dlzku tak potom potrebujes dynamicky alokovat pamat pre to pole. POuzivaju sa na to funkcie malloc alebo calloc, popripade pre zvacsenie vyhradenej pamate sa pouziva realloc.

Priklad:

Kód: Vybrať všetko

char **pole;

pole = (char **) calloc(pocet_slov, sizeof(char *));
tymto si si ako keby vytvoril pamat pre "riadky", to znamena ze teraz mozes pristupovat k jednotlivym riadkom ako pole[cislo_riadku]. Ked teraz pristupis na nejaku hodnotu napriklad pole[1] tak je tam hodnota NULL cize tam nic nie je

mame teda vytvorene miesto pre urcity pocet slov. aby si mohol na toto miesto nakopirovat nejaky string, musis naalokovat este aj miesto pre ten konkretny retazec. Na to budes potrebovat vediet dlzku toho stringu ktoru ti vrati funkcia getline (vrati ti pocet znakov v riadku ale asi mas kazde meno na jeden riadok) + budes potrebovat naalokovat o jeden znak viacej prave kvoli ukoncovaciemu znaku.

Kód: Vybrať všetko

pole[cislo_riadku] = (char *) calloc(dlzka_riadku + 1, sizeof(char));
takze teraz mas naalokovane miesto pre jeden konkretny string o dlzke dlzka_riadku + 1 na pozicii cislo_riadku

pre kopirovanie stringov pouzijes funkciu strcpy(ciel, zdroj);

strcpy(pole[cislo_riadku], zdroj_odkial_kopirujes);


Tvoje zadanie:

Kód: Vybrať všetko

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

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

            FILE * fp = fopen("mena.txt", "r");
             if (fp == NULL)
            {
              exit(EXIT_FAILURE);
             }
      int pocitadlo = 0;

             while ((read = getline(&line, &len, fp)) != -1) {
                    pocitadlo++; //inkrementujeme pocitadlo podla ktoreho budeme realokovat pamat
                    slova = (char **) realloc(slova, pocitadlo * sizeof(char *));  
                    slova[pocitadlo-1] = (char *) calloc(read + 1, sizeof(char));
                    printf("Retrieved line of length %zu :\n", read);
                    printf("%s", line);
                    strcpy(slova[pocitadlo - 1], line);
             }

             fclose(fp);
             return 0;
      }
}
Samozrejme pri alokacii pamate treba este osetrit, ci nam alkoacia prebehla uspesne... premennu kontrolujeme na NULL ak nam pri alokacii calloc realloc alebo malloc vrati NULL, alokacia sa nepodarila.
Uvolnovanie pamate funkciou free sa robi opacne, najskor uvolnime string a potom "riadok" na ktorom ten string bol.
Kod som netestoval ale mal by ist.

S pozdravom
Peter
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8217
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: Pole stringov C

Príspevok od používateľa harrison314 »

Ten program ide, ale ma dost chyb.
napriklad, nic sa nedealokuje, co je vazna chyba.
A realokovat pole po kazdom nacitani riadku nie je dobry napad, skus to radcej takto

Kód: Vybrať všetko

int capcity = 50;
char **words = (char**) malloc(capcity*sizeof(char));
char buff[100];
FILE* f = fopen("mena.txt", "r");
int index = 0;
while(fgets(buff,50,f)!=NULL)
{
   printf("Nacital som %s\n",buff);
   char* tmp = (char*) malloc((strlen(buff)+1)*sizeof(char));
   strcpy(tmp,buff);
   words[index] = tmp;
   index++;
if(index>=capcity)
{
  capcity = capcity*2;
  void* ptr = realloc(words,capcity);
  words = (char**) ptr;
}
}
words[index] = NULL;
fclose(f);


//dealokacia
index = 0;
while(words[index]!=NULL)
{
  free(words[index]);
  index++;
}
free(words);
dunno
Star
Star
Príspevky: 622
Registrovaný: 17 júl 2014, 11:04
Bydlisko: KE

Re: Pole stringov C

Príspevok od používateľa dunno »

dakujem ;)
n0b0dy
Light Expert
Light Expert
Príspevky: 45
Registrovaný: 16 nov 2006, 9:09
Bydlisko: Považská Bystrica
Kontaktovať používateľa:

Re: Pole stringov C

Príspevok od používateľa n0b0dy »

Hej, samozrejme realokacia pola pri kazdej iteracii je hlupost, ale cielom mojho prispevku bolo napisat priklad ako to asi zhruba vyzera a co sa tam deje. Optimalne by sa velkost mala zvysovat pri dosiahnuti kapacity o dvojnasobok. Aspon tak nas to teda ucili :).

A co sa tyka dealokacie zdrojov, pri ukonceni sa OS uz postara o dealokovanie pamate ktora bola vyhradena pre ten proces. Samozrejme spravny programator by sa o to mal postarat hlavne ked to nie je nejaky jednoduchy program :)

S pozdravom

Peter
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8217
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: Pole stringov C

Príspevok od používateľa harrison314 »

n0b0dy napísal: A co sa tyka dealokacie zdrojov, pri ukonceni sa OS uz postara o dealokovanie pamate ktora bola vyhradena pre ten proces. Samozrejme spravny programator by sa o to mal postarat hlavne ked to nie je nejaky jednoduchy program :)
Nie kazdy OS ti to zarucuje, takze je dobre to uvolnovat.
Napísať odpoveď