c ++ cout и char-pointers, что-то, чего мне не хватает в указателях - PullRequest
2 голосов
/ 29 декабря 2011

Я пытаюсь написать кусок кода для своего рода дерева, которое я создаю, и если узел не существует, я хотел бы выдать исключение, показывающее, какой узел не существует.Т.е.:

Trie t = Trie();
try {
    t.get('a');
} catch(NoSuchNode e) {
    cout << e.what() << endl;
}

этот код должен просто ничего не делать, если узел существует, в противном случае выведите данную ошибку, вот мой код исключения (я использую std :: exception, потому что это показалось хорошей идеей):

class NoSuchNode : public std::exception
{
private:
  char *_node_name;
public:
  NoSuchNode(const char *node_name) { _node_name = new char(*node_name); }
  virtual const char* what() const throw()
    {
      std::stringstream ss;
      ss << "There exists no node for: " << _node_name << ".";
      const std::string& tmp = ss.str();
      return tmp.c_str();
    }
};

И это работает так, как должно, valgrind также не выдает ошибок при неправильном чтении, так что я полагаю, все в порядке?Теперь на мой вопрос, прежде чем я пришел к этому решению, я просто изменил:

_node_name = new char(*node_name);

на:

_node_name = node_name;

, так что мне не нужно выделять для него больше места,Проблема в том, что иногда он не печатает хорошие данные, а иногда один символ и даже больше после этого.Не совсем то, что я ожидал.Кроме того, Вальгринд пожаловался на то, что я прочел память, которую мог использовать.Почему это?Бьюсь об заклад, что если std :: string просто get - это указатель на символ, он думает, что это строка с нулевым символом в конце и поэтому пытается читать с начала памяти, пока не найдет нулевой символ?Это правильно, и как правильно решить эту проблему?Должен ли я просто передавать данные по значению, как я это делаю?

Добавлено: Каждый узел должен содержать только один символ и ничего более, все, что передается символом, это просто один символ и ничего больше.Так что у меня нет, так сказать, строки в символах.

Итак, получается, что меня действительно заинтересовало то, как потоки обрабатывают ввод char *.Спасибо за ответы!

Если что-то не так в моем коде и у вас есть время, пожалуйста, сообщите мне!

Заранее спасибо!

Ответы [ 3 ]

3 голосов
/ 29 декабря 2011

new char(*node_name) выделяет один символ, соответствующий первому символу node_name. Не строка Когда вы используете его как строку C с нулевым символом в конце, байт-терминатор отсутствует, и вы получите мусор.

Char * является особенным для std :: cout и других потоков, потому что это означает «строку C с нулевым символом в конце». Вам придется разыменовать его (<< *_node_name <<) или, как предполагает hmjd, просто использовать один символ (char node_name).

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

В общем, написание собственных классов исключений не так просто, и есть над чем подумать. В вашем случае просто наследуйте от std::logic_error или std::runtime_error, и пусть они обрабатывают строки.

2 голосов
/ 29 декабря 2011

Возвращать не очень хорошая идея return tmp.c_str (); потому что tmp.c_str () возвращает указатель на область памяти, которая будет освобождена после возврата из функции.

2 голосов
/ 29 декабря 2011

Почему вы вообще используете указатели?Ваше имя узла - это одиночное char, относитесь к нему как к такому.

class NoSuchNode : public std::exception
{
private:
  char _node_name;
public:
  NoSuchNode(char node_name) : _node_name(node_name) { }
  virtual const char* what() const throw()
    {
      std::stringstream ss;
      ss << "There exists no node for: " << _node_name << ".";
      const std::string& tmp = ss.str();
      return tmp.c_str();
    }
};

(Я заменил присвоение в конструкторе инициализацией. Это общая рекомендация.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...