C++ problem z zapisem słownika do pliku tekstowego

Witam,

Chciałem napisać program, który zrobi słownik(7-znakowy, który jakby co mógłbym rozszerzyć). Słownik ma być zapisany do jakiegoś pliku *.txt. Niestety nie wiem co nie działa, gdyż ten temat jest dla mnie nowy. Niektóre informacje znalazłem w internecie, ale nie wiem jak je skleić. Czy możecie pomóc :o ? Oto kod:

#include 

#include 

#include 

#include 


using namespace std;

int main()

{

    string nazwap, co;

    cout << "7-literowy slownik: podaj nazwe i rozszerzenie np. plik.txt :";

    cin >> nazwap;

    ofstream plik( nazwap.c_str() );

    char litera[63] = { "qwertyuioplkjhgfdsazxcvbnm1234567890QAZWSXEDCRFVTGBYHNUJMIKOLP" };

    for( int z = 0, x = 0, c = 0, v = 0, b = 0, n = 0, m = 0; z < 63; m++ )

    {

        co = "";

        cout << litera[z] << litera[x] << litera[c] << litera[v] << litera[b] << litera[n] << litera[m] << endl;

        co = litera[z] + litera[x] + litera[c] + litera[v] + litera[b] + litera[n] + litera[m];

        cin.ignore();

        getline( cin, nazwap );

        plik << nazwap;

        plik.close();

        if( m == 63 ) n++, m = 0;


        if( n == 64 ) b++, n = 0;


        if( b == 64 ) v++, b = 0;


        if( v == 64 ) c++, v = 0;


        if( c == 64 ) x++, c = 0;


        if( x == 64 ) z++, x = 0;


        if( z == 64 ) goto aaa;


    }

    aaa:

    return 0;

}

Z góry dziękuję za pomoc :lol:

  1. Usuń goto i zamiast tego używaj break

  2. W ogóle zamień to wszystko na 6 pętli for jedna w drugiej (będziesz mógł wywalić break)

  3. Do czego służy string co?

  4. Czemu w pętli wczytujesz coś do nazwap?

  5. Czemu w pętli zamykasz plik?

  6. Dodawanie znaków do siebie nie działa tak jak ci się wydaje. Operator + jest przeciążony dla std::string http://en.cppreference.com/w/cpp/string/basic_string/operator%2B. Dodawanie char’ów do siebie działa tak jak dodawanie liczb (znaki w kodowaniu ASCII mają swoje liczbowe reprezentacje; np

Dziękuję za cenne uwagi, zmienię to na 6 funkcji, oraz char na string. Odnośnie punktów 3), 4) oraz 5)- coś podobnego do tego, co zamieściłem w programie znalazłem w internecie. Niestety nie znalazłem opisu, nie wiem jak to dokładnie działa i właśnie to jest moim problemem. Jak użyć tego w moim programie?

Właśnie tak sobie pomyślałem i doszedłem do wniosku, że jednak nie chcesz pisać tego programu. Chcesz wygenerować wszystkie siedmioznakowe słowa jakie można poukładać ze znaków, które masz w tablicy “litera”. Tych słów jest 2198804731200. Każde zajmuje 7 znaków + znak końca linii, co daje 8 bajtów na słowo. Razem będzie 17590437849600 bajtów, czyli około 15 terabajtów.

A tu masz jak to powinno wyglądać:

#include 

#include 

int main()

{

    const std::string litery("qwertyuioplkjhgfdsazxcvbnm1234567890QAZWSXEDCRFVTGBYHNUJMIKOLP");

    std::ofstream plik("bla.txt");


    for (std::string::const_iterator a = litery.begin(); a != litery.end(); ++a)

        for (std::string::const_iterator b = litery.begin(); b != litery.end(); ++b)

            for (std::string::const_iterator c = litery.begin(); c != litery.end(); ++c)

                for (std::string::const_iterator d = litery.begin(); d != litery.end(); ++d)

                    for (std::string::const_iterator e = litery.begin(); e != litery.end(); ++e)

                        for (std::string::const_iterator f = litery.begin(); f != litery.end(); ++f)

                            for (std::string::const_iterator g = litery.begin(); g != litery.end(); ++g)

                                plik << *a << *b << *c << *d << *e << *f << *g << std::endl;

    return 0;

}

Rzeczywiście, dziękuję, że mi to uświadomiłeś. Potrzebnaby była duża moc obliczeniowa oraz kilka dysków po kilka tera. Ale kod mogę wykorzystać do (dużo) mniejszego słownika.

