zliczanie słów i niepoprawne wartości

0

Witam chciałem napisać program do zliczania słów ile razy występowały. Robię to tylko przy pomocy wektorów (po to by się uczyć) wiem że do tego wykorzystujemy count() oraz map(). Ale postanowiłem zobaczyć czy udam mi się rozwiązać ten problem przy pomocy wektorów a później chce to samo na listach. Ma dziwny problem bo program działa tylko poprawni kiedy podam coś takiego {ee gg ara ara} wtedy zlicza poprawnie: ee 1 gg 1 ara 2 w innych przypadkach mam głupoty.

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    int k = 1;
    vector<string> words;
//    vector<string> usedWords = ;
    for (int i = 0 ; i < 4 ; ++i)
    {
        string addWords;
        cin >> addWords;
        words.push_back(addWords);
    }
    for ( int i = 0; i < words.size() ; ++i)
    {
            for ( int j = i + 1 ; j < words.size() ; ++j)
            {
                if ( words[i] == words[j] )
                {
                    words.erase(words.begin()+j);
                    k++;
                }
            }
//        if (words[i] == usedWords(usedWords.begin(),usedWords.end() ) )
//            int count_words = count(words.begin() , words.end(), words[i]);
            cout << "slowo " << words[i] << " wystepuje: " << k << endl;
    }

    return 0;
}

 
2

Ten kod ma niewiele sensu. Użyj do tego map<string,int> i po prostu rób coś na zasadzie:
dla każdego słowa:
jeśli słowa nie ma w mapie to dodaj do mapy (słowo,0)
wyciagnij z mapy licznik dla danego słowa i włóż licznik +1

0

ale chodzi ci o to że nie da się zrobić czy jak tak źle to napisałem?

0

Nie no tak ogólnie to różne rzeczy się da zrobić, ale to co napisałeś nie ma nic wspólnego z tym co chciałeś osiągnąć.

0

Ale czemu? W końcu udało mi się zrobić że jak mam 3 razy jakieś słowo to kasuje 2 i zlicza tylko jedno. Ale dalej mam problem, bo nawet przy jednym słowie pokazuje dalej tyle samo zliczeń co przy tym słowie które wystąpiło 3 razy. Wiem że problem polega na zmiennej k bo używam jej do całość a nie tylko do tych słów których jest kilka.

 #include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    int k = 1;
    vector<string> words;
//    vector<string> usedWords = ;
    for (int i = 0 ; i < 4 ; ++i)
    {
        string addWords;
        cin >> addWords;
        words.push_back(addWords);
    }
    for ( int i = 0; i < words.size() ; ++i)
    {
            for ( int j = i + 1 ; j < words.size() ; ++j)
            {

                while ( words[i] == words[j] )
                {
                    k++;
                    words.erase(words.begin()+j);
                }

            }
            cout << "slowo " << words[i] << " wystepuje: " << k << endl;
    }

    return 0;
}
2

Hmm a moze to dlatego że masz TYLKO JEDEN LICZNIK o nazwie k? Więc czemu się spodziewasz że liczysz nim coś dla wielu różnych słów? ;] Dlatego sugerowałem mapę która dla słowa przypisuje jego własny licznik...

0

już zrobiłem teraz będę testował na większej ilości danych.

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    vector<string> words;
    for (int i = 0 ; i < 4 ; ++i)
    {
        string addWords;
        cin >> addWords;
        words.push_back(addWords);
    }
    for ( int i = 0; i < words.size() ; ++i)
    {
        int k = 1;
            for ( int j = i + 1 ; j < words.size() ; ++j)
            {
                while ( words[i] == words[j] )
                {

                    k++;
                    words.erase(words.begin()+j);
                }
            }

            cout << "slowo " << words[i] << " wystepuje: " << k << endl;
    }

    return 0;
}

 

po prostu zmienna k nie wskakiwała nigdzie na początkującą wartość i cały czas pamiętała wartość tę co zliczała kiedy słów było więcej

0

Możesz zrobić oddzielny wektor do przechowywania stringów i oddzielny na inty liczace ile razy wystąpił dany string. Wtedy zatem to przestaje mieć sens, bo mamy std::map

0

Nie wiem dlaczego już drugi raz wspominacie o std::map. std::unordered_map jest duży lepszym pomysłem do tego zadania.

