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

Я пытаюсь создать очередь с минимальным приоритетом, одна из проблем, с которыми я сталкиваюсь, заключается в том, что я не могу понять, как инициализировать значение параметров, которые я ввожу в командной строке... Я получаю ошибку seg, когда пытаюсь для ввода значений.

Я чувствую, что упускаю что-то очень очевидное, но я на пределе своих возможностей, пытаясь понять это. Любая помощь приветствуется, так как я новичок в кодировании в целом. Спасибо..

    //header file 
   #ifndef __MinPriorityQueue
   #define __MinPriorityQueue

   #include <string>
   #include <list>
   #include <vector>

   using std::vector;
   using std::string;
   using std::list;

class MinPriorityQueue{

    public:
        MinPriorityQueue();                       //constructor
        ~MinPriorityQueue();                      //destructor
        void insert(const string&, int key);      //insert string and key
        void decreaseKey(const string id, int newKey);  //decreases key in minqueu
        string extractMin();                      //extracts the min string

    private:
        void buildMinHeap();     //produces a min heap from an unordered array
        void minHeapify(int i);  //maintain the min-heap property
        int parent(int i);       //returns min value 
        int left(int i);         //returns smaller val
        int right(int i);        //returns larger val

        class Element
        {
            public:
                Element();
                Element(const string& id, int key);
                ~Element();
            private:
                string* id;
                int key;
        };
        vector<Element*>minheap;
};

#endif

//.cpp-файл

MinPriorityQueue::Element::Element()
{
    *id = "";
    key=0;
}
MinPriorityQueue::Element::Element(const string& i, int k )
{
    *id=i;//segfaults here
    key=k;
}

//main.cpp

#include "minpriority.h"
#include <iostream>

using std::cout;
using std::cin;
using std::endl;

int main(){
    char command='w';
    cin>> command;
    MinPriorityQueue minQue;
    while(command!='q'){
        if (command== 'a')
        {
            string id;
            int key;
            cin>>id>>key;
            minQue.insert(id, key);
        }
        else if (command== 'd')
        {
            string id;
            int key;
            cin>>id>>key;
            minQue.decreaseKey(id, key);
        }
        else if (command== 'x')
        {
            cout<<minQue.extractMin()<<endl;
        }
        cin>>command;
    }
    return 0;
}

Почему вы сделали член id указателем?

molbdnilo 07.04.2019 11:17
string* id; Почему вы храните здесь указатель на строку? Это, вероятно, причина, почему ваша программа терпит неудачу.
πάντα ῥεῖ 07.04.2019 11:17

мой учитель хотел, чтобы мы так делали, я тоже думал, что это странно.

Raquel de Anda 07.04.2019 11:19

«мой учитель хотел, чтобы мы сделали это таким образом». Мне очень трудно поверить... Он упоминал что-нибудь о const char *? Удалите указатель из строки, и код работает нормально.

Constantinos Glynos 07.04.2019 11:25

@ConstantinosGlynos нет, она дала нам файл .h и названия функций

Raquel de Anda 07.04.2019 11:27

Что ж, в этом случае причина, по которой ваш код не работает, заключается в том, что вы пытаетесь присвоить значение этому указателю с помощью разыменования *id = " " или *id = i, когда id не имеет выделенной памяти, что означает, что его нельзя разыменовать. Есть несколько способов «исправить» вашу программу.

Constantinos Glynos 07.04.2019 11:34

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

Jesper Juhl 07.04.2019 12:11
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
42
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Причина, по которой ваш код не работает, заключается в том, что вы пытаетесь присвоить значение указателю std::string *id посредством разыменования *id = " " и *id = i, когда указатель id не имеет выделенной памяти. Это означает, что его нельзя разыменовать.

Есть несколько способов «исправить» вашу программу.

Опция 1: Сделать std::string *id константой и присвоить адрес переменной user_id из main.

class MinPriorityQueue
{
    private:
        class Element
        {
            private:
                const std::string *id;
                int key;

            public:
                Element(const std::string &i, int k)
                {
                    id = &i;
                    key = k;
                }
                ~Element() = default;
        };
        std::vector<Element*> minheap;

    public:
        void insert(const std::string &s, int k)
        {
            minheap.push_back(new Element(s,k));
        }
};

int main()
{
    MinPriorityQueue minQue;

    std::string user_id = "test";
    minQue.insert(user_id, 2);
}

Вариант 2: Выделить память для std::string *id.

class MinPriorityQueue
{
    private:
        class Element
        {
            private:
                std::string *id;
                int key;

            public:
                Element(const std::string &i, int k)
                {
                    id = new std::string(i);
                    key = k;
                }
                ~Element() = default;
        };
        std::vector<Element*> minheap;

    public:
        void insert(const std::string &s, int k)
        {
            minheap.push_back(new Element(s,k));
        }
};

int main()
{
    MinPriorityQueue minQue;

    minQue.insert("test", 2);
}

Вариант 3: Удалите const из параметров функции, чтобы его адрес можно было назначить неконстантному указателю члена.

class MinPriorityQueue
{
    private:
        class Element
        {
            private:
                std::string *id;
                int key;

            public:
                Element(std::string &i, int k)
                {
                    id = &i;
                    key = k;
                }
                ~Element() = default;
        };
        std::vector<Element*> minheap;

    public:
        void insert(std::string &s, int k)
        {
            minheap.push_back(new Element(s,k));
        }
};

int main()
{
    MinPriorityQueue minQue;

    std::string user_id = "test";
    minQue.insert(user_id, 2);
}

Вариант 4 (и мой личный фаворит): преобразовать указатель std::string *id; в обычную строку std::string id;.

пс. С помощью метода указателя ваш конструктор по умолчанию должен либо выделить память и инициализировать строку пустой строкой std::string *id = new std::string("");, либо определить ее как нулевой указатель std::string *id = nullptr;.

Надеюсь это поможет.

Другие вопросы по теме