Функтор сравнения строк STL - PullRequest
0 голосов
/ 16 июня 2009

У меня есть следующий функтор:

class ComparatorClass {
  public:
    bool operator () (SimulatedDiskFile * file_1, SimulatedDiskFile * file_2) {
      string file_1_name = file_1->getFileName();
      string file_2_name = file_2->getFileName();

      cout << file_1_name << " and " << file_2_name << ": ";

      if (file_1_name < file_2_name) {
        cout << "true" << endl;
        return true;
      }
      else {
        cout << "false" << endl;
        return false;
      }
    }
};

Предполагается, что это строгий слабый порядок, и он такой длинный (может быть только одной строкой) для целей отладки.

Я использую этот функтор как функтор сравнения для stl :: set. Проблема в том, что он вставляет только первый элемент. Добавив вывод консоли в функцию компаратора, я узнал, что она фактически сравнивает имя файла с самим собой каждый раз .

Другие соответствующие строки:

typedef set<SimulatedDiskFile *, ComparatorClass> FileSet;

и

// (FileSet files_;) <- SimulatedDisk private class member
void SimulatedDisk::addFile(SimulatedDiskFile * file) {
  files_.insert(file);
  positions_calculated_ = false;
}

РЕДАКТИРОВАТЬ: код, который вызывает .addFile ():

current_request = all_requests.begin();
while (current_request != all_requests.end()) {
  SimulatedDiskFile temp_file(current_request->getFileName(), current_request->getResponseSize());
  disk.addFile(&temp_file);
  current_request++;
}

Где all_requests - это список, а класс Request таков:

class Request {
  private:
    string file_name_;
    int response_code_;
    int response_size_;

  public:
    void setFileName(string file_name);
    string getFileName();
    void setResponseCode(int response_code);
    int getResponseCode();
    void setResponseSize(int response_size);
    int getResponseSize();
};

Хотел бы я предложить свой гипотезу о том, что происходит, но на самом деле я понятия не имею. Заранее спасибо за любые указатели.

Ответы [ 4 ]

5 голосов
/ 16 июня 2009

Нет ничего плохого в коде, который вы разместили, говоря функционально. Вот полная тестовая программа - я только заполнил пробелы, не меняя ваш код вообще.

#include <iostream>
#include <string>
#include <set>

using namespace std;

class SimulatedDiskFile
{
public:
    string getFileName() { return name; }

    SimulatedDiskFile(const string &n)
        : name(n) { }

    string name;
};

class ComparatorClass {
  public:
    bool operator () (SimulatedDiskFile * file_1, SimulatedDiskFile * file_2) {
      string file_1_name = file_1->getFileName();
      string file_2_name = file_2->getFileName();

      cout << file_1_name << " and " << file_2_name << ": ";

      if (file_1_name < file_2_name) {
        cout << "true" << endl;
        return true;
      }
      else {
        cout << "false" << endl;
        return false;
      }
    }
};

typedef set<SimulatedDiskFile *, ComparatorClass> FileSet;

int main()
{
    FileSet files;

    files.insert(new SimulatedDiskFile("a"));
    files.insert(new SimulatedDiskFile("z"));
    files.insert(new SimulatedDiskFile("m"));

    FileSet::iterator f;
    for (f = files.begin(); f != files.end(); f++)
        cout << (*f)->name << std::endl;

    return 0;
}

Я получаю этот вывод:

z and a: false
a and z: true
z and a: false
m and a: false
m and z: true
z and m: false
a and m: true
m and a: false
a
m
z

Обратите внимание, что набор заканчивается всеми тремя вещами, хранящимися в нем, и ваши записи в журнале сравнения показывают разумное поведение.

Edit:

Ваша ошибка в этих строках:

SimulatedDiskFile temp_file(current_request->getFileName(), current_request->getResponseSize());

disk.addFile(&temp_file);

Вы берете адрес локального объекта. Каждый раз в цикле этот объект уничтожается, а следующий объект размещается в одном и том же пространстве. Таким образом, только последний объект все еще существует в конце цикла, и вы добавили несколько указателей на этот же объект. Вне цикла все ставки отключены, потому что теперь ни один из объектов не существует.

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

2 голосов
/ 16 июня 2009

А вот и проблема:

SimulatedDiskFile temp_file(current_request->getFileName(),
                                   current_request->getResponseSize());
disk.addFile(&temp_file);

Вы добавляете указатель на переменную, которая немедленно уничтожается. Вам необходимо динамически создавать объекты SDF.

1 голос
/ 16 июня 2009
urrent_request = all_requests.begin();
while (current_request != all_requests.end()) {
  SimulatedDiskFile temp_file(...blah..blah..); ====> pointer to local variable is inserted
  disk.addFile(&temp_file);
  current_request++;

}

temp_file выйдет из области действия в момент следующей итерации цикла while. Вам нужно изменить код вставки. Создайте объекты SimulatedDiskFile в куче и нажмите иначе, если объекты меньше, а затем сохраните их по значению в наборе.

0 голосов
/ 16 июня 2009

Согласен с @Earwicker. Все выглядит хорошо. Вы смотрели в all_requests? Может быть, все имена файлов там одинаковые, а все остальное работает нормально? (просто мысли вслух)

...