0
 void loadFile()
{
    fstream file;
    file.open( "dane.txt" , ios::in );
    if ( file.good() == false )
    {
        cout << "Plik nie istnieje" << endl;
    }
    assignment();
}
//==========================================================================================
void assignment()
{
    vector<string> words;
    int i = 0;
    while( getline(file , words) )
    {
        words.push_back();
        ++i;
    }
}

mam pytanie jak mam zrobić by plik wczytany w loadFile był widziany w assignment. Nie wiem jakiego argumentu mam użyć.

0

Takiego jaki zadeklarowałeś? o_O fstream? Najlepiej referencje więc fstream&

0

Zmodyfikowałem trochę program ale mam jakiś problem z map:

 #include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <fstream>
#include <cstdlib>
#include <cstddef>
#include <map>

using namespace std;

void openFile ( fstream& file );                                //zaladowanie pliku
vector<string> assignment ( fstream& file );                    //przypisanie
vector<string> checkingValues ( vector<string> finishWords );   //sprawdzanie slow
void countingOfWords ( vector<string> endChangesWords );        //zliczanie slow

int main()
{
    fstream file;
    openFile( file );
    vector<string> finishWords =  assignment( file );
    vector<string> endChangesWords = checkingValues( finishWords );
    countingOfWords( endChangesWords );

    return 0;
}

//==========================================================================================
void openFile( fstream& file )
{
    file.open( "dane.txt" , ios::in );
    if ( file.good() == false )
    {
        cout << "Plik nie istnieje" << endl;
    }
}
//==========================================================================================
vector<string> assignment( fstream& file )
{
    string line;
    vector<string> words;
    while( getline( file , line ) )
    {
        words.push_back(line);
    }
    return words;
}
//==========================================================================================
vector<string> checkingValues ( vector<string> finishWords )
{
    int start = 0 ;
    string wordWithVector;
    while ( start < finishWords.size() )
    {
        wordWithVector = finishWords[start];
        size_t found = wordWithVector.find_first_of("!@#$%^&*()_+|");
        if ( found != string::npos )
        {
            finishWords.erase(finishWords.begin()+start);
        }
        else
            start++;
    }
    return finishWords;
}
//========================================================================================
void countingOfWords ( vector<string> endChangesWords )
{
    map<string,vector<string>> countWords ( endChangesWords.begin() , endChangesWords.end() );
    cout << countWords << endl;
}
0

chodzi o zliczenie słów bez powtórzeń:
dane wejściowe np.
ara
ee
ff
gg
kk
ara
ara
ee
wynik:
miej więcej coś takiego nie wiem jaką formę ma map():
ara: 3
ee: 2
ff: 1
kk: 1

0
#include <iostream>
#include <string>
#include <fstream>
#include <map>
#include <iterator>
#include <algorithm>
using namespace std;

map <string, int> words;

bool openfile(fstream &f){

}
map <string, int>::iterator GetIter(string word)
{
    return words.find(word);
}

bool checkfile(fstream &f){
    string buff;
    while(!f.eof())
    {
        f >> buff;
        auto it = GetIter(buff);
        if(it != words.end())
        {
            ///twoje słowo istnieje, wystarczy dodać do wartosci int iteratora 1
        }
        else
        {
            ///twoje slowo nie istnieje, trzeba dodać nowy element
        }
    }
}

int main()
{

}

 
0

Przy pomocy książek i stron internetowych na razie udało mi się dojść do czegoś takiego ale nie działa.

map<string ,int> countWords;
    for (int i = 0 ; i < endChangesWords.size() ; ++i)
    {
        countWords.insert( make_pair( endChangesWords[i] , i ) );
    }
    typedef map<string,int>::const_iterator Iter;
    for (Iter p = countWords.begin(); p!=countWords.end();++p)
    {
        cout << p->first << ": " << p->second << endl;
    } 

Ale gdybym stosował coś takiego że nie korzystam z słów przechowywanych w kontenerze tylko bym je wpisywał z cin to by działało. Bo coś podobnego mam w książce. Ale nie mam pojęcia jak wykorzystać do tego vector.

0

Nie czytałeś nic o std::map co?

bool checkfile(fstream &f){
    string buff;
    while(!f.eof())
    {
        f >> buff;
        auto it = GetIter(buff);
        if(it != words.end())
        {
            ++words[buff];
        }
        else
        {
            words[buff] = 1;
        }
    }
} 
0

