Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Usuwanie duplikatów z pliku tekstowego

Ostatnio zmodyfikowano 2013-04-14 11:27
Autor Wiadomość
wojownik266
Temat założony przez niniejszego użytkownika
[C++] Usuwanie duplikatów z pliku tekstowego
» 2013-04-13 10:36:13
Witam. Napisałem sobie taki program do usuwania duplikatów z pliku tekstowego, którego kod zamieszczam poniżej. Program w 95% działa zgodnie z moimi oczekiwaniami. Problemem jest to że gdy w pliku mam np: taki tekst "ala,ala,ala,ala" to algorytm usuwa tylko dwa pierwsze powtórzenia pozostawiając resztę bez zmian. Czy ktoś mógłby podpowiedzieć co zrobić aby program pozostawiał tylko jeno słowo a resztę usuwał?

C/C++
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

void usun_znak( vector < string > * slowa, string filtr )
{
    vector < string >::iterator iter = slowa->begin();
    vector < string >::iterator iter_koniec = slowa->end();
    if( !filtr.size() )
         filtr.insert( 0, "\".,:;!?)(\\/" );
   
    while( iter != iter_koniec ) {
        string::size_type poz = 0;
        while(( poz =( * iter ).find_first_of( filtr, poz ) ) != string::npos )
            ( * iter ).erase( poz, 1 );
       
        iter++;
    }
}
int main()
{
    string nazwaPliku, efilter;
    cout << "Podaj nazwe pliku do otwarcia: ";
    cin >> nazwaPliku;
    ifstream plikwe( nazwaPliku.c_str() );
    if( !plikwe )
    {
        cerr << "Blad otwarcia pliku\n";
        return - 1;
    }
   
    string tmp;
    vector < string > tekst;
    while( plikwe >> tmp )
    {
        tekst.push_back( tmp );
    }
   
    cout << "Przed usunieciem duplikatow\n";
    for( int i = 0; i < tekst.size(); ++i )
    {
        cout << tekst[ i ] << "\n";
    }
    // najpierw sortujemy slowa, bo algorytm unique "usuwa" tylko
    // slowa lezace obok siebie
    sort( tekst.begin(), tekst.end() );
    // algorytm unique przenosi duplikaty na koniec, i zwraca nowy logiczny
    // koniec. Aby usunac calkowicie z kontenera duplikaty
    // stosujemy metode erase.
    tekst.erase( unique( tekst.begin(), tekst.end() ), tekst.end() );
    usun_znak( & tekst, efilter );
    cout << "Po usunieciu duplikatow\n";
    for( int i = 0; i < tekst.size(); ++i )
    {
        cout << tekst[ i ] << "\n";
    }
   
    cout << "Podaj nazwe pliku do ktorego zapisac\n";
    cin >> nazwaPliku;
    ofstream plikwy( nazwaPliku.c_str() );
   
    for( int i = 0; i < tekst.size(); ++i )
    {
        plikwy << tekst[ i ] << "\n";
    }
   
    cin.get();
    return 0;
}
 
P-80500
DejaVu
» 2013-04-13 12:33:34
Jeżeli dane sortujesz to wystarczy, że je wrzucisz do std::set<std::string>, a następnie wypiszesz zawartość tego kontenera. Duplikaty same zostaną usunięte.
P-80503
wojownik266
Temat założony przez niniejszego użytkownika
» 2013-04-13 17:53:36
Wszystko jest tak jak mówisz tylko mam mały problem z tą funkcją:
C/C++
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <fstream>
using namespace std;

void usun_znak( set < string > * slowa, string filtr )
{
    set < string >::iterator iter = slowa->begin();
    set < string >::iterator iter_koniec = slowa->end();
    if( !filtr.size() )
         filtr.insert( 0, "\".,:;!?)(\\/" );
   
    while( iter != iter_koniec ) {
        string::size_type poz = 0;
        while(( poz = iter->find_first_of( filtr, poz ) ) != string::npos )
             iter->erase(( slowa->begin(), slowa->end() ), poz );
       
        iter++;
    }
}

