Fórum Ubuntu CZ/SK

Ubuntu pro osobní počítače => Software => Příkazový řádek a programování pro GNU/Linux => Téma založeno: zeminem 16 Května 2011, 16:18:10

Název: C++ práce se souborem
Přispěvatel: zeminem 16 Května 2011, 16:18:10
Zdravím,
právě se učím pracovat se souborem v C++. Udělal jsem si program na generování "náhodné" čtyřmístné captchy a každé vygenerované číslo se mi ukládá do souboru "vygenerovana-cisla.txt" hezky pod sebe...
Teď však nevím jak ze souboru zase správně číst. Jak například přečíst všechny hodnoty a udělat z nich průměr, nebo jak kontrolovat vygenerované číslo tak, aby se nikdy nevygenerovalo 2x vzhledem souboru? Tzn. pokud už číslo s souboru jednou je, bude se generovat nové, dokud se nenarazí na takové, které tam ještě není?
Nehledejte v tom smysl, jde o to se to jen naučit... :)

Kód: [Vybrat]
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <fstream>
/* time.h - pro práci s časem viz semínko
stdlib.h - fce rand()
fstream - pro práci se souborem */
using namespace std;

int main (int argc, char *argv[])
{

cout<<"Inicializuji..."<<endl;
ofstream soubor; /* výstupní proud do souboru (zapis), opak je IFSTREAM */
soubor.open("vygenerovana-cisla.txt",ios::app); /* vytvoří textový soubor a připíše */
if(soubor==NULL){
cout<<"Chyba: Soubor se nepodařilo otevřít."<<endl;
return 0;
}
else{
cout<<"> debug soubor vytvořen"<<endl;
cout<<endl;
}

while(true){

int cislo;
srand((unsigned) time(NULL)); /* semínko */
cislo = ((rand() % (99999+1))/10)+(rand() % (999+1)); /* část za + dodána, důvod: problémy v dev-cpp, třeba ještě poladit, je to nějaka hovadina! */
soubor<<cislo<<endl;
int test;
if(cislo >= 1000 && cislo < 10000 && test != cislo){
test=cislo;
cout<<"Pro ověření opište číslo a stiskněte enter:"<<endl;
cout<<cislo<<endl;
int vstup;
cin>>vstup;
if(cislo==vstup){
cout<<"Výborně! Nyní můžete konečně ukončit program."<<endl;
soubor.close();
return 0; /* ZDE OPRAVIT podle kompilátoru */
}
else{
cout<<"Tak takto to nepůjde! Vyčkejte na nové číslo a zkuste to znova!"<<endl;
cout<<endl;
}
}
}}

Děkuji za jakoukoliv radu.
Incpiraci jsem čerpal: ZDE (http://www.google.cz/url?sa=t&source=web&cd=1&ved=0CCkQFjAA&url=http%3A%2F%2Fwww1.osu.cz%2F~fojtik%2Fcpp%2Fcpp11.pdf&rct=j&q=%22ios%3A%3Aout%22&tbs=lr%3Alang_1cs&ei=0SPRTdinKs_ssgbc5qyoCw&usg=AFQjCNHHt4KHbYDF3zDunluJI13Yn2yx5g&sig2=6TRYhIqiG7TJffZahqxNzg&cad=rja) a ZDE (http://homel.vsb.cz/~moz017/cpp/?lek=6)
Název: Re: C++ práce se souborem
Přispěvatel: Martin Šácha 16 Května 2011, 16:35:21
Tak průměr by šel jednoduše
Kód: [Vybrat]
double prumer()
{
double sum=0,buff=0,pocet=0;
fstream vstup;
if((vstup.open("vygenerovana-cisla.txt",ios::in))==NULL)
return -1;

while(!vstup.eof())
{
vstup>>buff;
sum+=buff;
buff=0;
pocet++;
}
vstup.close();
return sum/pocet;
}
A pak ve tvé aplikaci stačí zavolat například "cout<<prumer()<<endl;" Střílím od boku, ale doufám že tam chyba není.

JIank s kontrolou existujícího - chtělo by to pole, do kterého budeš ukládat vygenerované hodnoty a při generování nového čísla projdeš FORem celé pole jestli se neopakuje...ale snad někdo přijde na něco elegantnějšího.
Název: Re: C++ práce se souborem
Přispěvatel: Martin - ViPEr*CZ* 16 Května 2011, 17:03:59
Použil bych pro čtení istream ve kterém je členská metoda getline. Ta načte ten textový soubor pěkně řádek po řádku (předpokládejme, že ukládáte captcha kódy tak, že co kód to jeden řádek). Odkaz: http://www.cplusplus.com/reference/iostream/istream/getline/
Poté už jen stačí načíst řádek a porovnat s vygenerovaným kódem. Samozřejmě to je jen učební postup. V praxi je to nesmyslnné. Pro nástin, kdyby měl daný soubor 5GB, tak ta rychlost by se značně blížila šneku, zvlášť, kdyby nastal případ, kdy se najde xkrát po sobě ke konci souboru shoda a celé to začne nanovo. Lepší je zaručit hned při generování to, aby se kody lišili nebo prostě podmínku vypustit, když to lze.
Název: Re: C++ práce se souborem
Přispěvatel: zeminem 16 Května 2011, 17:45:54
Díky za názory, pokusím se z toho něco udělat... :) Aspoň už je čeho se chytit.
Název: Re: C++ práce se souborem
Přispěvatel: zeminem 16 Května 2011, 20:50:49
Po mnoha pokusech jsem nakonec spleskal toto:

Kód: [Vybrat]
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <fstream>
/* time.h - pro práci s časem viz semínko
stdlib.h - fce rand()
fstream - pro práci se souborem */
using namespace std;

int main (int argc, char *argv[])
{

ofstream tam; /* výstupní proud do souboru (zapis), opak je IFSTREAM */
tam.open("vygenerovana-cisla.txt",ios::app); /* vytvoří textový soubor a připíše - app */

/* Povedlo se soubor otevrit? */
if(tam==NULL){
cout<<"Chyba: Soubor se nepodařilo otevřít."<<endl;
return 0;
}
/* ANO - pokračuj */
else{
while(true){
srand((unsigned) time(NULL)); /* semínko */
int cislo;
cislo = ((rand() % (99999+1))/10)+(rand() % (999+1)); /* část za + dodána, důvod: problémy v dev-cpp, třeba ještě poladit, je to nějaka hovadina! */
int test=0;
if(cislo >= 1000 && cislo < 10000 && test != cislo){
test=cislo;
cout<<"Pro ověření opište číslo a stiskněte enter:"<<endl;
cout<<cislo<<endl;
int vstup;
cin>>vstup;
if(cislo==vstup){
tam<<cislo<<endl;
cout<<endl;
cout<<"Výborně! Nyní si přečteme co je v souboru."<<endl;
tam.close(); /* uzavreni souboru */

/* otevreni souboru pro cteni */
ifstream sem;
sem.open("vygenerovana-cisla.txt",ios::in);
int radka=1;
/* vypis souboru */
while(!sem.eof()){
sem>>radka;
cout<<radka<<endl;
radka=0;
}
/* konec výpisu souboru */
sem.close();
/* konec cteni */

return 0; /* ZDE OPRAVIT podle kompilátoru */
}
else{
tam<<cislo<<endl;
cout<<"Tak takto to nepůjde! Vyčkejte na nové číslo a zkuste to znova!"<<endl;
cout<<endl;
}
}
}//konec while(true)
}//konec else ANO
}//konec main

Takže program najde, nebo vytvoří soubor, do něho ukládá všechny vygenerované captchy od prvního spuštění programu. Pokud se zadá kód blbě, vyžádá zadání nového a pokud se zadá dobře, tak vrátí celý seznam někdy vygenerovaných catptch. Nepíšu to sem však proto abych se chlubil, ale proto, že mimo jiné vypíše i jako poslední znak nulu. Jak mu mám říct, aby psal na sklo vše krom poslední řádky? Předpokládám, že je ten problém zaklet ve funkci eof()...
Název: Re: C++ práce se souborem
Přispěvatel: Martin - ViPEr*CZ* 16 Května 2011, 21:30:15
Tam je potřeba ten test dát až pod:

Kód: [Vybrat]
while(sem){
sem>>radka;
if (!sem.eof())
cout<<radka<<endl;
radka=0;
}
Název: Re: C++ práce se souborem
Přispěvatel: Martin Šácha 16 Května 2011, 21:35:12
Tam je potřeba ten test dát až pod:

Kód: [Vybrat]
while(sem){
sem>>radka;
if (!sem.eof())
cout<<radka<<endl;
radka=0;
}

Nebo místo "sem>>radka;" v původním zdrojáku dát "sem>>radka>>endl;".

Nula na konci výpisu je způsobena tím, že po načtení čísla zůstane pouze konec řádky v souboru (není eof), číslo se nanačte (ted už je eof) a tedy se vytiskne nula z předchozího průchodu.
Název: Re: C++ práce se souborem
Přispěvatel: zeminem 16 Května 2011, 21:39:25
Tam je potřeba ten test dát až pod:

Kód: [Vybrat]
while(sem){
sem>>radka;
if (!sem.eof())
cout<<radka<<endl;
radka=0;
}

Nebo místo "sem>>radka;" v původním zdrojáku dát "sem>>radka>>endl;".

