【问题标题】:Debug Assertation Failed c >= -1 && c <= 255调试断言失败 c >= -1 && c <= 255
【发布时间】:2015-02-14 07:00:58
【问题描述】:

我很难用我的代码理解这个运行时错误。这是我班上的一项作业,我认为这很容易,但有些奇怪的事情正在发生。我在下面发布了我的代码。

这个任务的提示是创建一个程序,要求用户输入一些单词,然后它应该输出有多少单词。我有一个朋友运行该程序并且它可以工作,但是,每当我尝试运行它时,我都会收到此运行时错误。 [http://imgur.com/FcdN3zK]

请记住,我是 C++ 和一般编程的初学者,所以我无法理解非常技术性的响应。提前感谢您的帮助。

#include <string>
#include <iostream>
#include <cstring>

using namespace std;

int wordCounter(char *);

int main()
{
    char *stringArray = nullptr;
    stringArray = new char[120];

    cout << "Please enter a saying or a phrase that has more than one word: " << endl;
    cin.getline(stringArray, 120);

    int words = wordCounter(stringArray);
    cout << "Your statement contains " << words << " words." << endl;

    system("pause");
    return 0;
}

int wordCounter(char *stringTest)
{
    char characterToTest;
    int numberOfWords = 0;
    for (int i=0; i < 120; i++)
    {
        characterToTest = *(stringTest + i);
        if (isspace(characterToTest) && i != 120)
        {
            char characterToTestTemp = *(stringTest + (i + 1));
            if (isalnum(characterToTestTemp))
            {
                numberOfWords++;
            }
        }
    }
    return numberOfWords;
}

【问题讨论】:

  • 您并没有停留在实际输入长度上,因此您正在处理不确定的垃圾粘贴输入字符串的长度。
  • 当我在我的 c++ 上运行您的代码时,我将 nullptr 更改为 NULL (我使用的是旧版本,所以没有 nullptr )并且我的程序编译没有任何问题,但数字单词数是错误的,如果我输入 3 个单词,则输出为 2 个单词,如果我输入 20 个单词,则输出为 19 个单词。
  • 您的代码有多个问题。未能从输入的实际行的末尾(而不是缓冲区的末尾)进行测试是其中之一。在尝试识别任何单词之前等待第一个空格字符是另一回事(这就是您不计算第一个单词的原因)。
  • @ArunA.S 未定义的行为可以以不同的方式表现出来。您的编译器要么将 char 设置为无符号,要么不检查传递给空间等的值,或者将缓冲区初始化为零。
  • @Alan Stokes,我不明白你在说什么(我没那么聪明,还是个新手)。我的意思是,当我编译@Dranslin 的代码时,由于nullptr 而显示错误。我的编译器是 gcc 4.8.0 ( Devc++ ),所以我将 nullptr 更改为 NULL 并且程序编译并给出了输出(尽管字数似乎总是比我输入的数字少 1 )。请解释你的意思(我没有得到任何未定义的行为)。

标签: c++ visual-studio c-strings


【解决方案1】:

您不会在输入字符串的终止处停下来,而是进入输入缓冲区尾部留下的非输入、不确定的缓冲区数据。

这可能是你想要做的:

int wordCounter(const char *str)
{
    int numberOfWords = 0;
    while (*str)
    {
        // skip any leading whitespace
        while (*str && isspace(static_cast<unsigned char>(*str)))
            ++str;

        // if we're still on string data, we have another word
        if (*str)
        {
            // skip everything up to more whitespace
            while (*str && !isspace(static_cast<unsigned char>(*str)))
                ++str;

            // and count the word
            ++numberOfWords;
        }
    }
    return numberOfWords;
}

或类似的东西。可能需要应用额外的处理来考虑标点符号等。一旦到达输入字符串的终止符,这就会停止。

祝你好运。

【讨论】:

    【解决方案2】:

    isspace 和朋友很难正确调用。具体来说,您不能安全地将char 传递给他们,因为char 的值可以是负数,这是不允许的,如错误消息所述。

    为了安全起见,您应该转换为 unsigned char

    isspace(static_cast<unsigned char>(characterToTest))
    

    这不是这里的主要问题,您需要先修复溢出,但这也是您收到错误消息的部分原因。

    【讨论】:

      【解决方案3】:

      无论实际读取的输入字符串的长度如何,您的 wordcount 函数始终处理 120 个字符。因此,您正在阅读字符串末尾并处理未初始化的内存。

      Microsoft 文档显示“如果 c 不是 EOF 或在 0 到 0xFF 范围内(含),则 _isctype 和 _isctype_l 的行为未定义。当使用调试 CRT 库且 c 不是这些值之一时,函数会引发断言。”

      这就是断言的原因。

      C 字符串以零结尾,您必须在循环中测试该条件。

      int wordCounter(char *stringTest)
      {
          char characterToTest;
          int numberOfWords = 0;
          for (int i = 0; i < 120; i++)
          {
              characterToTest = *(stringTest + i);
              if (characterToTest == 0)  
                  break; // <-- exit the loop at the end of the string
              if (isspace(characterToTest) && i != 120)
              {
                  char characterToTestTemp = *(stringTest + (i + 1));
                  if (isalnum(characterToTestTemp))
                  {
                      numberOfWords++;
                  }
              }
          }
          return numberOfWords;
      }
      

      您的计数函数中可能存在其他逻辑错误,例如不计算第一个单词。

      【讨论】:

        【解决方案4】:

        感谢大家的帮助。阅读此内容(我确实意识到我有逻辑错误,如果用户不输入任何内容并提交它,它仍然会打印 1),我能够想出一个稍微不同的方法。

        这是修改后的代码。

        #include <string>
        #include <iostream>
        #include <cstring>
        
        using namespace std;
        
        int wordCounter(char *, int);
        
        int main()
        {
            cout << "Please enter a saying or a phrase that has more than one word: " << endl;
        
            string testString;
            getline(cin, testString);
        
            int stringLength = testString.length();
        
            char *stringArray = nullptr;
            stringArray = new char[stringLength];
        
            strcpy(stringArray, testString.c_str());
        
            int words = wordCounter(stringArray, stringLength);
            cout << "Your statement contains " << words << " words." << endl;
        
            system("pause");
            return 0;
        }
        
        int wordCounter(char *stringTest, int length)
        {
            char characterToTest;
            int numberOfWords = 1;
            for (int i=0; i < length; i++)
            {
        
                    characterToTest = *(stringTest + i);
        
                    if (isspace(characterToTest) && (i != length))
                    {
        
                            char characterToTestTemp = *(stringTest + (i + 1));
                            if (isalnum(characterToTestTemp))
                            {
                                    numberOfWords++;
                            }
                    }
            }
            return numberOfWords;
        }
        

        【讨论】:

        • int stringLength = testString.length(); char *stringArray = new char[stringLength]; strcpy(stringArray, testString.c_str());您创建一个 N 字节数组,然后将 N+1 字节复制到其中(strcpy 以额外的 \0 字节终止其副本)。这被称为“缓冲区溢出错误”。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-02-19
        • 1970-01-01
        • 1970-01-01
        • 2014-03-14
        • 2016-07-21
        • 2016-08-01
        • 1970-01-01
        相关资源
        最近更新 更多