jaśkoo Temat założony przez niniejszego użytkownika |
Dublowanie znaku przy odczycie z pliku » 2016-04-07 08:22:32 Witajcie, mam zadanie napisać program, który zlicza ilość wystąpień "*" w pliku. Pisząc program pojawiło się dla mnie kilka niejasności. 1. Dlaczego ostatni znak jest dublowany, czy to przy wyświetlaniu czy przy zliczaniu jeśli w tym przypadku jest to "*"? Dla zawartości pliku- "Ala * ma * kota *" Program wyświetla: "A l a * m a * k o t a * * 4" nie dość, że dubluje to jeszcze wlicza także tą zdublowaną "*". 2. Czy istnieje możliwość wczytywania z pliku znak po znaku bez pomijania znaków białych? 3. Czy wg Was taki układ zadeklarowanych zmiennych jest ok czy bardziej popieracie zmienne w jednym miejscu? Napisałem to w ten sposób mając na uwadze optymalizację kodu, żeby nie były tworzone zbędne na danym etapie zmienne jeśli np pliku nie odnaleziono. 4. plik.close(); umieścilibyście w ifie czy już za ifami i elsami? 5. Czy is.open() i .good() działają dokładnie tak samo? #include <iostream> #include <fstream> #include <cstdlib>
using namespace std;
void zliczanie() { fstream plik; plik.open( "dokument.txt", ios::in ); if( plik.good() ) { char znak; int licznik = 0; while( !plik.eof() ) { plik >> znak; cout << znak << endl; if( znak == '*' ) licznik++; } cout << licznik; } else { cout << "Nie odnaleziono pliku!"; exit( 0 ); } plik.close(); }
int main() { zliczanie(); return 0; }
|
|
mateczek |
» 2016-04-07 09:05:52 while( plik >> znak ) { cout << znak << endl; if( znak == '*' ) licznik++; }
while( true ) { plik >> znak; if( plik.eof() ) break; cout << znak << endl; if( znak == '*' ) licznik++; }
|
|
mokrowski |
» 2016-04-07 10:52:57 #include <iostream> #include <fstream> #include <cstdlib>
using namespace std;
void zliczanie( const char * plik_nazwa, const char znak_badany ) { size_t licznik = 0; fstream plik( plik_nazwa, ios::in | ios::binary ); if( !plik ) { cerr << "Nie odnaleziono pliku " << plik_nazwa << "!\n"; exit( EXIT_FAILURE ); } for( char znak; plik >> znak; ) { if( znak_badany == znak ) { licznik++; } cout << znak << endl; } cout << licznik << endl; }
int main() { cout << zliczanie( "dokument.txt", '*' ); }
Tak naprawdę to Twoje zadanie to wykorzystanie algorytmu count_if z biblioteki standardowej. Oczywiście zakładając że nie potrzebujesz drukowania znaków. Bo jak potrzebujesz to... for_each także z bib. std. :-) Następna sprawa to pomieszanie 2 zadań w 1 funkcji. Tu masz: sprawdzenie czy plik się otworzył, zliczanie. Ja bym (jeśli można) wydzielił do 2 funkcji. |
|
jaśkoo Temat założony przez niniejszego użytkownika |
» 2016-04-07 13:10:55 @mateczek dlaczego eof dopiero po odczytaniu znaku? Do tej pory niejednokrotnie robiłem tak jak tu i działało, np tutaj:
#include <iostream> #include <fstream> #include <cstdlib>
using namespace std;
void kolumny() { fstream plik; fstream plik2; int pomocnicza; int licznik = 0; plik.open( "liczby.dat", ios::in ); if( plik.good() == false ) { cout << "Nie odnaleziono pliku!"; exit( 0 ); } else { plik2.open( "kolumny.txt", ios::out ); while( !plik.eof() ) { plik >> pomocnicza; plik2 << pomocnicza << " "; licznik++; if( licznik % 3 == 0 ) { plik2 << endl; } } plik.close(); plik2.close(); } }
int main() { kolumny(); cout << "DONE!"; return 0; }
@mokrowski do tego co napisałeś nawet się nie odniosę, bo nie mam pojęcia o czym tam piszesz, to jeszcze nie mój poziom, ale dzięki za zainteresowanie :) |
|
Monika90 |
» 2016-04-07 14:08:42 while (!plik.eof()) działało bo miałeś szczęście, np. plik nie kończył się białym znakiem, tylko cyfrą. Typowe pliki tekstowe kończą się znakiem '\n', w takiej sytuacji twoja błędna pętla odczyta ostatnią liczbę dwa razy (przed C++11) lub odczyta dodatkowe zero (C++11 i późniejsze). Jeszcze gorsze rzeczy mogą się stać gdy w pliku trafi się jakaś litera, wtedy twoja pętla będzie nieskończona, dlatego nigdy nie używaj while (!plik.eof()) { } 2. Czy istnieje możliwość wczytywania z pliku znak po znaku bez pomijania znaków białych?
|
Istnieje, można użyć funkcji get char znak; while( plik.get( znak ) ) { std::cout << + znak << '\n'; }
|
|
jaśkoo Temat założony przez niniejszego użytkownika |
» 2016-04-07 15:36:06 Skoro eof się nie sprawdza czym proponujecie go zastąpić? Poza "while( plik >> znak )" znacie też coś analogicznego? |
|
carlosmay |
» 2016-04-07 16:00:55 Skoro eof się nie sprawdza czym proponujecie go zastąpić? Poza "while( plik >> znak )" znacie też coś analogicznego? |
Sprawdzaj ifem po odczytaniu znaku, ale przed rozpoczęciem nowej pętli. Rozwiązanie takie zaproponował @mateczek. @Monika90 podała też inne rowiązanie. Twoja propozycja też jest dobra. Dlaczego nie chcesz jej używać? (pomija spacje). |
|
jaśkoo Temat założony przez niniejszego użytkownika |
» 2016-04-07 17:44:54 Do tej pory jej używałem, ale jeśli tak łatwo o jej niewłaściwe działanie, to chyba powinienem to zmienić. Jeśli chodzi o pętlę- "while( plik.get( znak ))" to zapewne zwraca true dopóki plik się nie skończył, a jakby ktoś jeszcze mógł wyjaśnić jak działa sama funkcja .get() i w odniesieniu do plików. |
|
« 1 » 2 |