2014-09-07 3 views
0

У меня есть задание Я работаю над тем, что я натолкнулся на следующую ошибку и не могу исправить. Может кто-нибудь объяснить эту ошибку и дать возможные решения для ее устранения? Последняя ночь кода - это ошибка. Любое понимание было бы оценено.Невозможно преобразовать карту <строка, класс> Значение в присваивании

81:43: ошибка: не удается преобразовать 'альбом' в 'станд :: карта, альбом *> :: mapped_type {ака альбом *}' в назначении

class song { 
    public: 
     string title; 
     int time; 
     int track; 

}; 

class album{ 
    public: 
     map <int, song *> songs; 
     string name; 
     int time; 
}; 

class artist{ 
    public: 
     map <string, album *> albums; 
     string name; 
     int time; 
     int nsongs; 
}; 

int main (int argc, char* argv[]){ 
    song song; 
    album album; 
    artist artist; 
    const string file = argv[1]; 
    ifstream infile; 
    infile.open(file.c_str()); 
    int itime; 
    int secs, mins, hours; 
    char extra; 
    string stitle, stime, sartist, salbum, sgenre, strack; 
    stringstream ss; 

    if(infile.fail()){ 
     cerr << "Could not open file" << endl; 
     exit (1); 
    } 

    while (infile >> stitle >> stime >> sartist >> salbum >> sgenre >> strack){ 
     replace(stitle.begin(), stitle.end(), '_', ' '); 
     song.title = stitle; 
     ss << stime; 
     ss >> mins >> extra >> secs; 
     itime = (mins * 60) + secs; 
     ss.str(""); 
     ss.clear(); 
     mins = itime/60; 
     secs = itime%60; 
     song.time = itime; 

     song.track = atoi (strack.c_str()); 
     replace(salbum.begin(), salbum.end(), '_', ' '); 
     album.name = salbum; 

     replace(sartist.begin(), sartist.end(), '_', ' '); 
     artist.name = sartist; 
     if(artist.albums.count(artist.name) == 1){ 
      cout << "Old Artist: " << artist.name << endl; 
      cout << "New Artist: " << artist.name << endl; 
     } 
     else{artist.albums[artist.name] = album;} 
+0

Поскольку я не вижу наследования между объектами, вы не используете ссылки в картах вместо указателей? Тогда у вас не будет проблем с распределением памяти, и вы можете удалить указатели с карт (и код должен работать) – JosiP

+0

Просто предупреждение. переменные с тем же идентификатором, что и типы, являются ** плохой идеей. Такие вещи, как «альбом альбома» и «песня», и «художник-художник», делают предстоящий код трудным для чтения и чрезвычайно подвержены тонким ошибкам. – WhozCraig

+0

Да, я планирую изменить имена переменных. –

ответ

0

Вы пытаетесь присвоить «альбом» объект указатель типа «альбом», если у вас есть действительный указатель на выделенную память, вы могли бы написать что-то вроде

else{*(artist.albums[artist.name]) = album;} 

, так как я не вижу никакого выделения памяти для указателя вы должны сами распределять память, прежде чем вставлять материал в карту, например

else{artist.albums[artist.name] = new album();} 

и помню, чтобы освободить эту память в конце вашей программы

+0

Я думаю, что если ОП действительно настаивает на использовании указателей (что, вероятно, ему или нет), тогда может быть желательно, что 'std :: shared_ptr' может быть желательным, так что сами классы все еще могут использоваться как типы значений. То есть 'std :: map >' и так далее. Но все же, это не похоже на то, что здесь нужны указатели. –

+0

Я согласен с общими указателями, но это может быть вторым шагом. Понимание проблемы ОП - это первый шаг. –

+0

Возможно, на фоне его вопроса есть необоснованный страх перед проблемами производительности, когда не используются указатели, или фон Java, где все, кроме примитивов, является указателем. –

0

Там нет никаких видимых причин, чтобы использовать указатели. Просто напишите:

class song { 
    public: 
     string title; 
     int time; 
     int track; 

}; 

class album{ 
    public: 
     map <int, song> songs; 
     string name; 
     int time; 
}; 

class artist{ 
    public: 
     map <string, album> albums; 
     string name; 
     int time; 
     int nsongs; 
}; 

song, albumartist) все похожи значение классов. Это означает, что отдельные объекты не имеют идентичности, а объекты могут сравниваться для равенства. Такие классы обычно не используются с указателями.

std::string сам по себе является другим (очень типичным) примером класса значений. Обычно вы не храните указатели на строки или не передаете или не возвращаете указатели строк. Вы редко увидите что-то вроде std::map<int, std::string*>, std::list<std::string*>, f(std::string* s) или std::string* f().

Фактически, int сам по себе является типом значения. Есть причина, почему что-то вроде std::map<int, int*>, std::list<int*>, f(int* i) или int* f() выглядит подозрительно.

Что касается вашего кода, песни, альбомы и исполнители похожи на строки и ints.


Есть несколько других проблем с кодом, кстати:

int itime; 

Это выглядит как Microsoft в стиле венгерской нотации, который я хотел бы назвать неудачным экспериментом с 90-х годов. Просто вызовите переменную time.

string stitle, stime, sartist, salbum, sgenre, strack; 

То же самое здесь. Если вам нужны две переменные одного и того же имени с разными типами (что не должно происходить очень часто), будьте откровенны в этом и назовите их что-то вроде time_as_integer и time_as_string.

while (infile >> stitle >> stime >> sartist >> salbum >> sgenre >> strack) 

Что это будет цикл делать, если один из титулов, случается «Пусть это будет»? Вам нужен более надежный механизм.Прочитайте целые строки с помощью std::getline и используйте что-то вроде Boost Tokenizer, чтобы разделить их.

atoi (strack.c_str()); 

atoi не может различать "0" и недопустимого ввода, как "" или "a". Он вернет 0 в любом случае. Используйте строковые потоки или C++ 11 stoi.


P.S .: Пожалуйста, напишите компилируемый код. Для того, чтобы воспроизвести вашу ошибку, необходимо вручную добавить все следующие, что очень утомительно:

#include <string> 
#include <fstream> 
#include <map> 
#include <sstream> 
#include <iostream> 
#include <stdlib.h> 
#include <algorithm> 

using namespace std; // just for throwaway test code 

Вы также должны добавить

} 
} 

в конце кода.

Даже с этими изменениями ваш код не достигает 81 строки.

+0

Могу ли я попросить нисходящего объяснить, что случилось с этим ответом? –

+0

Спасибо за советы. Строковая часть файла (те, которые он тестирует) - это все действительные числа. Мой профессор дает нам тестовые файлы раньше времени, чтобы проверить себя с ними, прежде чем включать их. Я, вероятно, в конечном итоге использую getline, но все заголовки с несколькими словами разделяются «_» между словами, а не пробелами. Спасибо за все комментарии. Это был мой первый вопрос, поэтому я ценю полезную обратную связь. –

Смежные вопросы