int main()
{
    set < string > call;
    set < string >::iterator it;
    string efilter, plik;
    ifstream in( "plik.txt" );
    ofstream out( "words.txt" );
    while( in >> plik )
         call.insert( plik );
   
    usun_znak( & call, efilter );
    for( it = call.begin(); it != call.end(); ++it ) {
        cout <<* it << endl;
        out <<* it << endl;
    }
    cin.get();
    return 0;
}
Jak sprawić aby usuwała znaki interpunkcyjne?
P-80514
DejaVu
» 2013-04-13 19:42:17
To nie rola kontenera std::set. std::set przechowuje unikatowe wartości. Ty decydujesz 'czym' ten kontener 'karmisz'.
P-80518
wojownik266
Temat założony przez niniejszego użytkownika
» 2013-04-13 20:30:19
Trochę tak pokracznie się wyraziłem. Chodzi mi o to że przy probie kompilacji powyższego programu otrzymuję komunikat, jak niżej z którym nie mogę sobie poradzić!?

D:\CodeBlock\CodeBlock_Projekty\Usuwanie znakow przestankowych z tekstu\usowanie_znakow_przestankowych.cpp|17|error: passing 'const std::basic_string<char, std::char_traits<char>, std::allocator<char> >' as 'this' argument of 'std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::erase(typename _Alloc::rebind<_CharT>::other::size_type, typename _Alloc::rebind<_CharT>::other::size_type) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]' discards qualifiers|
 
P-80523
pekfos
» 2013-04-13 21:16:00
z którym nie mogę sobie poradzić!?
Też się dziwię, że nie możesz sobie poradzić. Nie można modyfikować elementów std::set. Chyba nawet nie próbowałeś zrozumieć komunikatu błędu.
passing 'const [..] as 'this' argument of [..] erase [..] discards qualifiers|
P-80527
wojownik266
Temat założony przez niniejszego użytkownika
» 2013-04-14 11:27:49
No teraz to już wszystko jasne i proste. Gdyby nie Twoja podpowiedź to w dalszym ciągu wyważałbym otwarte drzwi. Zmodyfikowana i poprawiona wersja programu do usuwania znaków przestankowych i powtarzających się słów, ma się tak jak poniżej (gotowiec). Na zakończenie prosiłbym o rzuceniem okiem na ten program i powiedzenie mi czy jest dobrze napisany a jak nie to dlaczego i co by można jeszcze usprawnić?

C/C++
#include <iostream>
#include <set>
#include <vector>
#include <string>
#include <fstream>
#include <algorithm>
using namespace std;

void usun_znak( vector < string > * slowa, string filtr )
{
    vector < string >::iterator iter = slowa->begin();
    vector < string >::iterator iter_koniec = slowa->end();
    if( !filtr.size() )
         filtr.insert( 0, "\".,:;!?0123456789)(\\/" );
   
    while( iter != iter_koniec ) {
        string::size_type poz = 0;
        while(( poz =( * iter ).find_first_of( filtr, poz ) ) != string::npos )
            ( * iter ).erase( poz, 1 );
       
        iter++;
    }
}
int main()
{
    string tmp, plik, efilter;
    ifstream in( "plik.txt" );
    ofstream out( "word.txt" );
   
    vector < string > zn;
    set < string > call;
    set < string >::iterator it;
   
    while( in >> tmp )
    {
        zn.push_back( tmp );
        usun_znak( & zn, efilter );
        call.insert( zn.begin(), zn.end() );
    }
    for( it = call.begin(); it != call.end(); ++it ) {
       
        cout <<* it << endl;
        out <<* it << endl;
       
    }
    cin.get();
    return 0;
}
 
P-80541
« 1 »
  Strona 1 z 1