Wiecie co znalazłem na razie błąd przy wpisaniu słów do map

 map<string ,int> countWords;
    for (int i = 0 ; i < endChangesWords.size() ; ++i)
    {
      countWords.insert( std::pair<string,int>( endChangesWords[i] , i ) );
      cout << "to jest slowo w map" << &countWords << endl;

    }

wiem że zawsze mam ten sam adres czyli do map wpisałem tylko jedno słowo, pierwsze. I teraz rozchodzi mi sie o to że radzicie mi jak mam zrobić map z danych z pliku ale ja chce by te słowa były wczytanie z vectora i tu nie mam pojęcia jak to zrobić.

0

Nie jestem pewien czy zadziała bo nie sprawdzałem, ale coś z tego może wykminisz:

bool checkvector(vector<string> &v){
    for(auto &buff : v)
    {
        auto it = GetIter(buff);
        if(it != words.end())
        {
            ++words[buff];
        }
        else
        {
            words[buff] = 1;
        }
    }
} 
0

ok ale mam pytanie czy zmienną words wziąłeś z mojego programu czy to ma być zmienna bo wywala mi błąd że nie mam zadeklarowanej. Wydaje mi się ze to u mnie powinno być endChangesWords ale nie jestem pewien?
a GetIter ro trzeba dodać do include?? bo też nie mam zadeklarowanego.

0
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
#include <iterator>
using namespace std;

int main()
{
    vector<string> words{ "janek", "bazyl", "janek", "bazyl", "bazyl" };
    map<string, int> countWords;
    
    // użycie mapy ----------------------------------------------------------------
    for (auto const& elem : words) {
        auto status = countWords.insert(decltype(countWords)::value_type(elem, 1));
        if (!status.second) {
            ++status.first->second;
        }
    }

    for (auto const& item : countWords) {
        cout << item.first << "\t: " << item.second << '\n';
    }

    // użycie vectora -------------------------------------------------------------
    vector<string> vwords;
    vector<int> vcount;
    for (auto const& elem : words) {
        auto pos = find(vwords.begin(), vwords.end(), elem);
        if (pos == vwords.end()) {
            vwords.push_back(elem);
            vcount.push_back(1);
        }
        else {
            size_t dist = distance(vwords.begin(), pos);
            ++vcount[dist];
        }
    }
    
    for (size_t i = 0; i < vwords.size(); ++i) {
        cout << vwords[i] << "\t: " << vcount[i] << '\n';
    }
} 

Porównanie sposobów. Zamiast pliku jest vector.

0

dzięki wielkie carlosmay ale mam znowy ten sam problem:

 void countingOfWords ( vector<string> endChangesWords )
{
    map <string,int> countWords;
    for ( auto const& elem : endChangesWords)
    {
        auto status = countWords.insert(decltype(countWords)::value_type(elem, 1));
        if ( !status.second )
        {
            ++status.first->second;
        }
    }
    for ( auto const& item : countWords )
    {
        cout << item.first << " : " << item.second << endl;
    }
}

I dalej nie widzi endChangesWords??

0

Funkcja też ma niewłaściwą nazwę. Przepisuje zawartość vector'a do map'y.

void rewriteVectorToMap(){} 

lepiej pasuje.
Aaa... i wypisanie przenieś gdzieś indziej.

0
 void countingOfWords ( const vector<string>& endChangesWords )
{
    map <string,int> countWords;
    for ( auto const& elem : endChangesWords)
    {
        auto status = countWords.insert(decltype(countWords)::value_type(elem, 1));
        if ( !status.second )
        {
            ++status.first->second;
        }
    }
    for ( auto const& item : countWords )
    {
        cout << item.first << " : " << item.second << endl;
    }
}

mam coś dziwnego cała linijka

auto status = countWords.insert(decltype(countWords)::value_type(elem, 1)); 

Jest u mnie podkreślona na czerwono i jak najeżdżam na tą linie to dostaje coś takiego:

expected token )' got decltype'

0

zmieniłem na

auto status = countWords.insert(make_pair(elem, 1));
ale dalej mam coś takiego w wyniku:
ara : 1
: 3
: 1
: 2
: 1
: 1
: 1c
: 1

