Сохраненное значение исчезает при установке нулевого указателя на структуру в C ++ - PullRequest
3 голосов
/ 01 мая 2011

Я пишу приложение на 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 для моего «чистого» слова.Я могу напечатать слово cout'ing node-> clean.Но когда я устанавливаю node-> same в NULL, я теряю node-> clean.Я не теряю узел-> положение или узел-> размер.Если я удаляю строку, в которой назначаю 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;
}

Ответы [ 4 ]

2 голосов
/ 01 мая 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
2 голосов
/ 01 мая 2011

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

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

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

0 голосов
/ 01 мая 2011

Кроме новых и cout это может быть также C.

Некоторые другие чтения
В чем различия между struct и class в C ++?
char * Vs std :: string
Удалить пробелы из std :: string в 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);
}
0 голосов
/ 01 мая 2011

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

...