C, předání hodnot zpět do funkce main

C++, C#, Visual Basic, Delphi, Perl a ostatní

Moderátor: Moderátoři Živě.cz

Odeslat příspěvekod majklb 3. 3. 2011 21:10

Kód: Vybrat vše
void nacteni_souboru(int velikost, int *vstup, int cpocet)
{
  int cti = 0, i;
  const char *VSTUPNISOUBOR = "vstup.txt";
  FILE *cteni;
  cteni = fopen(VSTUPNISOUBOR,"r");
  while(fscanf(cteni, "%d",&cti) != EOF)
    cpocet += 1;
   velikost = cpocet;
  for(i = 0; i < velikost; i++)
    fscanf(cteni, "%d", &vstup[i]);

  fclose(cteni);
  //return (cpocet, velikost, vstup);
}



int main()
{
  //const char *VSTUPNISOUBOR = "vstup.txt";
  const char *SOUCET = "soucet.txt";
  const char *SERAZENI= "MinMax.txt";
  //const char *INTERVALY= "interval od Min.txt";
  int *minMax, *interval, *vstup;
  int i, min, max, velikost = 0, pocet = 0, soucet = 0, cpocet = 0, rozsah_intervalu;
  FILE  *zapis;

  nacteni_souboru(velikost, vstup, cpocet);
  printf("Ve vstupnim souboru je %d cisel, s nimiz bude program pracovat\n", cpocet);
  //velikost = cpocet;
  printf("Zadejte rozsah intervalu do kterych budete chtit vase data tridit: ");
  scanf("%d", &rozsah_intervalu);



Zdravím, potřeboval bych poradit s tím, jak to udělat, aby se mi vracel ukazatel *vstup a cpocet, teď když program spustím, tak se spustí, načte si ty hodnoty a snad je i uloží to pole vstupu, ale jak se přejde do funkce main, tak už jsou všechny hodnoty automaticky vynulované :-( potřebuju nějakou jednoduchou radu, jak to spravit

A ještě mi to hází že je (nebo občas že může být) neinicalizovaná proměnná, tak to řeším tím, že ji při prvním použití přiřadím nulu, je to správné??

Předem díky všem za odpovědi
majklb
Junior

Odeslat příspěvekod pepekpepek 3. 3. 2011 21:23

u toho cpocet nesmis predavat hodnotou ale referenci
pepekpepek
Kolemjdoucí

Odeslat příspěvekod majklb 3. 3. 2011 21:52

a ty načtená čísla mi to bude načítat v pohodě dál? Jsem se na to snažil přijít a udělal jsem z toho místo voidu opět int, jako jsem to už měl(ale četl jsem, že nejde předávat víc hodnot, což já potřebuju), tak to jsem zjistil, že jsem je nikam nepřirazoval, takže proto se mi žádná čísla nepředávala, ale nechápu jakto, že mi to vždy po skončení programu všechny hodnoty vynuluje zase (jestli si to bere z deklarace, kde mám většinu proměnných "inicializovaných" na nulu)
majklb
Junior

Odeslat příspěvekod Bari007 3. 3. 2011 22:13

Asi s Céčkem začínáš, že? Některé části kódu neodpovídají úplně tomu, jak by se to mělo psát... A celkově ten kód je nějaký divný a dost špatně čitelný.

Pokud chceš pracovat jenom s cpocet, tak si dej návratovou hodnotu funkce nacteni_souboru typu integer a vracej si ten cpocet, funkci si volej přímo v printf v mainu, ne tak jak to máš teď. Tvůj zápis mi nedává moc smysl...

Pokud chceš předávat i vstup, alokuj mu paměť pomocí malloc. Ale s tím vstupem už tam pak v mainu nic neděláš, tak nevím...
Bari007
VIP uživatel
Uživatelský avatar

Odeslat příspěvekod majklb 3. 3. 2011 22:26

ahá, díky, ráno vyzkouším, teď to vzdávám. Jinak poznal jsi to dobře, s céčkem začínám (nebo spíš tímhle programem končím :-D díkybohu). A ten program není vůbec celý, jen mi jde o to předání hodnot a zbytek je nepodstatný, ten funguje (dokud jsem se nesnažil i to načítání ze souboru dělat pomocí funkce).-..alokaci tam mám taky, jen až dál v programu (což je asi blbě když o tom tak přemýšlím).
Můj hlavní cíl je ve funkci načíst soubor (do pole), spočítat kolik tam je hodnot a předat do hlavního programu, kde se se vším zase pracuje.
majklb
Junior

Odeslat příspěvekod Bari007 3. 3. 2011 22:42

Tu alokaci paměti bys měl mít ve funkci nacteni_souboru.

Pokud chceš pracovat pouze s hodnotou cpocet, pak ji jednoduše dej do návratové hodnoty té funkce nacteni_souboru. A vypisuj pomocí
Kód: Vybrat vše
printf("Ve vstupnim souboru je %d cisel, s nimiz bude program pracovat\n", nacteni_souboru(velikost, vstup, cpocet));
Bari007
VIP uživatel
Uživatelský avatar

Odeslat příspěvekod majklb 4. 3. 2011 17:37

aháá, díky jdu to vyzkoušet ..a kdybych potřeboval i načíst ty hodnoty z toho souboru ? jde to vyřešit pomocí jedné funkce??

-- 4. 3. 2011 18:09 --

Tak jsem to vyzkoušel a to funguje, ale jde mi ještě o to předání toho celého pole vstup[i], abych i dál v programu mohl pracovat s těmi čísly. Takhle mi to vypíše jen ten počet čísel, ale nic dalšího nefunguje :-(
majklb
Junior

Odeslat příspěvekod Bari007 4. 3. 2011 18:17

O tom poli už jsem psal - alokuj mu paměť ve funkci nacteni_souboru pomocí malloc a pak dereferencí s tím pracuj dál.
Bari007
VIP uživatel
Uživatelský avatar

Odeslat příspěvekod majklb 4. 3. 2011 18:30

ahá, paměť mu už alokuji. a mám s tím dál pracovat jako s int nacteni_souboru teda? jelikož když jsem to zkoušel jako void (někde jsem se dočetl že jedině tak jde načíst více věcí z funkce), tak to nefunguje. Pro jistotu se zeptám, tu derefernci myslíš jak přesně?
Tak ať se snažím jak se snažím, tak to nepředá to pole. vstup má vždycky po přestupu z funkce do mainu adresu 0x0
Naposledy upravil majklb dne 4. 3. 2011 19:08, celkově upraveno 1
majklb
Junior

Odeslat příspěvekod Bari007 4. 3. 2011 19:07

Zde je velice hezky popsané, jak na návrat více hodnot funkce: http://www.jazykc.ic.cz/vyuka/pointery.html
Bari007
VIP uživatel
Uživatelský avatar

Odeslat příspěvekod majklb 4. 3. 2011 19:15

Kód: Vybrat vše
int nacteni_souboru(int velikost, int *vstup, int cpocet)
{
  int cti = 0, i;
  const char *VSTUPNISOUBOR = "vstup.txt";
  FILE *cteni;
  cteni = fopen(VSTUPNISOUBOR,"r");
  while(fscanf(cteni, "%d",&cti) != EOF)
    cpocet += 1;
  velikost = cpocet;
  for(i = 0; i < velikost; i++)
    fscanf(cteni, "%d", &vstup[i]);

  if ((vstup = (int*)malloc(velikost * sizeof(int))) == NULL) {
    printf("Malo pameti!\n");
    exit(1);
  }
  fclose(cteni);
  return cpocet;
}

int main()
{
  //const char *VSTUPNISOUBOR = "vstup.txt";
  const char *SOUCET = "soucet.txt";
  const char *SERAZENI= "MinMax.txt";
  //const char *INTERVALY= "interval od Min.txt";
  int *minMax, *interval, *vstup = 0;
  int i, min, max, velikost = 0, pocet = 0, soucet = 0, cpocet = 0, rozsah_intervalu;
  FILE  *zapis;


  //velikost = nacteni_souboru(velikost, vstup, cpocet);

  //velikost = cpocet;

  printf("Ve vstupnim souboru je %d cisel, s nimiz bude program pracovat\n", cpocet = nacteni_souboru(velikost, vstup, cpocet));
  printf("Zadejte rozsah intervalu do kterych budete chtit vase data tridit: ");
  scanf("%d", &rozsah_intervalu);

  soucet = soucet_cisel(vstup, velikost);



takhle to mám teď. Četl jsem tamto, ale po přečtení nevím zatím moc co se mě týká, tuším, že až to úplně nejvíc dole, ale zase to není úplně můj případ, jelikož já potřebuju předat jak to pole, tak ten cpocet a tam mají jen return a nic zatím (to nevím co znamená, neboli co se předává)
majklb
Junior

Odeslat příspěvekod Nargon 4. 3. 2011 19:23

Mno ukazatele, jsou jedna moznost, ale nejlepsi reseni je pres reference:
staci upravit definici funkce:
int nacteni_souboru(int& velikost, int& *vstup, int& cpocet)

Snad je to dobre (si to moc nepamatuju, c/c++ jsem fakt dlouho nepouzil) ale tahle mala uprava by mela stacit aby veskere hodnoty, ktere do tech promenych nastavis v te funkci, tak aby byly i v tech promenych po tom co ta funkce skonci.
Desktop: Ryzen 7 1800X (3.95GHz, 1.35V), Asus Crosshair VI Hero, 16GB DDR4 Ram (3200MHz), 128GB SSD + 3TB HDD, Nvidia GTX 1080
Notebook: Asus UL50VT 15.6" (SU7300@1.7GHz, 4GB ram, 500GB HDD, Intel GMA 4500MHD + nVidia G210M, dlouha vydrz cca 7+ hod)
Nargon
Moderátor

Odeslat příspěvekod majklb 4. 3. 2011 19:28

zkoušel jsem to a píše mi to že to očekávalo , ; nebo ) ale koukal jsem se na netu a ty reference jsou asi jen pro C++ :'(
majklb
Junior

Odeslat příspěvekod Bari007 4. 3. 2011 20:10

Ano, týká se tě ta část dole, resp. ten poslední příklad. Princip je v tom, že nepracuješ přímo s hodnotou, ale s ukazatelem na tu hodnotu v paměti. A díky tomu s ní pracuješ i v další funkci, protože paměť se uvolňuje po skončení programu nebo pomocí free. V tom posledním příkladu je naprosto jasně vidět, jak se to používá.
Kód: Vybrat vše
int nacteni_souboru(int velikost, int *vstup, int *cpocet)
{
  int cti = 0, i;
  const char *VSTUPNISOUBOR = "vstup.txt";
  FILE *cteni;
  cteni = fopen(VSTUPNISOUBOR,"r");
  while(fscanf(cteni, "%d",&cti) != EOF)
    *cpocet += 1;
  velikost = cpocet;
  for(i = 0; i < velikost; i++)
    fscanf(cteni, "%d", &vstup[i]);

  if ((vstup = (int*)malloc(velikost * sizeof(int))) == NULL) {
    printf("Malo pameti!\n");
    exit(1);
  }
  fclose(cteni);
  return;
}

int main()
{
  //const char *VSTUPNISOUBOR = "vstup.txt";
  const char *SOUCET = "soucet.txt";
  const char *SERAZENI= "MinMax.txt";
  //const char *INTERVALY= "interval od Min.txt";
  int *minMax, *interval, *vstup = 0;
  int i, min, max, velikost = 0, pocet = 0, soucet = 0, *cpocet, rozsah_intervalu;
  FILE  *zapis;


  //velikost = nacteni_souboru(velikost, vstup, cpocet);

  //velikost = cpocet;
nacteni_souboru(velikost, vstup, &cpocet);
  printf("Ve vstupnim souboru je %d cisel, s nimiz bude program pracovat\n", cpocet);
  printf("Zadejte rozsah intervalu do kterych budete chtit vase data tridit: ");
  scanf("%d", &rozsah_intervalu);

  soucet = soucet_cisel(vstup, velikost);

Nedáváš sem ale celý kód, takže nevím, kde a jak se pracuje s tím polem vstup. Nicméně cpocet funguje.

Použil jsem kód z tvého posledního příspěvku (viewtopic.php?p=8077006#p8077006) a upravil jsem jen to nutné, co bylo k tomuto problému potřeba. Na zbytek kódu jsem nesahal a ani nebudu a tím pádem nenesu žádnou zodpovědnost za to, jestli funguje, jak funguje a jakým stylem je psaný.
Bari007
VIP uživatel
Uživatelský avatar

Odeslat příspěvekod majklb 5. 3. 2011 08:45

Kód: Vybrat vše
int nacteni_souboru(int velikost, int *vstup, int *cpocet)
{
  int cti = 0, i;
  const char *VSTUPNISOUBOR = "vstup.txt";
  FILE *cteni;
  cteni = fopen(VSTUPNISOUBOR,"r");
  while(fscanf(cteni, "%d",&cti) != EOF)
    *cpocet += 1;
  velikost = cpocet;
  for(i = 0; i < velikost; i++)
    fscanf(cteni, "%d", &vstup[i]);

  if ((vstup = (int*)malloc(velikost * sizeof(int))) == NULL) {
    printf("Malo pameti!\n");
    exit(1);
  }
  fclose(cteni);
  return;
}


int soucet_cisel(int *vstup, int velikost)
{
  int soucet = 0, i = 0;
  for( i = 0; i < velikost; i++) {
    soucet += vstup[i];
  }
  return soucet;
}



int main()
{
  //const char *VSTUPNISOUBOR = "vstup.txt";
  const char *SOUCET = "soucet.txt";
  const char *SERAZENI= "MinMax.txt";
  //const char *INTERVALY= "interval od Min.txt";
  int *minMax, *interval, *vstup = 0;
  int i, min, max, velikost = 0, pocet = 0, soucet = 0, cpocet = 0, rozsah_intervalu;
  FILE  *zapis;

  nacteni_souboru(velikost, vstup, &cpocet);
  printf("Ve vstupnim souboru je %d cisel, s nimiz bude program pracovat\n", cpocet);
  printf("Zadejte rozsah intervalu do kterych budete chtit vase data tridit: ");
  scanf("%d", &rozsah_intervalu);

  soucet = soucet_cisel(vstup, velikost);
  zapis = fopen(SOUCET,"w+");
  fprintf(zapis,"Celkovy soucet od 1. do %d. císla je %d\n",velikost, soucet);
  fclose(zapis);

  return 0
}

Omlouvám se, chtěl jsem to přidat, aby šlo zkontrolovat jestli už to funguje, ale zapomněl jsem tam dát fci soucet..takže teď by to snad už mělo jít testovat, ale zkoušel jsem to a nefungovalo to :( jelikož cpocet předávám do proměnné velikost (která je int), tak se mi předala nějaká veliká hodnota. Takže tam pravděpodobně neproběhla ani celá fce nacteni_souboru ..a po spuštění programu se mi nezobrazily ani ty hlášky o počtu čísel v souboru a čekání na další tlačítko. Doufám, že po upravení tohoto kódu to bude možné. Stačí mít soubor vstup.txt s pár údaji pod sebou a měl by se pak vytvořit součet čísel v texťáku soucet.txt

majklb
Junior

Odeslat příspěvekod Bari007 5. 3. 2011 11:08

Nechápu význam proměnné velikost. Vždyť velikost je to stejné, co cpocet ne? Ty ale pracuješ na několika místech i s proměnnou velikost, která kromě funkce nacteni_souboru nenabývá žádných hodnot a i v té funkci načtení souboru má stejnou hodnotu, jako cpocet. K čemu teda ta proměnná je? Nestačí pracovat jenom s cpocet?

V mainu ti chybí za returnem středník.

Zkus si to nejdřív napsat tak, abys načítal hodnoty z příkazové řádky, nepracovat zatím se souborem.

Paměť pro vstup si musíš alokovat dřív, než začneš to pole vstup naplňovat, tzn. nejdřív si zjistíš, kolik je v souboru hodnot, pak si podle toho alokuješ paměť a až pak začneš ty hodnoty ze souboru načítat.

Když pracuješ se soubory, měl by sis testovat, jestli se povedlo otevření a uzavření souboru.

Hodnoty z funkce sčítající čísla pak vypisuješ opět nesmyslně, prostě volej tu funkci přímo v printf.
Bari007
VIP uživatel
Uživatelský avatar

Odeslat příspěvekod majklb 6. 3. 2011 17:38

velikost tam je jen proto, že pak v programu něco měním a cpocet se ještě mění nebo se používá jen jedna z těchto hodnot. v mainu u returnu středník už mám, to jsem si nevšiml při kopírování. To upravím ten součet, to testování otevření a zavření naštěstí testovat nemusíme (i když je mi jasný, že v běžném programu by se to psalo). A u té alokace paměti, ta se alokuje i pro main i když ji alokuju v té funkci? A o práci se soubory to není, jde mi opravdu jen a jen o to, jak předat do mainu vstup[1]= x až vstup[n]=xn, a zároveň ten cpocet (ale teď mi došlo, že by to možná šlo řešit přes ten index (neboli to "i") a jen z toho bych odvodil cpocet, jen mi to stále nepředává ten hodnoty toho vstupu :( a bohužel mě už nic nenapadá, jak by to mohlo jít. jestli to je tím co předávám do programu, nebo jak to mám vše definováno.
majklb
Junior

Odeslat příspěvekod Bari007 6. 3. 2011 18:04

Testovat otevření/zavření souboru bys měl také kvůli sobě ;) Protože se ti může stát, že se to nepovede a program pak bude pracovat chybně nebo nebude pracovat vůbec a ty se můžeš divit, v čem je chyba...Na testování je jednoduchá podmínka, určitě bych ji tam dal ;)

Ta paměť je alokovaná tak dlouho, dokud ji neuvolníš. A uvolní se pomocí free nebo skončením programu.

Návrat více hodnot realizuj pomocí ukazatelů. Už jsem ti to popisoval a dával jsem ti i odkaz, kde máš uvedený příklad užití. Použití pro pole je prakticky stejné, jako pro proměnnou - ukazuješ na začátek pole.
Bari007
VIP uživatel
Uživatelský avatar

Odeslat příspěvekod majklb 6. 3. 2011 20:22

aha, tak tu paměť tu mažu na konci pomocí free, a to testování tam teda asi taky hodím, ale zatím jsem si jistej, že otevřít to jde i k hodnotám se dostane ta funkce, jen se mi předá vždycky jen ten cpocet a žádná další hodnota :( pokud vím, tak nikde ten můj případ není popsanej - že předám cpocet + pole (někde jsem četl, že pole se předává automaticky, ale v tom mém programu prostě už má pole adresu, ale hned jak projede return a konečná závorka, tak vstup = 0x0)
majklb
Junior


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 0 návštevníků