Nula na konci výpisu je způsobena tím, že po načtení čísla zůstane pouze konec řádky v souboru (není eof), číslo se nanačte (ted už je eof) a tedy se vytiskne nula z předchozího průchodu.

Tohle mi nefunguje, jestli jsem to dobře pochopil, tak je to jako CIN a ani za CIN nemůžu dát ENDL...
Název: Re: C++ práce se souborem
Přispěvatel: zeminem 16 Května 2011, 21:43:36
Tam je potřeba ten test dát až pod:

Kód: [Vybrat]
while(sem){
sem>>radka;
if (!sem.eof())
cout<<radka<<endl;
radka=0;
}

Toto funguje dobře...
Zatím však děkuji oběma, bez vás bych to nedal dohromady. :)
Název: Re: C++ práce se souborem
Přispěvatel: Martin Šácha 16 Května 2011, 21:48:55
Tam je potřeba ten test dát až pod:

Kód: [Vybrat]
while(sem){
sem>>radka;
if (!sem.eof())
cout<<radka<<endl;
radka=0;
}

Nebo místo "sem>>radka;" v původním zdrojáku dát "sem>>radka>>endl;".

Nula na konci výpisu je způsobena tím, že po načtení čísla zůstane pouze konec řádky v souboru (není eof), číslo se nanačte (ted už je eof) a tedy se vytiskne nula z předchozího průchodu.

Tohle mi nefunguje, jestli jsem to dobře pochopil, tak je to jako CIN a ani za CIN nemůžu dát ENDL...

Zajímavé...měl jsem dojem, že endl je definovám i pro ifstream. Omluvám se za botu. Příště si to vyzkouším :D
Název: Re: C++ práce se souborem
Přispěvatel: Martin - ViPEr*CZ* 16 Května 2011, 22:20:29
Tam je potřeba ten test dát až pod:

Kód: [Vybrat]
while(sem){
sem>>radka;
if (!sem.eof())
cout<<radka<<endl;
radka=0;
}

Nebo místo "sem>>radka;" v původním zdrojáku dát "sem>>radka>>endl;".

Nula na konci výpisu je způsobena tím, že po načtení čísla zůstane pouze konec řádky v souboru (není eof), číslo se nanačte (ted už je eof) a tedy se vytiskne nula z předchozího průchodu.

Tohle mi nefunguje, jestli jsem to dobře pochopil, tak je to jako CIN a ani za CIN nemůžu dát ENDL...

Zajímavé...měl jsem dojem, že endl je definovám i pro ifstream. Omluvám se za botu. Příště si to vyzkouším :D

Jo jo je to zajímavé... ale určitě jsi to velice správně vysvětlil ... možná pokud by dotyčný chtěl aby to takhle fungovalo... musel by již změnit zápis do souboru.... nezapisovat číslo a za něj konec řádku... ale konec řádku a číslo (pokud by nešlo o první zápis) ... pak by samozřejmě původní načítání již fungovalo, protože na konci souboru by nebyl endl. Krásně se to dá ověřit nějakým binárním editorem, který ukáže všechny znaky v tom texťáku.
Název: Re: C++ práce se souborem
Přispěvatel: skunkos 17 Května 2011, 11:22:08
místo time.h a std.....používej v c++ <ctime> a <cstdlib> a podobně
Název: Re: C++ práce se souborem
Přispěvatel: zeminem 17 Května 2011, 11:25:27
místo time.h a std.....používej v c++ <ctime> a <cstdlib> a podobně

V čem je to jiné, nebo lepší?
Název: Re: C++ práce se souborem
Přispěvatel: Kedrigern 17 Května 2011, 11:29:09
místo time.h a std.....používej v c++ <ctime> a <cstdlib> a podobně

V čem je to jiné, nebo lepší?
Jsou to knihovny pro C++. Teoreticky mohou být lépe optimalizovaný, či zabráněno konfliktům. Jsou v normě C++.

Prakticky při drobnostech je to stejné, ale až budeš zkoumat proč ti projekt s 5MB kódu nechodí na nějaké obskurdní platformně... je lepší být si jistý, že používáš věci, tak jak jsou zamýšleny.

No a taky určitě budou podporovat C++0x.
Název: Re: C++ práce se souborem
Přispěvatel: skunkos 17 Května 2011, 12:53:40
místo time.h a std.....používej v c++ <ctime> a <cstdlib> a podobně

V čem je to jiné, nebo lepší?
Jsou to knihovny pro C++. Teoreticky mohou být lépe optimalizovaný, či zabráněno konfliktům. Jsou v normě C++.

Prakticky při drobnostech je to stejné, ale až budeš zkoumat proč ti projekt s 5MB kódu nechodí na nějaké obskurdní platformně... je lepší být si jistý, že používáš věci, tak jak jsou zamýšleny.

