Histogram pliku

0

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

0

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.

0

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ć.

0

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.

0

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

0

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)

0
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";
	}

	[...]

}
0

Dzieki bardzo :D ale dalej wyswietla dwa razy s na koncu... :/

0

Przepisałeś dokładnie to, co napisałem???

0

Dokładnie... Cos trzeba zmienic w petli while zeby ostatni znak nie byl brany pod uwage...

0
while (fscanf(plik,"%c",&znak)==1) { ... }
0

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();
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1