Ĺadny brzuch
Mam do napisania prosty program (dopiero uczę się C++):
“Napisz program zliczający ilość linii, słów i znaków w pliku podanym z linii polecać lub otrzymanych na standardowym wejściu (w przypadku uruchomienia programu bez dodatkowego argumentu)”
Z moich przemyśleń ;) wynika, że ugryzłbym to tak:
program jest otwierany w konsoli,
prosi o wpisanie ciągu znaków, lub podanie adresu pliku,
sprawdza czy to nazwa pliku czy ciąg znaków
jeśli to ciąg znaków zapisuje go w tablicy (wcześniej licząc ilość znaków by zdefiniować wielkość tablicy), lub otwiera plik.
zlicza ilość linii, słów, znaków i wyświetla te liczby.
Jak na trochę dalszy początek zadanie wydaje mi się dość trudne :(
Jedyna do czego doszedłem to:
oprócz iostream musze includować fstream...
plik otworze za pomocą plik.open("nazwa pliku")
słowa w stringu policzę za pomocą funkcji: length()
No i niestety dalej mam sporo nie wiadomych i brak pewności czy dobrze rozumiem treść zadania...
Prosiłbym o jakieś wskazówki co do rozumienia zadania, lub jego realizacji.
Użytkownik Marcin edytował ten post 11 luty 2007, 23:03
w pliku podanym z linii polecać lub otrzymanych na standardowym wejściu
wiec ogolnie to wygladalo by tak ze:
int main( int argc, char **argv ) { if( argc > 1 ) { // wczytaj z pliku plik.open( argv[1] ); } else{ wczytaj z stdin cin >> zmienna; ...... } }
argc to ilosc parametrow podanych w linii komend, z tym ze pierwszy to zawsze nazwa programu.
lenght()em nie odczytasz ilosci slow, chcesz czy nie musisz przeleciec przez caly bufor po bajcie liczac sobie wszystko, wiadomo, jak spacja, to konczy sie slowo, jak bajt różny od spacji itp (http://www.cppreference.com/stdstring/index.html zobacz funkcje rozpoczynajace sie od is...) to jest jakis znak, jezeli bajt jest rowny '\n' to nowa linia , trzy zmienne , kilka warunkow i inkrementujesz. Dosc proste zadanie , dasz sobie rade ^^.
uzyj string i fstream.
Użytkownik icek edytował ten post 11 luty 2007, 23:21
Prosiłbym o jakieś wskazówki co do rozumienia zadania, lub jego realizacji.
Mogę Ci podsunąć ideę. Na podstawie pobierania w pętli z pliku znaku po znaku dokonujesz analizy. Masz kilka zmiennych co przechowują Ci dane ilości. Więc tak zmienna od ilości znaków powinna się zwiększać, aż do wczytania End Of File. Zmienna od ilości linii powinna się zwiększyć po napotkaniu znaku nowej linii (ASCII: 10). Zmienna od ilości słów po napotkaniu spacji (ASCII: 32). Mam taki program w C, ale to Cię pewnie nie zadowoli. Odnośnie C++ mogą Cię do głębszej analizy zainteresować funkcje z bibliotegki cctype:
isalpha(char ch) //Zwraca 1 gdy ch jest literą
isspace(char ch) //Zwraca 1 gdy znak ch jest białym znakiem (nowy wiersz, spacja, tabulator)
isdigit(char ch) //Zwraca 1 gdy znak ch jest cyfrą
ispunct(char ch) //Zwraca 1 gdy znak ch jest znakiem przystankowym
PS. Cholera ktoś mnie uprzedził ;)
Użytkownik kulcikriu edytował ten post 11 luty 2007, 23:29
Mam teraz problem tego typu:
- muszę przelecieć po czymś (pliku, zdaniu) i odczytać jego zapis binarny i zapisać go do tablicy
- jak będę miał kody tych znaków w tablicy to przelecieć ile jest 32 (będę miał ilość znaków), (dodać +1 i będę miał ilość słów)
Tylko jak stworzyć taką dynamiczną tablicę w miare prosto? (wszystko co znajduje bazuje na wskaźnikach, których zbytnio pojąć nie mogę)
BTW: narazie mam coś takiego (nie wiele w tym mojej pracy):
# include <iostream> # include <fstream> # include <cctype> using namespace std; int main(int argc, char **argv){ char tresc; int linie; int slowa; int znaki; if( argc > 1 ){ plik.open( argv[1] ); } else { cin >> tresc; } }
tablice do char tworzysz tak
char *wsk << wskaznik jak wiesz do char
wsk = new char[ile];
wskaznik musi pokazywac na tablice gdyz jest tworzona dynamicznie
Jesli dobrze zrozumialem to powinienes zrobic tak:
- wczytujesz zawartosc
- sprawdzasz ile jest tych znakow
- tworzysz tablice char *wsk = new char[ilosc znakow]
- petla zapisujesz (najlepiej wskaznikiem tak >> wsk[i] = znak <<
- sprawdzasz tak:
int ile_spacji
for(int i = 0; i < ilosc komorek; i++)
{
if(wsk[i] = 32)ile_spacji++;
}
przy odczytywaniu z pliku mozesz pominac alokowanie pamieci, po prostu odczytuj po bajcie. (get())
edit: co do okreslania liczby wyrazow to wez pod uwage ze miedzy wyrazami moze byc wiecej niz 1 spacja, lepszym warunkiem bylo by jednak np.: if( poprzedni_bajt == znak && bajt== whitespace ) ilosc_slow++;
tu masz przyklad na odczyt z pliku
#include <iostream> #include <fstream> #include <cctype> using namespace std; int main (int argc, char * const argv[]) { if( argc > 1 ) { // plik fstream plik( argv[1] , ios::in ); char poprzedni = 'z', bajt; int wyrazy = 0, znaki = 0, linie = 1; do { bajt = plik.get(); if( isprint(bajt) && !isspace(bajt) ) znaki ++ ; // printable, not space else if( bajt == '\n' ) linie ++ ; // new line if( (isspace(bajt)|| plik.eof()) && isprint(poprzedni) ) wyrazy ++ ; // koniec wyrazu poprzedni = bajt; } while( !plik.eof() ); // do konca pliku plik.close(); cout << "znaki: " << znaki << endl << "wyrazy: " << wyrazy << endl << "linie: " << linie << endl; } else { // todo: sprawdzanie ze stdin } return 0; }
pisalem na szybkiego z niedzialajaco klawiatura, nie daje sobie nic za ten program uciac ;p
Użytkownik icek edytował ten post 12 luty 2007, 10:12
#include <iostream> #include <fstream> #include <conio.h> using namespace std; int ile_linijek(string plik); int main(int argc, char *argv[]) { string tresc; int linie = 0; int slowa = 1; int znaki = 0; ifstream plik; if(argv[1]) { plik.open(argv[1]); linie = ile_linijek(argv[1]); } else { cin >> tresc; plik.open(tresc.c_str()); //nie sprawdzam poprawnosci linie = ile_linijek(tresc); } int i = 0; string *wsk = new string[linie]; while(getline(plik, tresc)) { wsk[i] = tresc; i++; } int a = 0; while(a < linie) { znaki += wsk[a].size(); a++; } a = 0; int z; while(a < linie) { z = wsk[a].size(); for(int i = 0; i < wsk[a].size(); i++) { if(wsk[a].at(i) != 32)(z -= 1); } slowa += z; a++; } cout << "Lini w pliku: " << linie << endl << "Slow w pliku: " << slowa << endl << "Znakow w pliku: " <<znaki << endl; if(getch()) { delete wsk; return 0; } } int ile_linijek(string plik) { ifstream odczyt(plik.c_str()); //odczytuje plik int linijek = 0; string linia; while(getline(odczyt, linia)) //petla liczaca ilosc linijek { linijek++; } return linijek; }
Mysle ze teraz jest perfekt
Użytkownik Netrix edytował ten post 12 luty 2007, 11:40
no mi się zdaje że nie jest ;)
nie ma nigdzie delete wsk; to się robi memory leak :)
pozatym czy nie łatwiej jest to zrobić na std::vector ???
aa racja, bo widzisz devcpp nie wyrzuca mi tego i dlatego nie jestem przyzwyczajony :)
zawsze zapominam delete (chyba ze sie cos kaszani)
poprawilem,
Tak sobie mysle czy nie powinno to bardziej polegac na funkcjach iostream, ale liczy sie efekt ( poza tym tamtych jeszcze zabardzo nie znam:)
Użytkownik Netrix edytował ten post 12 luty 2007, 11:44
no wiesz mi VS wyrzuca ale tylko w takiej opcji że kompilacja trwa znacznie dłużej dlatego mam to wyłączone ;P
jeszcze się tak temu przyjrzałem i jest to bardzo nieoptymalne :) bo dwa razy wczytujesz to samo :) a druga sprawa to nie zamykasz strumieni co nie jest może aż tak straszne
a z użyciem std::vector chyba wyglądało by tak(dodam że teraz nie mam ochoty za bardzo na napisanie tego tak optymalnie więc tylko zmienię twój kod) (dodam jeszcze że właśnie spostrzegłem że moim sposobem nawet nie trzeba by mieć funkcji ile_linijek ale tera nie mam zabardzo czasu i ochoty :))
#include <string> // to na samej górze #include <vector> (...) std::vector<std::string> linie; while(getline(plik, tresc)) { linie.push_back(tresc); } ! no i potem nie ma delete !
generalnie to chcąc zrobić tylko kosmetyczną zmianę potem tylko zmieniamy nazwę zmiennej (heh masło maślane) i lepiej trochę się odnosić zamiast linie[cos] to linie.at(cos) bo w II przypadku funkcja sprawdza czy niewyjechaliśmy poza vector i jakby co to rzuca wyjątek
jeszcze jedno - korzystając z std::vectora można by znacząco zredukować ten kod, nawet bardzo :) ale to już zostawiam wam :P
Użytkownik Edas edytował ten post 13 luty 2007, 07:07
wiesz funkcja ile_linijek jest skopiowana bo uzywam ja we wczytywaniu playlisty w Zecie, a reszte pisalem o 1 w nocy to chcialem to skonczyc, zeby isc spac :)
Trochę mi to zajęło :)
No ale wymyśliłem by program działał bez zapisywania znaków po tablicy :)
Trochę musiałem pokombinować ze zmiennymi bo w plikach są jakieś dodatkowe znaki...
Pominąłem problem kiedy np. są dwie spacje obok siebie.
# include <iostream> # include <fstream> # include <cctype> using namespace std; int main(int argc, char **argv){ char znak = 0; int i = -1; int spacja = 0; int liniee = 1; int linie = -1; int znaki = 0; int slowa = 0; if(argv[1]){ fstream plik( argv[1] , ios::in ); while ( !plik.eof() ){ i ++; znak = plik.get(); if (znak == ' '){ spacja++; } if (znak == '\n'){ liniee++; } znaki = i - spacja - liniee; linie = liniee; } plik.close(); }else{ while ( !cin.eof() ){ i ++; cin.get(znak); if (znak == ' '){ spacja++; } if (znak == '\n'){ linie++; } znaki = i - spacja - linie; } } slowa = spacja + 1; cout << "Ilośc znaków: " << znaki << "\n" << "Ilość słów: " << slowa << "\n" << "ilośś linii: " << linie << "\n \n"; return 0; }
No i oczywiście wielkie dzięki za pomoc :)
zanotowane.pl doc.pisz.pl pdf.pisz.pl zsf.htw.pl
“Napisz program zliczający ilość linii, słów i znaków w pliku podanym z linii polecać lub otrzymanych na standardowym wejściu (w przypadku uruchomienia programu bez dodatkowego argumentu)”
Z moich przemyśleń ;) wynika, że ugryzłbym to tak:
program jest otwierany w konsoli,
prosi o wpisanie ciągu znaków, lub podanie adresu pliku,
sprawdza czy to nazwa pliku czy ciąg znaków
jeśli to ciąg znaków zapisuje go w tablicy (wcześniej licząc ilość znaków by zdefiniować wielkość tablicy), lub otwiera plik.
zlicza ilość linii, słów, znaków i wyświetla te liczby.
Jak na trochę dalszy początek zadanie wydaje mi się dość trudne :(
Jedyna do czego doszedłem to:
oprócz iostream musze includować fstream...
plik otworze za pomocą plik.open("nazwa pliku")
słowa w stringu policzę za pomocą funkcji: length()
No i niestety dalej mam sporo nie wiadomych i brak pewności czy dobrze rozumiem treść zadania...
Prosiłbym o jakieś wskazówki co do rozumienia zadania, lub jego realizacji.
Użytkownik Marcin edytował ten post 11 luty 2007, 23:03
w pliku podanym z linii polecać lub otrzymanych na standardowym wejściu
wiec ogolnie to wygladalo by tak ze:
int main( int argc, char **argv ) { if( argc > 1 ) { // wczytaj z pliku plik.open( argv[1] ); } else{ wczytaj z stdin cin >> zmienna; ...... } }
argc to ilosc parametrow podanych w linii komend, z tym ze pierwszy to zawsze nazwa programu.
lenght()em nie odczytasz ilosci slow, chcesz czy nie musisz przeleciec przez caly bufor po bajcie liczac sobie wszystko, wiadomo, jak spacja, to konczy sie slowo, jak bajt różny od spacji itp (http://www.cppreference.com/stdstring/index.html zobacz funkcje rozpoczynajace sie od is...) to jest jakis znak, jezeli bajt jest rowny '\n' to nowa linia , trzy zmienne , kilka warunkow i inkrementujesz. Dosc proste zadanie , dasz sobie rade ^^.
uzyj string i fstream.
Użytkownik icek edytował ten post 11 luty 2007, 23:21
Prosiłbym o jakieś wskazówki co do rozumienia zadania, lub jego realizacji.
Mogę Ci podsunąć ideę. Na podstawie pobierania w pętli z pliku znaku po znaku dokonujesz analizy. Masz kilka zmiennych co przechowują Ci dane ilości. Więc tak zmienna od ilości znaków powinna się zwiększać, aż do wczytania End Of File. Zmienna od ilości linii powinna się zwiększyć po napotkaniu znaku nowej linii (ASCII: 10). Zmienna od ilości słów po napotkaniu spacji (ASCII: 32). Mam taki program w C, ale to Cię pewnie nie zadowoli. Odnośnie C++ mogą Cię do głębszej analizy zainteresować funkcje z bibliotegki cctype:
isalpha(char ch) //Zwraca 1 gdy ch jest literą
isspace(char ch) //Zwraca 1 gdy znak ch jest białym znakiem (nowy wiersz, spacja, tabulator)
isdigit(char ch) //Zwraca 1 gdy znak ch jest cyfrą
ispunct(char ch) //Zwraca 1 gdy znak ch jest znakiem przystankowym
PS. Cholera ktoś mnie uprzedził ;)
Użytkownik kulcikriu edytował ten post 11 luty 2007, 23:29
Mam teraz problem tego typu:
- muszę przelecieć po czymś (pliku, zdaniu) i odczytać jego zapis binarny i zapisać go do tablicy
- jak będę miał kody tych znaków w tablicy to przelecieć ile jest 32 (będę miał ilość znaków), (dodać +1 i będę miał ilość słów)
Tylko jak stworzyć taką dynamiczną tablicę w miare prosto? (wszystko co znajduje bazuje na wskaźnikach, których zbytnio pojąć nie mogę)
BTW: narazie mam coś takiego (nie wiele w tym mojej pracy):
# include <iostream> # include <fstream> # include <cctype> using namespace std; int main(int argc, char **argv){ char tresc; int linie; int slowa; int znaki; if( argc > 1 ){ plik.open( argv[1] ); } else { cin >> tresc; } }
tablice do char tworzysz tak
char *wsk << wskaznik jak wiesz do char
wsk = new char[ile];
wskaznik musi pokazywac na tablice gdyz jest tworzona dynamicznie
Jesli dobrze zrozumialem to powinienes zrobic tak:
- wczytujesz zawartosc
- sprawdzasz ile jest tych znakow
- tworzysz tablice char *wsk = new char[ilosc znakow]
- petla zapisujesz (najlepiej wskaznikiem tak >> wsk[i] = znak <<
- sprawdzasz tak:
int ile_spacji
for(int i = 0; i < ilosc komorek; i++)
{
if(wsk[i] = 32)ile_spacji++;
}
przy odczytywaniu z pliku mozesz pominac alokowanie pamieci, po prostu odczytuj po bajcie. (get())
edit: co do okreslania liczby wyrazow to wez pod uwage ze miedzy wyrazami moze byc wiecej niz 1 spacja, lepszym warunkiem bylo by jednak np.: if( poprzedni_bajt == znak && bajt== whitespace ) ilosc_slow++;
tu masz przyklad na odczyt z pliku
#include <iostream> #include <fstream> #include <cctype> using namespace std; int main (int argc, char * const argv[]) { if( argc > 1 ) { // plik fstream plik( argv[1] , ios::in ); char poprzedni = 'z', bajt; int wyrazy = 0, znaki = 0, linie = 1; do { bajt = plik.get(); if( isprint(bajt) && !isspace(bajt) ) znaki ++ ; // printable, not space else if( bajt == '\n' ) linie ++ ; // new line if( (isspace(bajt)|| plik.eof()) && isprint(poprzedni) ) wyrazy ++ ; // koniec wyrazu poprzedni = bajt; } while( !plik.eof() ); // do konca pliku plik.close(); cout << "znaki: " << znaki << endl << "wyrazy: " << wyrazy << endl << "linie: " << linie << endl; } else { // todo: sprawdzanie ze stdin } return 0; }
pisalem na szybkiego z niedzialajaco klawiatura, nie daje sobie nic za ten program uciac ;p
Użytkownik icek edytował ten post 12 luty 2007, 10:12
#include <iostream> #include <fstream> #include <conio.h> using namespace std; int ile_linijek(string plik); int main(int argc, char *argv[]) { string tresc; int linie = 0; int slowa = 1; int znaki = 0; ifstream plik; if(argv[1]) { plik.open(argv[1]); linie = ile_linijek(argv[1]); } else { cin >> tresc; plik.open(tresc.c_str()); //nie sprawdzam poprawnosci linie = ile_linijek(tresc); } int i = 0; string *wsk = new string[linie]; while(getline(plik, tresc)) { wsk[i] = tresc; i++; } int a = 0; while(a < linie) { znaki += wsk[a].size(); a++; } a = 0; int z; while(a < linie) { z = wsk[a].size(); for(int i = 0; i < wsk[a].size(); i++) { if(wsk[a].at(i) != 32)(z -= 1); } slowa += z; a++; } cout << "Lini w pliku: " << linie << endl << "Slow w pliku: " << slowa << endl << "Znakow w pliku: " <<znaki << endl; if(getch()) { delete wsk; return 0; } } int ile_linijek(string plik) { ifstream odczyt(plik.c_str()); //odczytuje plik int linijek = 0; string linia; while(getline(odczyt, linia)) //petla liczaca ilosc linijek { linijek++; } return linijek; }
Mysle ze teraz jest perfekt
Użytkownik Netrix edytował ten post 12 luty 2007, 11:40
no mi się zdaje że nie jest ;)
nie ma nigdzie delete wsk; to się robi memory leak :)
pozatym czy nie łatwiej jest to zrobić na std::vector ???
aa racja, bo widzisz devcpp nie wyrzuca mi tego i dlatego nie jestem przyzwyczajony :)
zawsze zapominam delete (chyba ze sie cos kaszani)
poprawilem,
Tak sobie mysle czy nie powinno to bardziej polegac na funkcjach iostream, ale liczy sie efekt ( poza tym tamtych jeszcze zabardzo nie znam:)
Użytkownik Netrix edytował ten post 12 luty 2007, 11:44
no wiesz mi VS wyrzuca ale tylko w takiej opcji że kompilacja trwa znacznie dłużej dlatego mam to wyłączone ;P
jeszcze się tak temu przyjrzałem i jest to bardzo nieoptymalne :) bo dwa razy wczytujesz to samo :) a druga sprawa to nie zamykasz strumieni co nie jest może aż tak straszne
a z użyciem std::vector chyba wyglądało by tak(dodam że teraz nie mam ochoty za bardzo na napisanie tego tak optymalnie więc tylko zmienię twój kod) (dodam jeszcze że właśnie spostrzegłem że moim sposobem nawet nie trzeba by mieć funkcji ile_linijek ale tera nie mam zabardzo czasu i ochoty :))
#include <string> // to na samej górze #include <vector> (...) std::vector<std::string> linie; while(getline(plik, tresc)) { linie.push_back(tresc); } ! no i potem nie ma delete !
generalnie to chcąc zrobić tylko kosmetyczną zmianę potem tylko zmieniamy nazwę zmiennej (heh masło maślane) i lepiej trochę się odnosić zamiast linie[cos] to linie.at(cos) bo w II przypadku funkcja sprawdza czy niewyjechaliśmy poza vector i jakby co to rzuca wyjątek
jeszcze jedno - korzystając z std::vectora można by znacząco zredukować ten kod, nawet bardzo :) ale to już zostawiam wam :P
Użytkownik Edas edytował ten post 13 luty 2007, 07:07
wiesz funkcja ile_linijek jest skopiowana bo uzywam ja we wczytywaniu playlisty w Zecie, a reszte pisalem o 1 w nocy to chcialem to skonczyc, zeby isc spac :)
Trochę mi to zajęło :)
No ale wymyśliłem by program działał bez zapisywania znaków po tablicy :)
Trochę musiałem pokombinować ze zmiennymi bo w plikach są jakieś dodatkowe znaki...
Pominąłem problem kiedy np. są dwie spacje obok siebie.
# include <iostream> # include <fstream> # include <cctype> using namespace std; int main(int argc, char **argv){ char znak = 0; int i = -1; int spacja = 0; int liniee = 1; int linie = -1; int znaki = 0; int slowa = 0; if(argv[1]){ fstream plik( argv[1] , ios::in ); while ( !plik.eof() ){ i ++; znak = plik.get(); if (znak == ' '){ spacja++; } if (znak == '\n'){ liniee++; } znaki = i - spacja - liniee; linie = liniee; } plik.close(); }else{ while ( !cin.eof() ){ i ++; cin.get(znak); if (znak == ' '){ spacja++; } if (znak == '\n'){ linie++; } znaki = i - spacja - linie; } } slowa = spacja + 1; cout << "Ilośc znaków: " << znaki << "\n" << "Ilość słów: " << slowa << "\n" << "ilośś linii: " << linie << "\n \n"; return 0; }
No i oczywiście wielkie dzięki za pomoc :)