VC ++运行时错误:调试断言失败

时间:2014-04-25 09:12:08

标签: c++ debugging pointers runtime-error dynamic-memory-allocation

目前我收到运行时“断言错误”

这是错误:

enter image description here

我正在将文本文件中的单词读入动态分配的数组中。 这段代码是我填充新数组的地方。

我知道问题是由这段代码造成的,而我的逻辑关闭却看不出它是什么。

  //fill new arrays
    for( int y = 0; y < new_numwords; y++)
    {
        for( int i = 0; i < NUM_WORDS; i++)
        {
            if (!strcmp(SentenceArry[i], EMPTY[0]) == 0)
            {
            New_SentenceArry[y] = SentenceArry[i];
            New_WordCount[y] = WordCount[i];
            y++;
            }
        }
    }

另外,我如何将这个动态分配的2D数组传递给函数? (代码确实需要整体清理)

char** SentenceArry = new char*[NUM_WORDS]; //declare pointer for the sentence
for( int i = 0; i < NUM_WORDS; i++)
{
SentenceArry[i] = new char[WORD_LENGTH];
}

以下是代码的完整范围..非常感谢帮助!

以下是阅读内容:enter image description here

和当前输出(输出是它的假设):enter image description here

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <fstream>
#include <cstring>
#include <cctype>
#include <iomanip>

using std::setw;
using std::left;

using std::cout;
using std::cin;
using std::endl;

using std::ifstream;


int main()
{

const int NUM_WORDS = 17;//constant for the elements of arrays 
const int WORD_LENGTH = 50;//constant for the length of the cstrings (NEED TO GIVE THE VALUE ZERO STILL!)
short word_entry = 0; //declare counter
short new_numwords= 0; //declare new word count
char EMPTY[1][4]; //NULL ARRAY
EMPTY[0][0] = '\0';//define it as null


char** SentenceArry = new char*[NUM_WORDS]; //declare pointer for the sentence
for( int i = 0; i < NUM_WORDS; i++)
{
SentenceArry[i] = new char[WORD_LENGTH];
}

int WordCount[NUM_WORDS];//declare integer array for the word counter

for(int i = 0; i < NUM_WORDS; i++)//fill int array
{
WordCount[i] = 1;
}

int New_WordCount[NUM_WORDS] = {0};

ifstream read_text("DataFile.txt"); //read in our text file

    if (read_text.is_open()) //check if the the file was opened
    {
        read_text >> SentenceArry[word_entry];

        //REMOVE PUNCTUATION BEFORE BEING READ INTO THE ARRAY
        while (!read_text.eof()) 
        {

        word_entry++; //increment counter
        read_text >> SentenceArry[word_entry]; //read in single words of the text file into the array SentenceArry

        char* ptr_ch;//declare our pointer that will find chars

        ptr_ch = strstr( SentenceArry[word_entry], ",");//look for "," within the array

        if (ptr_ch != NULL)//if true replace it with a null character
            {
            strncpy( ptr_ch, "\0" , 1);
            }//end if
                else
                    {

                    ptr_ch = strstr( SentenceArry[word_entry], ".");//look for "." within the array

                        if (ptr_ch != NULL)//if true replace it with a null character
                            {
                            strncpy( ptr_ch, "\0" , 1);
                            }//end if
                    }//end else
            } //end while
    }//end if

    else 
    {
        cout << "The file could not be opened!" << endl;//display error message if file doesn't open
    }//end else

read_text.close(); //close the text file after eof



//WORD COUNT NESTED FOR LOOP
for(int y = 0; y < NUM_WORDS; y++)
{
    for(int i = y+1; i < NUM_WORDS; i++)
    {
        if (strcmp(SentenceArry[y], EMPTY[0]) == 0)//check if the arrays match
        {
            y++;

        }
        else
        {
            if (strcmp(SentenceArry[y], SentenceArry[i]) == 0)//check if the arrays match
            {
                WordCount[y]++;
                strncpy(SentenceArry[i], "\0" , 3);
            }//end if
        }//end if
    }//end for
}//end for


//find how many arrays still contain chars
for(int i = 0; i < NUM_WORDS; i++)
{
    if (!strcmp(SentenceArry[i], EMPTY[0]) == 0) 
    {
    new_numwords++;
    }
}


//new dynamic array
char** New_SentenceArry = new char*[new_numwords]; //declare pointer for the sentence
for( int i = 0; i < new_numwords; i++)
{
New_SentenceArry[i] = new char[new_numwords];
}



//fill new arrays
for( int y = 0; y < new_numwords; y++)
{
        for( int i = 0; i < NUM_WORDS; i++)
        {
        if (!strcmp(SentenceArry[i], EMPTY[0]) == 0)
        {
        New_SentenceArry[y] = SentenceArry[i];
        New_WordCount[y] = WordCount[i];
        y++;
        }
    }
}

//DISPLAY REPORT
cout << left << setw(15) << "Words" << left << setw(9) << "Frequency" << endl;
for(int i = 0; i < new_numwords; i++) //compare i to the array constant NUM_WORDS
{
cout << left << setw(15) << New_SentenceArry[i] << left << setw(9) << New_WordCount[i] << endl; //display the contents of the array SentenceArry
}


//DEALLOCATION
for( int i = 0; i < NUM_WORDS; i++)//deallocate the words inside the arrays
{
    delete [] SentenceArry[i];
}

for(int i = 0; i < new_numwords; i++)
{
delete [] New_SentenceArry[i];
}

delete [] SentenceArry; //deallocate the memory allocation made for the array SentenceArry
delete [] New_SentenceArry;//deallocate the memory allocation made for the array New_SentenceArry

}//end main

