c ++ перемешивает содержимое динамического массива? - PullRequest
0 голосов
/ 02 марта 2012

Эй, ребята, я пытаюсь перетасовать содержимое моего динамического массива, и он не работает. мне интересно, если у yall есть какие-либо советы или ссылки / ресурсы, которые могут мне помочь. я пытаюсь использовать std :: randomshuffle, но мой тест выдает 0 вместо правильных данных.

Songs *ptr;
ptr = new Songs[25];

ifstream fin;
fin.open("input.txt");

while (fin.good())                   //my input 
{
      getline(fin, song[num].title);    
      getline(fin, song[num].artist);
      fin >> song[num].mem;
      num++;
      fin>>ws;
}
fin.close();

и вот моя функция, я пытаюсь использовать случайное перемешивание

void shuffle (char choice, Songs song[], Songs *ptr, string title, string artist, int  mem, int num)
{
    if (choice == '4')
    {  
        std::random_shuffle(ptr, ptr + num);             //shuffle
    }
    for (int i = 0; i<num; i++)    //test
    {
        cout << ptr[i].title << ptr[i].artist << ptr[i].mem << endl;   
    }
}

Ответы [ 2 ]

3 голосов
/ 02 марта 2012

Никогда не используйте istream::good() или istream::eof() в качестве условия цикла.Он почти всегда генерирует код с ошибками (как в данном случае.)

Попробуйте:

while (std::getline(fin, song[num].title) &&
       std::getline(fin, song[num].artist) &&
       fin >> song[num].mem) 
{
      num++;
      fin>>ws;
}

Как указывает вонючий, ваш случайный порядок правилен, хотя и ужасен.Попробуйте:

void shuffle (char choice, Songs *ptr, int num)
{
    if (choice == '4')
    {  
        std::random_shuffle(ptr, ptr + num);             //shuffle
    }
    for (int i = 0; i<num; i++)    //test
    {
        std::cout << ptr[i].title << ptr[i].artist << ptr[i].mem << "\n";   
    }
}
2 голосов
/ 02 марта 2012

Пожалуйста, примите во внимание следующее, это более современный подход C ++ к вашей проблеме.Вы создаете оператор потока, поэтому вам не нужно анализировать объект вручную каждый раз, когда вы хотите прочитать.

#include <algorithm>
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>

struct song {
        std::string title, artist;
        int mem;
};

std::ostream& operator<<(std::ostream& os, const song& s) {
        return os << s.title << "\t" << s.artist << "\t" << s.mem;
}

std::istream& operator>>(std::istream& is, song& s) {
        std::getline(is, s.title);
        std::getline(is, s.artist);
        return is >> s.mem;
}

int main()
{
        std::ifstream file("input.txt"); 

        if(!file.is_open()) return 1;

        std::vector<song> songs((std::istream_iterator<song>(file)),
                                 std::istream_iterator<song>());
        std::random_shuffle(songs.begin(), songs.end());

        std::copy(songs.begin(), songs.end(), 
                  std::ostream_iterator<song>(std::cout, "\n"));
        return 0;
}

компилируется, но НЕ ПРОВЕРЯЕТСЯ НА ФОРМАТЕ ФАЙЛА

без вектора (НО ПОЖАЛУЙСТАУЗНАЙТЕ ИХ) это:

       std::vector<song> songs((std::istream_iterator<song>(file)),
                                 std::istream_iterator<song>());

можно записать как:

 const size_t sz=20;
 song songs[sz];
 for(unsigned i=0; i!=sz && file; ++i)
     file >> songs[i];

, а остальная часть вызова функции будет работать как

std::random_shuffle(songs, songs+sz);

, но серьезно учитесьвекторы сейчас (а затем и другие контейнеры).Массив в основном считается устаревшим для вашей задачи, примером чего является то, что если у вас более 20 элементов в файле, вы получите переполнение буфера и произойдет плохая вещь.

http://en.cppreference.com/w/cpp/container/vector

Также вам не нужно явно открывать и закрывать файлы (в большинстве случаев вы, скорее всего, будете вводить ошибки) из-за RAII:

http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization

...