c++ - 链表错误

标签 c++ linked-list

我正在用 C++ 编写一个程序,我应该在 Hangman 中与计算机对战,并且我应该将特定的 .cpp 文件从使用 vector 转换为使用链接列表。虽然我似乎快完成了,但我不断遇到这个奇怪的错误,每当计算机错误地猜测一个字母时,它就会导致我的程序崩溃。我通过调试器运行该程序,并在调用堆栈中弹出一条消息,内容为“程序收到 SIGSEGV,段错误”以及此信息:

libstdc++6!_ZNSsC1ERKSs()
Guesser::guessACharacter(this=0x28feac) Line 56
main(argc=1, argv=0x7725a8)             Line 30

崩溃似乎导致了我的 Guesser::guessACharacter 函数第 9 行的问题,我尝试将当前节点中的信息放入临时变量中。它看起来像这样:

string word = current->data;

完整代码如下:

#include "guesser.h"
#include "game.h"

#include <iostream>
#include <fstream>


using namespace std;

const std::string Guesser::alphabet = "abcdefghijklmnopqrstuvwxyz";


// Initialize the guesser for a game wit hthe indicated wordlength,
// using words from an indicated file.
Guesser::Guesser (int wordLength, const char* wordListFilename)
{
    for (int i = 0; i < 26; ++i)
        charactersTried[i] = false;

    string word;
    ifstream in (wordListFilename);
    while (in >> word)
    {
        if (word.size() == wordLength)
        {
            // word is of desired length
            if (word.find_first_not_of(alphabet) == string::npos) {
                // word contains only lowercse alphabetics
                //cerr<<"data before possible soln.:/n"<<possibleSolutions->data<<endl;
                possibleSolutions->data = word;
                //cerr<<"data after possible soln.:/n"<<possibleSolutions->data<<endl;
                possibleSolutions = possibleSolutions -> next;
            }
        }
    }
    in.close();

}


/**
 * Scan the words that are possible solutions so far, counting, for
 * each letter not already tried, the number of words with that letter.
 * Guess the letter that occurs in the most words.
 */
char Guesser::guessACharacter()
{
    int counts[26];
    for (int i = 0; i < 26; ++i)
        counts[i] = 0;

    // Count the number of words in which each letter can be found
    for(ListNode* current = possibleSolutions; current != NULL; current = current-> next)
    {
        //cerr<<"data before possible soln.:/n"<<possibleSolutions->data<<endl;
        string word = current->data;
        //cerr<<"data in word:/n"<<word<<endl;
        for (char c = 'a'; c <= 'z'; ++c)
        {
            if (!charactersTried[c- 'a'])
            {
                // Character c has not been tried yet
                if (word.find(c) != string::npos)
                    // c is in this word
                    ++counts[c - 'a'];
            }
        }
    }

    // Find the character that occurs in the most words
    char guess = ' ';
    int maxSoFar = -1;
    for (char c = 'a'; c <= 'z'; ++c)
    {
        if (counts[c - 'a'] > maxSoFar)
        {
            guess = c;
            maxSoFar = counts[c - 'a'];
        }
    }


    if (maxSoFar <= 0)
    {
        guess = 'a';
        while (charactersTried[guess-'a'])
            ++guess;
    }

    charactersTried[guess-'a'] = true;
    return guess;
}


/**
 * Following a successful guess of a letter in the word, make a pass through
 * the possibleSolutions, removing all words that do not contain the
 * guess character in the positions indicated in wordSoFar.
 */
void Guesser::characterIsInWord (char guess, const string& wordSoFar)
{
    ListNode* remainingSolutions = 0;
    for(ListNode* current = possibleSolutions; current != NULL; current = current-> next)
    {
        string wd = current-> data;
        bool OK = true;
        for (int k = 0; OK && k < wordSoFar.size(); ++k)
        {
            if (wordSoFar[k] == guess)
            {
                if (wd[k] != guess)
                {
                    OK = false;
                }
            }
        }
        if (OK)
        {
            //cerr << "Keeping " << wd << endl;
            remainingSolutions->data = wd;
            //possibleSolutions->next = remainingSolutions;
        }
    }
    possibleSolutions = remainingSolutions;


}


/**
 * Following a mistaken guess of a letter in the word, make a pass through
 * the possibleSolutions, removing all words that contain the
 * guess character.
 */
void Guesser::characterIsNotInWord (char guess)
{
    ListNode* remainingSolutions;
    for(ListNode* current = possibleSolutions; current != NULL; current = current-> next)
    {
        string wd = current->data;
        if (wd.find(guess) == string::npos)
        {

            remainingSolutions = new ListNode(wd, remainingSolutions);
        }
    }
    possibleSolutions = remainingSolutions;

}


/**
 * Guesser has lost the game. Look at the provider's actual word
 * and gripe a bit about losing.
 */
void Guesser::admitToLoss (std::string actualWord, const string& wordSoFar)
{
    bool match = actualWord.size() == wordSoFar.size();
    for (int i = 0; match && i < actualWord.size(); ++i)
    {
        match = wordSoFar[i] == Game::FILL_CHARACTER ||
        wordSoFar[i] == actualWord[i];
    }
    if (!match)
    {
        cout << "Ummm...your word '" << actualWord
        << "' does not match the patterh '"
        << wordSoFar <<"'.\nDid you make a mistake somewhere?"
        << endl;
    }
    else
    {
        for (int i = 0; match && i < actualWord.size(); ++i)
        {
            if (wordSoFar[i] == Game::FILL_CHARACTER
                && charactersTried[actualWord[i]-'a'])
            {
                cout << "Did you forget to mention the '"
                << actualWord[i]
                << "' in position " << i+1 << "?"
                << endl;
                return;
            }
        }

        for (ListNode* current = possibleSolutions;(!match) && current !=
             NULL; current = current-> next)
        {
            match = (actualWord == current->data);
            current = current->next;
            match = match && (current != 0);
        }
        //match = match && (current != 0);
        if (match)
        {
            cout << "OK, I might have guessed that eventually." << endl;
        }
        else
        {
            cout << "Interesting, I don't know that word. Are you sure you\n"
            << "spelled it correctly?." << endl;
        }

    }
}

我觉得这个问题的答案就在我面前,但我就是想不出来。我想知道其他人是否可以轻松发现我在这里做错了什么。

最佳答案

在下面的代码片段中

ListNode* remainingSolutions = 0;
for(ListNode* current = possibleSolutions; current != NULL; current = current-> next)
{
        ....
        if (wordSoFar[k] == guess)
        {
            if (wd[k] != guess)
            {
                OK = false;
            }
        }
    }
    if (OK)
    {
        remainingSolutions->data = wd;
    }
}
possibleSolutions = remainingSolutions;
如果被访问,

remainingSolutions 将为 0 或 NULL,这可能是原因之一。

最后它还会将 NULL 分配给 possibleSolutions(我假设它是链表的头部),因此下次访问它时,也许可以通过调用 guessACharacter(),会导致段错误。

关于c++ - 链表错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13634935/

相关文章:

c - 在C中的链表开头插入新节点

C:将 getline() 创建的字符串存储在链表中?

java - 获取 LinkedList 中 map 对象的索引

c++ - std::wstring:与 + 的连接无效

c++ - 如何使用 C++ 范围来实现 numpy.ndindex?

c++ - C++引用变量

c - 链表段错误

c++ - 我可以更改将引用参数传递到指针的函数的输入并仍然使其工作(C、C++)吗?

c++ - glVertexAttribPointer 问题(OpenGL 3.x 向前兼容上下文)

java - 为什么 LinkedList.removeFirst() = LinkedList.pop()?