Także dziękuję i pozdrawiam :slight_smile:

etam, a dla długości 15 i liter “01” będzie 15 zagnieżdżonych pętli ?

to samo ale rozsądnie, dowolny zestaw liter oraz dowolna długość słowa - zmieniasz tylko dwie stałe na początku:

#include 

using namespace std;


int main()

  {

   const unsigned size=4; // długość słowa

   const char litery[]="ABCD"; // dostępne litery

   const unsigned count=sizeof(litery)-1; // ile tych liter, ewentualnie =strlen(litery);

   unsigned char var[size]={0}; // zerujemy

   for(unsigned p=0;p<=size;)

     {

      for(unsigned i=0;i
      cout<

      for(p=size;(p--)&&(++var[p]>=count);) var[p]=0; // generujemy następne słowo

     }

   cin.sync(); cin.get();

   return 0;

  }

Ilość słów = (ilość dostępnych liter)^(długość słowa);

exty32 , proszę zapoznaj się z tą stroną oraz tym tematem, a następnie,używając przycisku image.php?album_id=20&image_id=4038

Rzeczywiście, dziękuję, że mi to uświadomiłeś. Potrzebnaby była duża moc obliczeniowa oraz kilka dysków po kilka tera. Ale kod mogę wykorzystać do (dużo) mniejszego słownika.

Także dziękuję i pozdrawiam :slight_smile:

C++11

#include 

#include 


void

println(std::ostream& strm)

{

    strm << std::endl;

}


template 

void

println(std::ostream& strm, T&& v, Ts&&... vs)

{

    strm << std::forward(v);

    println(strm, std::forward(vs)...);

}



template 

typename std::enable_if<(N==0), void>::type

generate(std::ostream& strm, const std::string&, Ts&&... vs)

{

    println(strm, std::forward(vs)...);

}


template 

typename std::enable_if<(N>0), void>::type

generate(std::ostream& strm, const std::string& chars, Ts&&... vs)

{

    for (char c : chars)

        generate(strm, chars, std::forward(vs)..., c);

}



int main()

{

    const std::string chars("01");

    generate<15>(std::cout, chars);

    return 0;

}

To ma być lepsze, prostsze czy krótsze od tego co ja podałem? Może ma jakąś inną zaletę?

Miało być tak samo dobre jak to co podałem wcześniej. Zrobiłem testy wydajnościowe i jednak się okazało, że twoja wersja jest nieznacznie szybsza. Zrobiłem jeszcze jedną wersję, którą na początku chciałem uniknąć myśląc że będzie gorsza, a jednak okazała się lepsza od wszystkich.

#include 

#include 


template 

typename std::enable_if<(N==0), void>::type

generate(std::ostream& strm, const std::string&, const std::string& str)

{

    strm << str << std::endl;

}


template 

typename std::enable_if<(N>0), void>::type

generate(std::ostream& strm, const std::string& chars, const std::string str = "")

{

    for (char c : chars)

        generate(strm, chars, str + c);

}


int main()

{

    const std::string chars("0123456789");

    generate<8>(std::cout, chars);

    return 0;

}

gcc (SUSE Linux) 4.7.1 20120723 [gcc-4_7-branch revision 189773] procesor: i5 460MKompilacja: “g++ -std=c++11 -O2 -march=native” Wynik działania programów przekierowałem do /dev/null żeby uniknąć opóźnień związanych z dyskiem lub terminalem. litery = “01” długość słowa = 25 moja poprzednia wersja:

29.53user 2.79system 0:32.36elapsed 99%CPU (0avgtext+0avgdata 4864maxresident)k

0inputs+0outputs (0major+364minor)pagefaults 0swaps

twoja wersja:

26.61user 2.83system 0:29.49elapsed 99%CPU (0avgtext+0avgdata 4752maxresident)k

0inputs+0outputs (0major+357minor)pagefaults 0swaps

moja ostatnia wersja:

11.38user 2.84system 0:14.24elapsed 99%CPU (0avgtext+0avgdata 4896maxresident)k

0inputs+0outputs (0major+366minor)pagefaults 0swaps

litery = “0123456789” długość słowa = 8 moja poprzednia wersja:

27.75user 8.28system 0:36.08elapsed 99%CPU (0avgtext+0avgdata 4864maxresident)k

0inputs+0outputs (0major+364minor)pagefaults 0swaps

twoja wersja:

27.76user 8.48system 0:36.29elapsed 99%CPU (0avgtext+0avgdata 4752maxresident)k

0inputs+0outputs (0major+357minor)pagefaults 0swaps

moja ostatnia wersja:

22.40user 8.28system 0:30.72elapsed 99%CPU (0avgtext+0avgdata 4880maxresident)k

0inputs+0outputs (0major+365minor)pagefaults 0swaps
#include 

using namespace std;


int main()

  {

   const unsigned size=4; // długość słowa

   const char litery[]="ABCD"; // dostępne litery

   const unsigned count=sizeof(litery)-1; // ile tych liter, ewentualnie =strlen(litery);

   unsigned var[size]={0}; // zerujemy

   const char napis[size+1]={0};

   for(unsigned p=0;p<=size;)

     {

      for(unsigned i=0;i
      cout<

      for(p=size;(p--)&&(++var[p]>=count);) var[p]=0; // generujemy następne słowo

     }

   cin.sync(); cin.get();

   return 0;

  }

I po sprawie :stuck_out_tongue_winking_eye:

#include 

#include 

#include 


namespace detail

{


    template 

    typename std::enable_if<(I==N), void>::type

    generate(std::ostream& strm, const std::string&, const std::array& str)

    {

        strm << str.data() << std::endl;

    }


    template 

    typename std::enable_if<(I::type

    generate(std::ostream& strm, const std::string& chars, std::array& str)

    {

        for (char c : chars) {

            str[I] = c;

            generate(strm, chars, str);

        }

    }


} // namespace detail


template 

void

generate(std::ostream& strm, const std::string& chars)

{

    std::array str{{0}};

    detail::generate(strm, chars, str);

}


int main()

{

    const std::string chars("01");

    generate<26>(std::cout, chars);

    return 0;

}

Testy: Warunki podobne do poprzednich. Tym razem jeszcze przełączyłem się na init 3 oraz ustawiłem procesor w tryb performance. litery = “01” długość słowa = 26 mój

7.48user 5.55system 0:13.04elapsed 99%CPU (0avgtext+0avgdata 4848maxresident)k

0inputs+0outputs (0major+363minor)pagefaults 0swaps

twój

9.19user 5.69system 0:14.89elapsed 99%CPU (0avgtext+0avgdata 4768maxresident)k

0inputs+0outputs (0major+358minor)pagefaults 0swaps

litery = “0123456789” długość słowa = 8 mój:

9.51user 8.27system 0:17.79elapsed 99%CPU (0avgtext+0avgdata 4848maxresident)k

0inputs+0outputs (0major+363minor)pagefaults 0swaps

twój:

10.28user 8.14system 0:18.44elapsed 99%CPU (0avgtext+0avgdata 4752maxresident)k

0inputs+0outputs (0major+358minor)pagefaults 0swaps

:smiley:

#include 


int main()

  {

   const unsigned size=4; // długość słowa

   const char litery[]="ABCD"; // dostępne litery

   const unsigned count=sizeof(litery)-1; // ile tych liter, ewentualnie =strlen(litery);

   unsigned var[size]={0}; // zerujemy

   const char napis[size+1]={0};

   for(unsigned p=0;p<=size;)

     {

      for(unsigned i=0;i
      puts(napis);


      for(p=size;(p--)&&(++var[p]>=count);) var[p]=0; // generujemy następne słowo

     }

   return 0;

  }

I po sprawie :stuck_out_tongue_winking_eye:

Miałem nadzieję, że do tego nie dojdzie. Ale skoro już wszedłeś ta to pole, to mam dla ciebie złą wiadomość: ja nadal wygrywam :smiley:

#include 

#include 

#include 


namespace detail

{


    template 

    typename std::enable_if<(I==N), void>::type

    generate(std::ostream& strm, const std::string&, const std::array& str)

    {

        strm.write(str.data(), N+1);

    }


    template 

    typename std::enable_if<(I::type

    generate(std::ostream& strm, const std::string& chars, std::array& str)

    {

        for (char c : chars) {

            str[I] = c;

            generate(strm, chars, str);

        }

    }


} // namespace detail


template 

void

generate(std::ostream& strm, const std::string& chars)

{

    std::array str;

    str[N] = '\n';

    detail::generate(strm, chars, str);

}


int main()

{

    std::ios_base::sync_with_stdio(false);

    const std::string chars("01");

    generate<3>(std::cout, chars);

    return 0;

}

Warunki testowe takie same jak poprzednio. Twój program skompilowany poleceniem gcc -std=c99 -O2 -march=native litery = “01” długość słowa = 30 mój program:

34.83user 0.57system 0:35.42elapsed 99%CPU (0avgtext+0avgdata 4880maxresident)k

0inputs+0outputs (0major+366minor)pagefaults 0swaps

twój program:

82.23user 0.70system 1:22.99elapsed 99%CPU (0avgtext+0avgdata 1824maxresident)k

0inputs+0outputs (0major+155minor)pagefaults 0swaps

litery = “0123456789abc” długość słowa = 8 mój program:

20.79user 0.13system 0:20.94elapsed 99%CPU (0avgtext+0avgdata 4864maxresident)k

0inputs+0outputs (0major+365minor)pagefaults 0swaps

twój program:

27.62user 0.16system 0:27.80elapsed 99%CPU (0avgtext+0avgdata 1808maxresident)k

0inputs+0outputs (0major+153minor)pagefaults 0swaps

PS: Usuń const spod tablicy napis i zamień “const unsigned size=4;” na “#define size 4”.

#include 


#define size 8 // długość słowa

const char litery[]="01"; // dostępne litery = pierwsza dostępna litera

const char *end_litery=litery+sizeof(litery)-1; // ostatnia dostępna litera

const char *var[size+1];

const char **end_var=var+size;

const char cr='\n';


int main()

  {

   const char **p=var;

   while(p
   *p=&cr;

   while(p>=var)

     {

      p=var; while(p<=end_var) putchar(**(p++));


      --p; while(((p--)>=var)&&(++*p>=end_litery)) *p=litery;

     }

   return 0;

  }

Powodzenia. :stuck_out_tongue_winking_eye:

Czy to już jest konkurs na to, kto bardziej zaciemni kod?

Uruchomiłem ten program na teście, który twój poprzedni przechodził w 1:23, ale przerwałem po 3 minutach, bo nie chciało mi się czekać.

A piosenka fajna :slight_smile:

Pewnie coś zchrzaniłeś przy adaptacji. U mnie działa dwa razy szybciej niż poprzedni.

Nic nie zmieniłem (z wyjątkiem danych wejściowych i formatowania). To nie ma prawa działać szybciej. Zrobiłeś tablicę wskaźników do char. Masz p, który jest wskaźnikiem do wskaźnika, a podwójna dereferencja jest cholernie kosztowną operacją. Masz wypisywanie znak po znaku, mimo że już na samym początku wyszło, że szybciej jest wypisać gotowy string.

Twój program po moich adaptacjach:

#include 


#if 1

    #define size 30

    const char litery[] = "01"; // dostępne litery

#else

    #define size 8

    const char litery[] = "0123456789abc"; // dostępne litery

#endif


const char *end_litery=litery+sizeof(litery)-1; // ostatnia dostępna litera

const char *var[size+1];

const char **end_var=var+size;

const char cr='\n';


int

main()

{

    const char **p = var;

    while(p < end_var)

        *(p++) = litery;

    *p = &cr;

    while (p >= var) {

        p = var;

        while (p <= end_var)

            putchar(**(p++));


        --p;

        while (((p--) >= var) && (++*p >= end_litery))

            *p=litery;

    }

    return 0;

}

znaki “01”, długość 30

299.17user 0.79system 5:00.13elapsed 99%CPU (0avgtext+0avgdata 1792maxresident)k

0inputs+0outputs (0major+152minor)pagefaults 0swaps

znaki “0123456789abc”, długość 8

65.34user 0.16system 1:05.54elapsed 99%CPU (0avgtext+0avgdata 1792maxresident)k

0inputs+0outputs (0major+152minor)pagefaults 0swaps

U mnie pod linuksem też dłużej zadziałało niż poprzednia wersja, pewnie przez dużą ilość wywołań putchar, więc wracam do puts:

#include 


#if 1

    #define size 30

    const char litery[] = "01"; // dostępne litery

#else

    #define size 8

    const char litery[] = "0123456789abc"; // dostępne litery

#endif


const char *end_litery=litery+sizeof(litery)-1; // ostatnia dostępna litera

const char *var[size];

const char **end_var=var+size;


int main()

  {

   char napis[size+1]={0},first=*litery,*i=napis;

   const char **p=var;

   while(p
   p=var;

   while(true)

     {

      memset(i,first,end_var-p);

      puts(napis);

      p=end_var;

      while(((--p)>=var)&&(++*p>=end_litery)) *p=litery;

      if(p
      i=napis+(p-var);

      *(i++)=**(p++);

     }

   return 0;

  }[/code]