0

Wstaw do mojego kodu

vector<string> words{ "ara", "ee", "ff", "gg", "kk", "ara", "ara", "ee" }; 

i podmień decltype na make_pair.

0

Z tego co wyczytałem w komentarzu, program jest pisany w Qt?
Czemu nie wykorzystać Qt pisząc w Qt?

Prosty szybki przykład

#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QMap>
#include <QString>

int main(){
    QFile file("tekst.txt");
    file.open(QFile::ReadOnly);

    QTextStream stream(&file);
    QMap<QString, int> map;

    while(!stream.atEnd()){
        QString word;
        stream >> word;
        ++map[word];
    }

    foreach(const QString& key, map.keys()){
        qDebug() << map.value(key) << key;
    }

    file.close();

    return 0;
}

Dla pliku:

Witaj      swiecie
co u co co co sie popsulo.

Wynik:

1 "" 
1 "Witaj" 
4 "co" 
1 "popsulo." 
1 "sie" 
1 "swiecie" 
1 "u" 
0

FF nie korzystam z QT bo go nie umiem uczę się dopiero C++. carlosmay nie korzystam z words twojego bo musiałbym je wpisywać ręcznie a cały program polega na tym ze najpierw wczytuje dane z pliku potem dodaje je do vectora później kasuje słowa, a teraz chce zrobić map() które wykorzystuje te słowa z vectora i dlatego ich nie chce wpisywać. Może cały czas złe rozumiem?? Czy do map można dodawać słowa z kontenerów bo jeśli nie można to carlosmay wykorzystam twój drugi sposób.

0

Proponuje Qt niż "czysty" C++ jeśli chodzi o start, Qt ma bardziej "przystępne" biblioteki i łatwiej zrozumieć a dalej piszemy w C++, ale to jest tylko moja opinia.
W tradycyjnym C++ pisząc tak jak należy, czasami są takie zawiłości że głowa boli.

Cuś takiego?

#include <iostream>
#include <fstream>
#include <vector>
#include <map>

using namespace std;


vector<string> loadWords(fstream& file){
    string line;
    vector<string> words;
    while(file >> line)
        words.push_back(line);
    return words;
}

map<string, int> wordsToMap(vector<string>& words){
    map<string, int> wordMap;

#if __cplusplus > 199711L
    for(auto word: words)
        ++wordMap[word];
#else
    for(vector<string>::iterator word = words.begin(); word != words.end(); ++word)
        ++wordMap[*word];
#endif
    return wordMap;
}

int main(){
#if __cplusplus > 199711L
    cout << "Mam C++11!" << endl;
#else
    cout << "Nie mam c++11 :(" << endl;
#endif

    fstream file;
    file.open("tekst.txt");
    vector<string> words = loadWords(file);
    file.close();

    map<string, int> wordMap = wordsToMap(words);

#if __cplusplus > 199711L
    for(auto &it: wordMap)
        cout << it.second << " " << it.first << endl;
#else
    for(map<string, int>::iterator it = wordMap.begin(); it != wordMap.end(); ++it)
        cout << it->second << " " << it->first << endl;
#endif

    return 0;
}
0
void countingOfWords ( const vector<string>& endChangesWords )
{
    for ( int i = 0 ; i < endChangesWords.size() ; i++)
    {
        cout << "to sa słowa: " << endChangesWords[i] << endl;
    }
    map <string,int> countWords;
    for ( auto const& elem : endChangesWords)
    {
        auto status = countWords.insert(make_pair(elem, 1));
        if ( !status.second )
        {
            ++status.first->second;
        }
    }
    for ( auto const& item : countWords )
    {
        cout << item.first << " : " << item.second << endl;
    }
} 

carlosmay sprawdziłem

 for ( int i = 0 ; i < endChangesWords.size() ; i++)
    {
        cout << "to sa słowa: " << endChangesWords[i] << endl;
    }

czy są słowa są dostaje coś takiego:
to sa słowa: ara
to sa słowa: gg
to sa słowa: ee
to sa słowa: rr
to sa słowa: ee
to sa słowa: rrt
to sa słowa: ara
to sa słowa: ara
to sa słowa: rrewc
to sa słowa: dd
to sa słowa: ara
ara : 1
: 3
: 1
: 2
: 1
: 1
: 1c
: 1

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