Witam wszystkich.
Mam do napisania program w c++ który wczytuje dowolny plik tekstowy a następnie zapisuje do innego pliku tekstowego histogram tego wczytanego pliku(ilość występowania każdej litery oraz udział procentowy wszystkich liter). Z wczytaniem pliku nie mam problemów jednak nie wiem jak zliczać ile razy każda litera występuje w pliku(jak przypisać indeks do każdej litery z osobna).
Prosze o jakaś rade
jak przypisać indeks do każdej litery z osobna.
A po co indeks? Każda litera ma swój kod i to ci wystarczy. Najprostszą metodą jest zrobienie tablicy 256 elementowej, która będzie indeksowana kodem litery, a wartość komórki inkrementowana. Inna metoda to użycie kontenera map.
Ja zrobiłbym to tak:
Najpierw stworzył bym tablice 256 elementów typu int(lub long) i ją wyzerował. później stworzył funkcje, która sprawdzałaby kod aktualnie wczytywanego znaku i wykonywała instrukcje
++tablica[wczytywany_znak];
I tak dla każdego znaku w pliku. Gdy chciałbyś sprawdzić ile razy wystąpiła np. spacja, to wystarczy odnieść sie do tego elementu tablicy jaki znak ma dany znak.
Przykład dla entera
char enter = 13;
cout<<"enter wystapil "<<tablica[enter]<<" razy.";
Tablica jest 256(a nie 255) element owa ponieważ łatwiej jest później dodawać i odczytywać coś z tablicy,
bo gdybyśmy tego nie zrobili i zapisywali wszystko od elementu 0, to przy wczytywaniu trzeba by było odejmować o jeden od numeru znaku, który akurat chcemy sprawdzić.
Proste?
P.S Pisałem z głowy i mogłem trochę pogmatwać.
http://unixhelp.ed.ac.uk/CGI/man-cgi?ascii+7
Tworzysz sobie tablicę
int litery[57]
Na początku ustawiasz wszystkie elementy na zero a następnie przy przeglądaniu pliku
litery[ (int)znak-64 ]++;
Z wyliczeniem procentów chyba sobie poradzisz?
Można by też użyć map z STLa, ale IMHO nie ma to sensu w tym przypadku.
Pzdr.
Panie Ktoś_tam'ie, a co będzie gdy znak='0'; litery[ (int)znak-64 ]++;? a nie daj boże jeszcze \t się znajdzie? :)
jak pisali koledzy wcześniej, 256 to "boża liczba", a Twoje 64 jest akurat liczbą magiczną
Szklanka chciał czytać dowolne pliki, a dowolny oznacza także EBCIDC
I znow mam problem z tym histogramem....
Oto kod programu:
#include<fstream>
#include<iostream>
//---------------------------------------------------------------------------
using namespace std;
int tab[256];
char znaki[256];
int main()
{
FILE *plik;
char znak;
int i=0;
plik = fopen("f:\\test.txt","r");
while (!feof(plik))
{
i++;
fscanf(plik,"%c",&znak);
cout<<"Podany znak " << znak << "\n";
znaki[i]=znak;
++tab[(int)znak];
}
cout<<"\n";
cout<<"\n";
cout<<"\n";
for(i=1;i<=256;i++)
{
znak=znaki[i];
if (tab[znak]!=0)
{
cout<<"Znak " << znaki[i] <<" wystepuje " << tab[znak] << " razy\n";
}
};
system("PAUSE");
return 0;
}
W pliku który otwieram jest napis: "Jakis napis".
Nie wiem dlaczego podczas wyswietlania znaków wypisuje mi dwa razy s na koncu...
NIe wiem tez co zrobić żeby wyswietlal mi tylko znaki i ile razy wystepuja w tekscie a nie tak jak moj program po kolei wszystkie znaki i ile wystepuja razy(powtarzaja sie znaki)
int main()
{
unsigned char znak;
[...]
memset(tab,0,sizeof(int)*256);
while (!feof(plik))
{
fscanf(plik,"%c",&znak);
++tab[znak];
cout<<"Podany znak " << znak << "\n";
}
[...]
for(int i=0;i<256;++i)
{
if (tab[i]!=0 && isalnum(i))
cout<<"Znak " << char(i) <<" wystepuje " << tab[i] << " razy\n";
}
[...]
}
Dzieki bardzo :D ale dalej wyswietla dwa razy s na koncu... :/
Przepisałeś dokładnie to, co napisałem???
Dokładnie... Cos trzeba zmienic w petli while zeby ostatni znak nie byl brany pod uwage...
while (fscanf(plik,"%c",&znak)==1) { ... }
fscanf? przeciez to chyba mialo byc c++? pewnie to z obawy o przypadkowe pomijanie bialych znakow jak to sie ma przy istream::operator>>. szczesliwie sa inne metody czytania niz operator>> :)
ponizsze przemieli poprawnie nawet pliki binarne
#include <iostream>
#include <fstream>
#include <map>
int main(int argc, char* argv[])
{ using namespace std;
if(argc < 3)
{ cout << "Za malo parametrow!\nPodaj nazwe pliu wejsciowego i wyjsciowego" << endl;
return 1;
}
ifstream plik_we(argv[1], ios::binary);
if(!plik_we)
{ cout << "Nie udalo sie otworzyc pliku wejsciowego" << endl;
return 2;
}
ofstream plik_wy(argv[2]);
if(!plik_wy)
{ cout << "Nie udalo sie otworzyc pliku wyjsciowego" << endl;
return 3;
}
map<unsigned char,unsigned long> stats;
for(int i=0; i<256; ++i)
stats.insert(make_pair((unsigned char)i, 0));
do
{ char c;
plik_we.read(&c,1);
if(plik_we.eof())
break;
if(plik_we.fail())
{ cout << "Blad podczas odczytu z pliku" << endl;
return 4;
}
++stats[c];
}while(1);
plik_we.close();
map<unsigned char,unsigned long>::const_iterator it, end;
it=stats.begin();
end=stats.end();
unsigned long razem = 0;
while(it!=end)
razem += it++->second;
it=stats.begin();
end=stats.end();
while(it!=end)
{ plik_wy << "Znak ";
if(isprint(it->first))
plik_wy << "'" << it->first << "' wystepuje " << it->second << " razy, czyli " << (it->second/(double)razem*100) << "%" << endl;
else
plik_wy << hex << "0x" << (unsigned int)it->first << dec << " wystepuje "<< it->second << " razy, czyli " << (it->second/(double)razem*100) << "%" << endl;
++it;
}
plik_wy.close();
}