2 个答案:

答案 0 :(得分:2)

代码有几个问题,但不能说这可以用C ++编写,而不是用C ++ I / O编写。

Issue 1:

由于你正在使用c风格的字符串,任何字符串数据的复制都需要函数调用,例如strcpy(),strncpy()等。你在这段代码中没有遵循这个建议:

for( int y = 0; y < new_numwords; y++)
{
    for( int i = 0; i < NUM_WORDS; i++)
    {
        if (!strcmp(SentenceArry[i], EMPTY[0]) == 0)
        {
            New_SentenceArry[y] = SentenceArry[i]; // This is wrong
            New_WordCount[y] = WordCount[i];   
            y++;
        }
    }
}

您应该使用strcpy(),而不是=来复制字符串。

strcpy(New_SentenceArry[y], SentenceArry[i]);

Issue 2:

您应该为原始阵列和新阵列分配WORD_LENGTH。字符串的长度与字符串的数量无关。

char** New_SentenceArry = new char*[new_numwords]; //declare pointer for the sentence
for( int i = 0; i < new_numwords; i++)
{
    New_SentenceArry[i] = new char[new_numwords];
}

这应该是:

char** New_SentenceArry = new char*[new_numwords]; //declare pointer for the sentence
for( int i = 0; i < new_numwords; i++)
{
    New_SentenceArry[i] = new char[WORD_LENGTH];
}

Issue 3:

您的循环不会检查索引是否超出了数组的范围。

您似乎根据当前使用的数据对程序进行了编码,而不是编写代码而不管数据是什么。如果您将自己限制为17个单词,那么检查指数是否超过16?不通。

例如:

while (!read_text.eof() )

应该是:

while (!read_text.eof() && word_entry < NUM_WORDS) 

Issue 4:

您不能正确处理找到的第一个字符串:

read_text >> SentenceArry[word_entry];  // Here you read in the first word
while (!read_text.eof() ) 
{
     word_entry++; //increment counter
     read_text >> SentenceArry[word_entry]; // What about the first word you read in?

Summary:
即使有这些变化,我也无法保证程序不会崩溃。即使它没有因这些变化而崩溃,我也无法保证它能在100%的时间内正常工作 - 保证需要进一步分析。

考虑到此任务的内容,正确的C ++解决方案是使用std::map<std::string, int>来保持字频率。地图会自动在一个条目中存储相似的单词(假设您从单词中删除了垃圾),并且当条目插入地图时会自动将计数提高到1。

这样的事情:

#include <string>
#include <map>
#include <algorithm>

typedef std::map<std::string, int> StringMap;
using namespace std;

bool isCharacterGarbage(char ch)
{ return ch == ',' || ch == '.'; }

int main()
{
   StringMap sentenceMap;
   //...
   std::string temp;
   read_text >> temp;
   temp.erase(std::remove_if(temp.begin(), temp.end(), isCharacterGarbage),temp.end());
   sentenceMap[temp]++;
   //...
}

单独的代码可以你的原始代码所做的一切 - 跟踪字符串,破坏字数,在处理之前从字中删除垃圾字符等等。但最重要的是,无手动内存管理。没有调用new [],删除[],没有。代码只是&#34;工作&#34;。这实际上是 5行的代码,您只需编写一个&#34; read&#34;循环。

我不会仔细检查每一个细节,你可以自己做,因为代码很小,而且有大量的资源可用来解释std::mapremove_if()等。< / p>

然后打印出来只是通过地图并打印每个条目(字符串和计数)。如果添加打印,则可能是4行额外代码。总而言之,几乎所有的任务都是通过10行左右的代码完成的。

答案 1 :(得分:1)

删除以下代码。

for(int i = 0; i < new_numwords; i++)
{
 delete [] New_SentenceArry[i];
}