No a taky určitě budou podporovat C++0x.

Navíc tyhle C++ update knihovny umí používat jmenné prostory, proto třeba jména funkcí a maker cpou do std. Tedy můžeš napsat třeba
std::exit(0);
Název: Re: C++ práce se souborem
Přispěvatel: zeminem 17 Května 2011, 13:14:38
A jde jen o ty knihovny, nebo je třeba upravit i nějaké instrukce v to programu? Po změnění knihoven se to chová na první pohled stejně...

EDIT: Podle tohoto vypadají stejně, jen mají jiný název. Moc se v tom ještě nevyznám, ale myslím si to... http://www.cplusplus.com/reference/clibrary/
Název: Re: C++ práce se souborem
Přispěvatel: Kedrigern 17 Května 2011, 14:41:27
A jde jen o ty knihovny, nebo je třeba upravit i nějaké instrukce v to programu? Po změnění knihoven se to chová na první pohled stejně...

EDIT: Podle tohoto vypadají stejně, jen mají jiný název. Moc se v tom ještě nevyznám, ale myslím si to... http://www.cplusplus.com/reference/clibrary/
Čti!

Ano, mohou být stejné. Ale to neznamená, že např.  v další verzi nebudou jiné (či v jiném kompilátoru). Programy píšeš podle norem, proto aby fungovaly i za rok na jiném systému. Pokud je něco doporučeno, tak to není jen tak ze srandy. Navíc i malá změna může hodně změnit užitnou hodnotu (takovou změnou jsou právě ty jmenné prostory). Fakticky je lepší tyhle věci dělat, tak jak ti poradí lidé, co ten jazyk píšou.

Jmenné prostory jsou velmi dobrý příklad, dík.
Název: Re: C++ práce se souborem
Přispěvatel: skunkos 17 Května 2011, 15:53:23
A jde jen o ty knihovny, nebo je třeba upravit i nějaké instrukce v to programu? Po změnění knihoven se to chová na první pohled stejně...

EDIT: Podle tohoto vypadají stejně, jen mají jiný název. Moc se v tom ještě nevyznám, ale myslím si to... http://www.cplusplus.com/reference/clibrary/

Je to takový úzus, že když vlastně píšeš v C++ tak použíješ C++ knihovny(pokud jsou k dispozici, což ty std. jsou), protože jinak vznikaj takový prasácký programy, kde se míchaj knihovny odtud a odtud (čemuž se ve velkých programech dá jen těžce vyhnout).
Název: Re: C++ práce se souborem
Přispěvatel: zeminem 17 Května 2011, 16:13:23
A jde jen o ty knihovny, nebo je třeba upravit i nějaké instrukce v to programu? Po změnění knihoven se to chová na první pohled stejně...

EDIT: Podle tohoto vypadají stejně, jen mají jiný název. Moc se v tom ještě nevyznám, ale myslím si to... http://www.cplusplus.com/reference/clibrary/

Je to takový úzus, že když vlastně píšeš v C++ tak použíješ C++ knihovny(pokud jsou k dispozici, což ty std. jsou), protože jinak vznikaj takový prasácký programy, kde se míchaj knihovny odtud a odtud (čemuž se ve velkých programech dá jen těžce vyhnout).

No tak na moje "programování" je to asi jedno, každopádně díky za upozornění. Nedělám to pro nic, jen tak pro svůj pocit, že vím o co jde a pro svojí radost, že občas funguje něco co jsem tam naťukal... :)
Název: Re: C++ práce se souborem
Přispěvatel: Martin Šácha 17 Května 2011, 16:29:59
A jde jen o ty knihovny, nebo je třeba upravit i nějaké instrukce v to programu? Po změnění knihoven se to chová na první pohled stejně...

EDIT: Podle tohoto vypadají stejně, jen mají jiný název. Moc se v tom ještě nevyznám, ale myslím si to... http://www.cplusplus.com/reference/clibrary/

Je to takový úzus, že když vlastně píšeš v C++ tak použíješ C++ knihovny(pokud jsou k dispozici, což ty std. jsou), protože jinak vznikaj takový prasácký programy, kde se míchaj knihovny odtud a odtud (čemuž se ve velkých programech dá jen těžce vyhnout).

No tak na moje "programování" je to asi jedno, každopádně díky za upozornění. Nedělám to pro nic, jen tak pro svůj pocit, že vím o co jde a pro svojí radost, že občas funguje něco co jsem tam naťukal... :)

Pokud si zvykneš na pravidla od začátku, tak tě cizí kod nerozhází - a naopak, když budeš někoho žádat o radu, rychleji se v tvém kodu vyzná. :)