Сохраненное значение исчезает при установке указателя структуры на null в C++

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

struct Word{
    char* clean;
    int size;
    int position;
    SongId id;
    Word* same;
    Word* diff;
};

У меня есть функция makeNode, которая делает следующее:

  1. вникает в каждое слово
  2. создает новую структуру Word и добавляет в нее слово
  3. создает узел с именем Word*, который указывает на новое слово
  4. сохраняет указатель в хеш-таблице.

В моей функции makeNode я установил для node->clean свое «чистое» слово. Я могу напечатать слово, выбрав node->clean. Но когда я устанавливаю для node->same значение NULL, я теряю node->clean. Я не теряю node-> position или node-> size. Если я удалю строку, в которой я присваиваю node->same значение NULL, я не потеряю node->clean.

char* clean = cleanse(word);
Word* node = new Word;
node->size = strlen(word);
node->clean = clean;
cout<<"MADE NODE FOR "<<node->clean<<endl;
node->position = position;
cout<<"4 node clean: "<<node->clean<<endl;
node->id = id;
cout<<"5 node clean: "<<node->clean<<endl;
node->same = NULL;
cout<<"6 node clean: "<<node->clean<<endl;
cout<<"node position: "<<node->position<<endl;
cout<<"node size: "<<node->size<<endl;
node->diff = NULL;

дает следующий результат:

MADE NODE FOR again
4 node clean: again
5 node clean: again
6 node clean:
node position: 1739
node size: 6
0 node clean:
1 node clean:
3 node clean: 

Может ли кто-нибудь помочь мне обойти эту ошибку? Если вам нужна дополнительная информация, дайте мне знать. Заранее спасибо!

РЕДАКТИРОВАТЬ: вот функция очистки.

char* SongSearch::cleanse(char* dirty)
{

string clean;
int iter = 0;
while (!isalnum(dirty[iter]))
{
    iter++;
}
while(dirty[iter]!='\0')
{
    clean += dirty[iter];
    iter++;
}

int backiter = clean.length() - 1;
while(!isalnum(clean[backiter]))
{
    clean.erase(backiter, 1);
    backiter--;
}


char c;
  for (int i = 0; i<clean.length(); i++)
{
    c = tolower(clean[i]);
    clean[i] = c;
}

char* toReturn = (char*)(clean.c_str());
return toReturn;
}

person Sarah    schedule 01.05.2011    source источник
comment
Что такое cleanse? Функция? Выложи его код. Возвращает ли он локальный массив символов?   -  person Nawaz    schedule 01.05.2011
comment
Если вам больно, когда вы что-то делаете, не делайте этого. Прекратите использовать char *, Word * и используйте std::strings и вектор Word. И переосмыслите название своей структуры - почему она называется Word????   -  person    schedule 01.05.2011


Ответы (4)


Проблема, вероятно, в том, что в cleanse вы возвращаете clean.c_str().

Это значение указателя перестает быть действительным, когда clean перестает существовать, то есть когда функция завершает работу. Больше не гарантируется, что он указывает на что-либо, так что это чистая удача, что вы когда-либо видите строку «снова», как и ожидалось.

Я подозреваю, что происходит то, что память, которая используется для хранения данных для строки clean в cleanse, была повторно использована для структуры word, но не перезаписывается немедленно. Так уж получилось, что байт, который раньше содержал первый a, теперь содержит часть same члена вашей структуры. Таким образом, когда вы записываете нулевой указатель на node->same, это приводит к записи 0 байтов в место, на которое указывает node->clean. После этого он указывает на пустую строку.

person Steve Jessop    schedule 01.05.2011

Вам нужно сократить свой код до минимального примера, отображающего проблему, и опубликовать его.

Следующий код не отображает проблему. Содержимое main и определение Word скопированы из вашего кода, затем я добавил код, необходимый для его компиляции:

#include <iostream>
#include <cstring>
using namespace std;

typedef int SongId;

struct Word{
    char* clean;
    int size;
    int position;
    SongId id;
    Word* same;
    Word* diff;
};

char *cleanse(const char *w) {
    return (char *)w;
}
const char *word = "again ";
const int position = 1739;
const int id = 0;

int main() {
    char* clean = cleanse(word);
    Word* node = new Word;
    node->size = strlen(word);
    node->clean = clean;
    cout<<"MADE NODE FOR "<<node->clean<<endl;
    node->position = position;
    cout<<"4 node clean: "<<node->clean<<endl;
    node->id = id;
    cout<<"5 node clean: "<<node->clean<<endl;
    node->same = NULL;
    cout<<"6 node clean: "<<node->clean<<endl;
    cout<<"node position: "<<node->position<<endl;
    cout<<"node size: "<<node->size<<endl;
    node->diff = NULL;
}

Выход:

MADE NODE FOR again 
4 node clean: again 
5 node clean: again 
6 node clean: again 
node position: 1739
node size: 6
person Community    schedule 01.05.2011

Хорошо, нам нужно увидеть код для некоторых из них, чтобы быть уверенным, но вот что говорит вам ошибка: в какой-то момент вы назначаете что-то, что перезаписывает или удаляет ваш clean. Поскольку вы объявляете его как char *, я предполагаю, что вы используете его как указатель на массив символов, и велика вероятность, что один массив совмещен с двумя «чистыми» указателями в двух разных словах.

person Charlie Martin    schedule 01.05.2011

Помимо new и cout, это также может быть C.

Некоторое другое чтение
Каковы различия между структурой и класс на C++?
char * Vs std::string
Удалить пробелы из std:: строка в C++
функция tolower для строк C++
Как отменить функтор в C++ (STL)?

Попробуйте следующую альтернативу (нескомпилированный пример)

#include <iostream>
#include <string>
#include <algorithm>
#include <functional>

typedef int SongId;

class Word{
    int position;
    SongId id;
    Word* same;
    Word* diff;

public: 
  const std::string word;

  const int size() const { return clean.length() };

  Word( const std::string& word_, const int position_ = 1739, const int id_ = 0 )
    : clean( cleanse(word_) )
    , position( position_ )
    , id( id_ )
    , same( NULL )
    , diff( NULL )
  {
    cout<<"MADE NODE FOR "<< word_ << "\n"
      <<"node clean: "<< word << "\n"
      <<"node position: "<< position << "\n";
      <<"node size: "<< size() << endl;
  }

  static std::string cleanse( const std::string& dirty)
  {
    string clean( dirty );

// Remove anything thats not alpha num
    clean.erase(remove_if(clean.begin(), clean.end(), std::not1(::isalnum) ), clean.end());
// make it lower case
    std::transform( clean.begin(), clean.end(), clean.begin(), ::tolower);  // or boost::to_lower(str);

    return clean;
  }
};

const char *word = "again ";

int main() {
    Word* node = new Word(word);
}
person Greg Domjan    schedule 01.05.2011