| | |
| Stránka: 1 z 1
| [ Príspevkov: 26 ] | |
Autor | Správa |
---|
Registrovaný: 15.06.14 Prihlásený: 20.04.24 Príspevky: 17930 Témy: 142 Bydlisko: Bratislava |
zdravim, robim projekt v ccko do skoly a neviem si dat radu s pointerom na pole. mam textovy subor s velkym mnozstvom dat, potrebujem z neho dostat realne cisela (vyplaty) v kazdom siestom riadku (+-1000 cisel) a potrebujem ich zapisat do pola, ktore bude dostupne pre ostatne funkcie ukazka vstupneho suboru: Kód: 1 Ronald Carpenter 1 2176.01 07202016
2 Catherine Jenkins 1 1058.32 05192008 potrebujem cisla z tretieho riadku kazdeho jedneho "zaznamu" funkcia na zapis: Kód: void platarray(int *pocet, double **platy) { *pocet = 0; FILE *f; f = fopen("zamestnanci.txt", "r"); if ((f == NULL) { printf("Neotvoreny subor\n"); return; } char line[32]; double salary; char c; c = getc(f); while (c != EOF) { if (c != '\n') { ungetc(c, f); } fgets(line, 6, f); fgets(line, 33, f); fgets(line, 3, f); fgets(line, 10, f); sscanf(line, "%lf", &salary); //nacitanie platu do double fgets(line, 11, f); c = getc(f); *pocet = *pocet + 1; //zistenie poctu vsetkych ludi v subore } fclose(f); *platy = (double*)malloc(*pocet * sizeof(double)); //alokacia pamate pre pole s prvkami 0-'pocet' f = fopen("zamestnanci.txt", "r"); if ((f == NULL) { printf("Neotvoreny subor\n"); return; } int a; a = 0; c = getc(f); while (c != EOF) { if (c != '\n') { ungetc(c, f); } fgets(line, 6, f); fgets(line, 33, f); fgets(line, 3, f); fgets(line, 10, f); sscanf(line, "%lf", &salary); //nacitanie platu do double fgets(line, 11, f); c = getc(f); *platy[a] = salary; a = a + 1; } fclose(f);
int i; i = 0; for (i = 0; i < *pocet; i++) //vypis pola { printf("plat[%d] = %lf\n", i, *platy[i]); } } main: Kód: double *platy; platarray(&prikazV, &pocet, &*platy); //tu mi hadze error
error: argument of type "double *" is incompatible with parameter of type "double ** skusal som uz vselico, od obeda prezeram google a nic. vedel by mi s tymto niekto poradit? vopred vdaka
_________________ ITX >>> ATX |
|
Registrovaný: 22.08.11 Prihlásený: 14.12.23 Príspevky: 2361 Témy: 11 | Napísal magic: 06.11.2016 2:12 | |
|
Pozeral som ten kod len tak zbezne ale ked prerobis "&*platy" na "&platy", tak by to mohlo ist. "platy" je typu "double *" a tym & z neho spravis double**. "&*platy" by vlastne malo byt to iste ako platy lebo zoberes hodnotu na adrese platy, pomocou *, a hned na to si & vypytas jej adresu.
|
|
Registrovaný: 17.07.11 Prihlásený: 29.12.20 Príspevky: 1516 Témy: 3 | Napísal BX: 06.11.2016 9:22 | |
|
magic má asi pravdu, len to napíšem trochu zrozumeteľnejšie, lebo to magicove som mal aj ja problém pochopiť & je referencia * je dereferencia Keď napíšeš &*platy, tak & a * sa ti navzájom vyrušia (robíš referenciu dereferencie) a ostane ti len platy. Keďže samotná premenná platy je typu double*, tak potrebuješ adresu práve tejto premennej, čiže jednoducho &platy. Typovo to znamená &(double*) => adresa double* => vznikne typ double**
_________________ Na súkromné správy týkajúce sa problémov, ktoré sa riešia vo fóre, neodpovedám! |
|
Registrovaný: 22.08.11 Prihlásený: 14.12.23 Príspevky: 2361 Témy: 11 | Napísal magic: 06.11.2016 13:46 | |
|
Este mala pripomienka: "getc()" vracia "int" a ten sa nemusi zmestit do "char".
|
|
Registrovaný: 15.06.14 Prihlásený: 20.04.24 Príspevky: 17930 Témy: 142 Bydlisko: Bratislava | Napísal autor témy Miso122: 06.11.2016 15:47 | |
|
diki, uz nehadze errory ale po spusteni kompilacie a nacitani prveho prvku do pola prestane reagovat. pri tomto riadku: Kód: *platy[a]=salary; chybova hlaska z debugu: Citácia: Exception thrown at 0x0040682F in ConsoleApplication1.exe: 0xC0000005: Access violation writing location 0xCCCCCCCC. getc funguje ako ma asopn zatial EDIT: po pridani pomocneho pola priamo vo funkcii a nakonici jeho prekopirovani do pointeru funguje, len mi to pride ako nejake divne riesenie: Kód: void platarray(int *pocet, double **platy) ... ... //zistenie poctu pracovnikov ... double *temp; temp = (double *)malloc(*pocet * sizeof(double)); ... temp[a] = salary; //zapis platov do pola ... *platy = temp;
_________________ ITX >>> ATX |
|
Registrovaný: 17.07.11 Prihlásený: 29.12.20 Príspevky: 1516 Témy: 3 | Napísal BX: 06.11.2016 16:47 | |
|
Miso problém tam môže byť v priorite operátorov - viz http://en.cppreference.com/w/c/language/operator_precedence=> Najprv sa vyhodnocujú zátvorky a až potom hviezdička. Takže to asi robí niečo iné, než by si chcel. + Kopírovať celé pole netreba. Stačilo by len prehodiť si to do inej premennej správneho typu (nech nemusíš vo funkcii všade písať hviezdičku).
_________________ Na súkromné správy týkajúce sa problémov, ktoré sa riešia vo fóre, neodpovedám! |
|
Registrovaný: 15.06.14 Prihlásený: 20.04.24 Príspevky: 17930 Témy: 142 Bydlisko: Bratislava | Napísal autor témy Miso122: 06.11.2016 18:24 | |
|
ten prikaz sme dostali na prednaske ako prikaz pre alokovanie pamate pre dynamicke polia, ja som v tom dost mimo
no tak som to myslel, nakonci funkcie som cele pole prehodil po pointera co siel do mainu
vecer este skusim to prehodenie nazaciatku a odpadne mi tym par riadkov kodu
_________________ ITX >>> ATX |
|
Registrovaný: 17.07.11 Prihlásený: 29.12.20 Príspevky: 1516 Témy: 3 | Napísal BX: 06.11.2016 18:39 | |
|
Teda pozor, ak pred tou funkciu žiadne pole nealokuješ (cez malloc), tak to samozrejme musíš v tej funkcií. Inak povedané aspoň raz ho alokovať musíš. Buď pred funkciou a v nej už s ním pracuješ, alebo v tej funkcií a vrátiš novo alokované pole.
_________________ Na súkromné správy týkajúce sa problémov, ktoré sa riešia vo fóre, neodpovedám! |
|
Registrovaný: 15.06.14 Prihlásený: 20.04.24 Príspevky: 17930 Témy: 142 Bydlisko: Bratislava | Napísal autor témy Miso122: 06.11.2016 22:30 | |
|
hej, uz som si vsimol, aj ho alokoval. vdaka este mam jednu otazku, mame v zadani tuto vetu: Citácia: Ak už bolo pole predtým načítané, je najprv dealokované, a potom sa vytvorí nové. a celkom nechapem co tym myslia ja som v tom, ze ak uz bole alokovane (neviem akou podmienkou zistit), cez prikaz "free(platy);" pole dealokujem a znova vykonam alokaciu?
_________________ ITX >>> ATX |
|
Registrovaný: 22.08.11 Prihlásený: 14.12.23 Príspevky: 2361 Témy: 11 | Napísal magic: 06.11.2016 22:47 | |
|
Mozes pouzit aj realloc
|
|
Registrovaný: 15.06.14 Prihlásený: 20.04.24 Príspevky: 17930 Témy: 142 Bydlisko: Bratislava | Napísal autor témy Miso122: 06.11.2016 22:48 | |
|
usetrim jeden riadok a nevies akou podmienkou zistit ci uz bolo pole alokovane?
_________________ ITX >>> ATX |
|
Registrovaný: 22.08.11 Prihlásený: 14.12.23 Príspevky: 2361 Témy: 11 | Napísal magic: 06.11.2016 22:53 | |
|
Ked pouzijes realloc, tak nepotrebujes vediet, ci to bolo alokovane. Neviem ci existuje bezpecny sposob, ako zistit, ci je alokovane alebo nie.
|
|
Registrovaný: 15.06.14 Prihlásený: 20.04.24 Príspevky: 17930 Témy: 142 Bydlisko: Bratislava | Napísal autor témy Miso122: 06.11.2016 23:23 | |
|
a pockaj, zle citam zadanie ako zistim ci uz bolo pole niekedy davnejsie nacitane? bude to nieco ako Kód: if (*platy != NULL) { free(*platy); } *platy = (double *)malloc(*pocet * sizeof(double)); //alokacia alebo uplne inac?
_________________ ITX >>> ATX |
|
Registrovaný: 22.08.11 Prihlásený: 14.12.23 Príspevky: 2361 Témy: 11 | Napísal magic: 06.11.2016 23:32 | |
|
Nacitane znamena co ? Ak spravis malloc a potom free, tak v tom poitery zstane aj tak nieco ine ako NULL.
|
|
Registrovaný: 15.06.14 Prihlásený: 20.04.24 Príspevky: 17930 Témy: 142 Bydlisko: Bratislava | Napísal autor témy Miso122: 06.11.2016 23:38 | |
|
boli donho nacitane hodnoty (tato funkcia uz bola v programe raz vykonana). aspon tak to chapem ja
_________________ ITX >>> ATX |
|
Registrovaný: 22.08.11 Prihlásený: 14.12.23 Príspevky: 2361 Témy: 11 | Napísal magic: 07.11.2016 0:35 | |
|
Tak to si mozes teoreticky ulozit niekde do premenej, ze to uz bolo raz vykonane.
|
|
Registrovaný: 17.07.11 Prihlásený: 29.12.20 Príspevky: 1516 Témy: 3 | Napísal BX: 07.11.2016 8:52 | |
|
To, či je pole fyzicky alokované alebo nie, nezistíš. Musíš sa spoliehať na to, že programátor ho po uvoľnení vyNULLoval (čo by sa malo robiť VŽDY, a nezabudnúť aj pri deklarácií premennej) a otestovať pointer na hodnotu NULL. Ísť na to cez hodnoty nemôžeš, pretože ak prisúpiš na prvý prvok uvoľneného poľa, tak v lepšom prípade dostaneš rovnaký prvok (akoby uvoľnené nebolo - pointer stále ukazuje na rovnaké miesto, ktoré ešte nebolo prepísané), v horšom dostaneš nejakú náhodnú hodnotu (z ktorej tiež nič nezistíš) a v najhoršom prípade program spadne (operačný systém ho zakilluje).
_________________ Na súkromné správy týkajúce sa problémov, ktoré sa riešia vo fóre, neodpovedám! |
|
Registrovaný: 15.06.14 Prihlásený: 20.04.24 Príspevky: 17930 Témy: 142 Bydlisko: Bratislava | Napísal autor témy Miso122: 07.11.2016 9:06 | |
|
tak ked sa to zistit neda, skusil som to cez premennu ktora po vykonani funkcie zmeni hodnotu na true. potom som tu alokaciu vyriesil takto: Kód: if (*prikazN == false) { temp = (double *)malloc(*pocet * sizeof(double)); } if (*prikazN==true) { free(temp); temp = (double *)malloc(*pocet * sizeof(double)); } a po opatovnom spusteni funckie program prestane odpovedat
_________________ ITX >>> ATX |
|
Registrovaný: 17.07.11 Prihlásený: 29.12.20 Príspevky: 1516 Témy: 3 | Napísal BX: 07.11.2016 10:37 | |
|
Poprosím celý kód, včetne deklarácie temp. A inak poznáme aj if-else
_________________ Na súkromné správy týkajúce sa problémov, ktoré sa riešia vo fóre, neodpovedám! |
|
Registrovaný: 15.06.14 Prihlásený: 20.04.24 Príspevky: 17930 Témy: 142 Bydlisko: Bratislava | Napísal autor témy Miso122: 07.11.2016 10:47 | |
|
to hej, nejako som to vtedy pisal doradu podmeinky, else este pridam kod v aktualnom stave: Kód: void platarray(bool *prikazV, bool *prikazN, int *pocet, double *(*platy)) { *pocet = 0; FILE *f; f = fopen("zamestnanci2.txt", "r"); if ((f == NULL) || (*prikazV == 0)) { printf("Neotvoreny subor\n"); return; } char line[32]; char c; c = getc(f); while (c != EOF) //cyklus na zistenie poctu ludi v subore { if (c != '\n') { ungetc(c, f); } fgets(line, 6, f); fgets(line, 33, f); fgets(line, 3, f); fgets(line, 11, f); fgets(line, 11, f); c = getc(f); *pocet = *pocet + 1; //zistenie poctu vsetkych ludi v subore } printf("pocet ludi %d\n", *pocet); fclose(f); f = fopen("zamestnanci2.txt", "r"); if ((f == NULL) || (*prikazV == 0)) { printf("Neotvoreny subor\n"); return; } int a; a = 0; double salary; double *temp; if (*prikazN == false) { temp = (double *)malloc(*pocet * sizeof(double)); } if (*prikazN==true) { free(temp); temp = (double *)malloc(*pocet * sizeof(double)); } c = getc(f); while (c != EOF) //prechadzanie suboru este raz na nacitanie platov do pola { if (c != '\n') { ungetc(c, f); } fgets(line, 6, f); fgets(line, 33, f); fgets(line, 3, f); fgets(line, 11, f); sscanf(line, "%lf", &salary); //nacitanie platu do float-u printf("%.2lf\n", salary); fgets(line, 11, f); c = getc(f); temp[a] = salary; //vlozenie platu do pola a = a + 1; } fclose(f); *platy = (double *)malloc(*pocet * sizeof(double)); *platy = temp; *prikazN = true; } int main() //skrateny main { char c; bool prikazV; prikazV = false; bool prikazN; prikazN = false; int pocet; pocet = 0; double *platy; while ((c=getchar()) !='K') { switch (c) { case 'N': platarray(&prikazV, &prikazN, &pocet, &platy); int i; i = 0; for (i = 0; i < pocet; i++) { printf("plat[%d] = %.2lf\n", i+1, platy[i]); } mozno je tam par blbych chyb ale aspon ide (az na tu dealokaciu)
_________________ ITX >>> ATX |
|
Registrovaný: 17.07.11 Prihlásený: 29.12.20 Príspevky: 1516 Témy: 3 | Napísal BX: 07.11.2016 11:21 | |
|
Nooo... tak pekne poporiadku. Nejaké maličkosti radšej aj vynechám Premennej platy chýba inicializácia. Ak by si ju mal, nepotrebuješ tie hrozné booly s napohľad nič-nehovoriacim názvom. Kód: double *platy = NULL; //pole je prázdne, nepoužiteľné
Premennú prikazN takto môžeš úplne ostrániť. Máš predsa NULL Kód: if( (*platy) != NULL ) free(*platy); //uvolním staré pole *platy = NULL; //nastavím na NULL ako indikáciu, že pole je nepoužiteľné } double* temp = malloc(...); //každopádne naalokujem nové pole
Keďže ale *platy bude nahradené novým poľom za každých okolností, tak aj tento kód je zbytočný a môžeš napísať priamo Kód: free( *platy ); *platy = NULL; double* temp = malloc(...); . .//naplnim temp . *platy = temp;
Keďže *platy je vždy NULL, alebo platné pole, free vždy prejde ako validný príkaz (free(pole), alebo free(NULL)). Poznámka: to free(temp) je trochu nebezpečná operácia. Ak by si temp inicializoval na NULL, tak je to vporiadku - príkaz free(NULL) je validný a nevykoná nič. Príkaz free(nejaký neinicializovaný pointer) je už trocha horší a výsledok je tzv. "undefined behaviour". Čiže nikto nevie, čo sa stane, môže ti kľudne umrieť pes, takže bacha na to! To free(temp) som ale odstránil, takže preto len poznámka. Na konci to Kód: *platy = (double *)malloc(*pocet * sizeof(double)); *platy = temp;
je totálna kravina. Na čo alokuješ pole, keď si ho vzápätí prepíšeš iným? Veď pole už máš alokované a ukazuje naň premenná temp. Takže to stačí prehodiť Kód: *platy = temp;
_________________ Na súkromné správy týkajúce sa problémov, ktoré sa riešia vo fóre, neodpovedám! |
|
Registrovaný: 15.06.14 Prihlásený: 20.04.24 Príspevky: 17930 Témy: 142 Bydlisko: Bratislava | Napísal autor témy Miso122: 07.11.2016 12:56 | |
|
a este jedna vec. ja by som sa polu temp najradsej vyhol, no nedokazal som nijako napisat kod tak aby som mohol vo funkcii pracovat priamo s platy. neslo citanie, zapis, len nahradenie cez: Kód: *platy = temp; takze ak by sa mi nejako podarilo sprevadzkovat pracu priamo s hlavnym polom bolo by to idealne. no netusim ako spravit pointer do funkcie na pole s tym ze bude normalne pouzitelne. Citácia: Premennej platy chýba inicializácia. Ak by si ju mal, nepotrebuješ tie hrozné booly s napohľad nič-nehovoriacim názvom. boolom sa aj tak nevyhnem, su potrebne kvoli zadaniu ostatnych funkcii (ktore som sem pre skratenie nedaval). maju sa vykonat len ak boli najprv vykonane predchadzajuce 2 (funkcia V a N). inicializovat na null toaj tak budem musiet, kvoli free. o tom spravani prikazu free pri neinicializovanych premennych som netusil. Citácia: Na čo alokuješ pole, keď si ho vzápätí prepíšeš iným? Veď pole už máš alokované a ukazuje naň premenná temp. Takže to stačí prehodiť v ukazovateloch som uplne mimo, takze vdaka za opravu.
_________________ ITX >>> ATX |
|
Registrovaný: 17.07.11 Prihlásený: 29.12.20 Príspevky: 1516 Témy: 3 | Napísal BX: 07.11.2016 14:43 | |
|
Ak chceš pracovať priamo s platy, stačí vždy použiť zápis (*platy) včetne zátvoriek. Tak sa dereferencia vždy vykoná správne.
_________________ Na súkromné správy týkajúce sa problémov, ktoré sa riešia vo fóre, neodpovedám! |
|
Registrovaný: 15.06.14 Prihlásený: 20.04.24 Príspevky: 17930 Témy: 142 Bydlisko: Bratislava | Napísal autor témy Miso122: 07.11.2016 22:57 | |
|
super, diki. temp som dal uplne prec a konecne mi aj to pole funguje este ma stve jedna vec ohladom celeho programu (nejedna sa len o tuto funkciu). textovy subor Kód: FILE *fr; fr = fopen("zamestnanci2.txt", "r"); sa pouziva takmer vo vsetkych fuknkciach. ja som to vyriesil tak ze v kazdej sa otvori nanovo a pracuje sa s nim. chcel by som ho otvorit len v prvej funkcii a nasledne len odkazat smernikom (nech sa da pouzit premenna fr pre vsetky funkcie) a presunut sa nazaciatok namiesto zatvarania a znovuotvorenia. mam to nejako takto, no akonahle sa skonci prva funkcia, premenna fr=NULL, co netusim preco sa deje: Kód: void vypis_V(FILE *fr, int *pocet) { char c; fr = fopen("ZAMESTNANCI2.txt", "r"); if (fr == NULL) { printf("Neotvoreny subor\n"); return; } ... }
void platmin_P(FILE *fr) { if (fr == NULL) { printf("Neotvoreny subor\n"); return; } rewind(fr); ... }
void platarray_N(FILE *fr, double *platy) { if (fr == NULL) { printf("Neotvoreny subor\n"); return; } rewind(fr); ... }
int main() { ... FILE *fr; fr = NULL; while ((c = getchar()) != 'K') { switch (c) { case 'V': vypis_V(fr, &prikazV, &pocet, &pocetVP); break; case 'P': platmin_P(&prikazV); break; case 'N': platarray_N(&prikazV, &pocet, &platy); break; } } return 0; }
errory to nehadze ziadne, len dalsie funkcie uz nejdu pretoze fr=NULL tak nemozu pokracovat. Dalo by sa to nejako jednoducho vyriesit?
_________________ ITX >>> ATX |
|
Registrovaný: 17.07.11 Prihlásený: 29.12.20 Príspevky: 1516 Témy: 3 | Napísal BX: 08.11.2016 7:48 | |
|
Vždy, keď chceš použiť out parameter (čiže parameter, ktorý chceš meniť vo funkcií a nechať zmenený aj vonku), musíš použiť referenciu na danú premennú. Takže Kód: void vypis_V(FILE** fr) { (*fr) = fopen("ZAMESTNANCI2.txt", "r"); if( (*fr) == NULL ) {...} }
FILE * fr = ...; vypis_V( &fr );
_________________ Na súkromné správy týkajúce sa problémov, ktoré sa riešia vo fóre, neodpovedám! |
|
Registrovaný: 15.06.14 Prihlásený: 20.04.24 Príspevky: 17930 Témy: 142 Bydlisko: Bratislava | Napísal autor témy Miso122: 14.11.2016 12:41 | |
|
uz ide vsetko ako ma, komplet program funguje podla predstav vdaka za pomoc
_________________ ITX >>> ATX |
|
| Stránka: 1 z 1
| [ Príspevkov: 26 ] | |
Podobné témy | Témy | Odpovede | Zobrazenia | Posledný príspevok |
---|
| Pointer v C v Assembler, C, C++, Pascal, Java | 2 | 463 | 09.05.2011 10:05 the_pivo | | C volanie funkcii v Assembler, C, C++, Pascal, Java | 12 | 1161 | 22.10.2011 15:43 nBXXL | | c++ zoskupenie funkcii v Assembler, C, C++, Pascal, Java | 6 | 378 | 26.11.2012 16:42 silentasflash | | dynamicka struktura, bool a pouzitie vo funkcii C++ otazka v Assembler, C, C++, Pascal, Java | 3 | 376 | 05.02.2016 12:57 Elendil | | C# pole matíc v Assembler, C, C++, Pascal, Java | 1 | 346 | 11.07.2010 11:37 dEVIANT | | C++ pole unikátnych hodnôt v Assembler, C, C++, Pascal, Java | 4 | 387 | 24.10.2014 13:42 marian_r | | Dynamicke pole v Triede C++ v Assembler, C, C++, Pascal, Java | 1 | 2006 | 19.11.2008 14:51 Dark_Raven | | Dynamicky alokovane 2D pole C v Assembler, C, C++, Pascal, Java | 2 | 344 | 11.11.2013 13:32 Marcello123 | | Jazyk C - Oddeleny preklad - pole struktur v Assembler, C, C++, Pascal, Java | 1 | 1445 | 28.05.2010 22:18 chrono | | Ako vytvoriť pole reťazcov v C++? v Assembler, C, C++, Pascal, Java | 1 | 941 | 23.05.2011 12:58 nBXXL | | 2 rozmerne pole v C-cku v Assembler, C, C++, Pascal, Java | 4 | 1340 | 22.12.2010 21:33 the_pivo | | Internet vo vedlajsej budove v Poskytovatelia internetu | 4 | 308 | 11.10.2011 15:43 milosenko | | inteligent pointer v Assembler, C, C++, Pascal, Java | 4 | 484 | 25.10.2008 11:05 johny3212 | | Delphi: Pointer, hodnota v Delphi, Visual Basic | 1 | 1187 | 22.12.2008 22:49 programator | | Pointer cursor aj mimo textu v HTML, XHTML, XML, CSS | 2 | 346 | 21.04.2012 14:28 Bokos | | error C2109: subscript requires array or pointer type v Assembler, C, C++, Pascal, Java | 4 | 276 | 09.12.2012 15:36 BX |
| Nemôžete zakladať nové témy v tomto fóre Nemôžete odpovedať na témy v tomto fóre Nemôžete upravovať svoje príspevky v tomto fóre Nemôžete mazať svoje príspevky v tomto fóre
|
|