【问题标题】:strcpy assertion error c++strcpy 断言错误 C++
【发布时间】:2014-05-09 06:42:53
【问题描述】:

我是一名学生,刚刚学习 c++,所以我确信有更有效的方法可以做到这一点;话虽如此,我真的很感激能帮助我弄清楚我的程序崩溃的原因。我已将其范围缩小为 strcpy 函数,该函数会使所有内容崩溃并破坏它,我已将其注释掉并标记。我显然在程序中多次使用了类似参数的 strcpy 函数,所以我不明白为什么那个特定的函数会崩溃。我已经尝试了我能想到的一切,并且非常感谢您的帮助。到目前为止,我已经注释掉了很多内容,因此它应该使用名为“bookdb”的正确文本文件运行,我的文本文件中目前有这个

Active Learning Approach,Randal Albert,9780763757236,1,650,1,<br>
Technical Communications,John Lannon,9780321899972,2,724,0,

要查看错误,您必须取消注释 strcpy(bookArray[num_books].author_name, temp_authorName);

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>

enum Genres {HORROR=1, SCIFI, COMEDY, DRAMA, ACTION};


struct Book
{
    char title[100];
    char author_name[50];
    char isbn[14];
    Genres genre;
    int num_pages;
    bool paperback;
};

//Function Declarations
unsigned short ReadBooks(Book * bookArray, unsigned short & num_books);
void DisplayBooks(Book * bookArray, unsigned short num_books);
void ResizeArrays(Book * bookArray, unsigned short num_books);

int main ()
{
    unsigned short num_books = 0;
    Book * bookArray = new Book();

    num_books = ReadBooks(bookArray, num_books);

}//End Main

unsigned short ReadBooks(Book * bookArray, unsigned short & num_books)
{
    ifstream readBooks("bookdb.txt");
    char temp_title[100] = "0";
    char temp_authorName[100] = "0";
    char temp_isbn[14] = "0";

    char temp_genre[50] = "0";
    char temp_numPages[50] = "0";
    char temp_paperback[50] = "0";

    int genreNumber = 0,
        numPages = 0,
        paperback = 0;

    if (readBooks.is_open() )
    {
        cout << "The file was successfully opened\n" << endl;

        readBooks.getline(temp_title, 100, ',');//Reads into temp cstring
        strcpy(bookArray[num_books].title, temp_title); //copies to dynamic cstring
        //cout << bookArray[num_books].title << endl; //displays part of structure to make sure it worked!!

        readBooks.getline(temp_authorName, 100, ',');
        strcpy(bookArray[num_books].author_name, temp_authorName); 
        //cout << bookArray[num_books].author_name << endl; 

        readBooks.getline(temp_isbn, 14, ',');
        strcpy(bookArray[num_books].isbn, temp_isbn); 
        //cout << bookArray[num_books].isbn << endl;

        readBooks.getline(temp_genre, 50, ',');//Get the genre as a char
        genreNumber = atoi(temp_genre);//converts char to an int
        bookArray[num_books].genre = static_cast <Genres> (genreNumber);//converts int to ENUM
        //cout << bookArray[num_books].genre << endl;//Displays ENUM to make sure it worked!!

        readBooks.getline(temp_numPages, 50, ',');
        numPages = atoi(temp_numPages); //converts char to an int
        bookArray[num_books].num_pages = numPages; //assigns int to structure
        //cout << bookArray[num_books].num_pages << endl; //Displays part of structure to make sure to works!!

        readBooks.getline(temp_paperback, 50, ',');
        paperback = atoi(temp_paperback); //converts char to an int
        bookArray[num_books].paperback = static_cast <bool> (paperback);
        //cout << bookArray[num_books].paperback << endl;
        num_books++;

        //DisplayBooks(bookArray, num_books);
        ResizeArrays(bookArray, num_books);
        cout << "The number of books is: " << num_books << endl;

        //while (!readBooks.eof() )
        //{

        readBooks.getline(temp_title, 100, ',');//Reads into temp cstring
        strcpy(bookArray[num_books].title, temp_title); //copies to dynamic cstring
        cout << bookArray[num_books].title << endl; //displays part of structure to make sure it worked!!

        readBooks.getline(temp_authorName, 100, ',');
        cout << temp_authorName << endl; 
        //strcpy(bookArray[num_books].author_name, "0");
        ///THIS BREAKS MY CODE////strcpy(bookArray[num_books].author_name, temp_authorName); 
        //cout << bookArray[num_books].author_name << endl; 

        readBooks.getline(temp_isbn, 14, ',');
        //strcpy(bookArray[num_books].isbn, temp_isbn); 
        //cout << bookArray[num_books].isbn << endl;

        readBooks.getline(temp_genre, 50, ',');//Get the genre as a char
        //genreNumber = atoi(temp_genre);//converts char to an int
        //bookArray[num_books].genre = static_cast <Genres> (genreNumber);//converts int to ENUM
        //cout << bookArray[num_books].genre << endl;//Displays ENUM to make sure it worked!!

        readBooks.getline(temp_numPages, 1000, ',');
        //numPages = atoi(temp_numPages); //converts char to an int
        //bookArray[num_books].num_pages = numPages; //assigns int to structure
        //cout << bookArray[num_books].num_pages << endl; //Displays part of structure to make sure to works!!

        readBooks.getline(temp_paperback, 50, ',');
        //paperback = atoi(temp_paperback); //converts char to an int
        //bookArray[num_books].paperback = static_cast <bool> (paperback);
        //cout << bookArray[num_books].paperback << endl;*/

        num_books++;

        //ResizeArrays(bookArray, num_books);
        //}//End while

        readBooks.close();
    }//End if
    else
    {
        cout << "There was not an existing book file, so one will be created"  << endl;
    }//End else

    return 0;
}//End ReadBooks

void DisplayBooks(Book * bookArray, unsigned short num_books)
{
    for (unsigned short i = 0; i < num_books; i++)
    {
        cout << setw(30) << left << bookArray[i].title << left << setw(20) << bookArray[i].author_name << left << setw(15) << bookArray[i].isbn
             << left << setw(3) << bookArray[i].genre  << left<< setw(6) << bookArray[i].num_pages << left << setw(4) << bookArray[i].paperback << endl;
    }//End For
}//ENd Display Function

void ResizeArrays(Book * bookArray, unsigned short num_books)
{
    Book * temp_bookArray = new Book[num_books + 1];


    for (int i = 0; i < num_books; i++)
    {
        strcpy(temp_bookArray[i].title, bookArray[i].title);
        //cout << temp_bookArray[i].title << endl; //For Debugging

        strcpy(temp_bookArray[i].author_name, bookArray[i].author_name);
        //cout << temp_bookArray[i].author_name << endl; //for Debugging

        strcpy(temp_bookArray[i].isbn, bookArray[i].isbn);
        //cout << temp_bookArray[i].isbn << endl;//for debugging

        temp_bookArray[i].genre = bookArray[i].genre;
        //cout << temp_bookArray[i].genre << endl;//for debugging

        temp_bookArray[i].num_pages = bookArray[i].num_pages;
        //cout << temp_bookArray[i].num_pages << endl;// for debugging

        temp_bookArray[i].paperback = bookArray[i].paperback; 
        //cout << temp_bookArray[i].paperback << endl; //for debugging


    }//End for

    delete [] bookArray;

    bookArray = temp_bookArray; 

    DisplayBooks(bookArray, num_books); //debugging to make sure bookArray is reassigned


}//End Resize Function

【问题讨论】:

  • 突出的问题是你分配了一个Book,然后你使用一个指向它的指针,因为它是一个数组。删除new 和指针,这样会更难犯这种错误。
  • 从 C 到 C++ 的过程中你应该摆脱的东西:char [] 支持string任何 类型的数组,支持vector。有利于引用的指针参数。构造函数之外的动态内存分配。当然,这过于简单化了,但这是一个很好的第一条经验法则。您的struct Book 应该是一个类,该类的函数(ReadBooks()DisplayBooks() 等)成员。这是最低限度的。您可以忽略所有其他内容 - 继承、模板、异常等 - 但不做我上面提到的事情,您基本上可以继续使用 C。;-)
  • 你的代码有太多的破坏,这就引出了一个问题,它是怎么写的?在任何情况下,您都应该尝试将问题缩小到单个问题,并发布可以重现该问题的最少但独立的代码。一堵错误的代码对于一个问题来说太多了。

标签: c++ visual-c++ assertions strcpy


【解决方案1】:

strlen 获取所有没有 '\0' 的元素,所以如果你有 str = "1234"; str 长度为 5,(1234 + '\0) 但返回 4.Strcpy 取所有 5 个元素 + '\0' 。

【讨论】:

    【解决方案2】:

    ResizeArrays 存在问题:

    • 它为数组分配新内存,但不会将该新数组返回给调用函数,以便调整指向新数组位置的指针。
    • 可能需要调整大小、旧大小和新大小,您只能复制这些元素中的最小值。

    为了解决这个问题,您可以执行以下操作:

    Book* ResizeArrays(Book * bookArray, unsigned short num_books)
    { 
        ....
        return bookArray;
    }
    

    那么就这样使用函数

    bookArray = ResizeArrays(bookArray, num_books);
    

    但是,当您使用数组删除时,对于您的第一次分配,您也需要在 main() 中使用数组分配,

    Book * bookArray = new Book[1];
    

    虽然它只分配一本书,但它应该作为一个数组来完成,因此它与 ResizeArrays 中使用的 delete [] 兼容。

    我认为这是一个学习练习。在正常使用 C++ 时,您不会使用裸 new 和 delete 运算符。您可以简单地使用 std::vector 或类似的,或者创建一个管理内存的对象,分别在构造函数和析构函数中使用 new 和 delete。

    【讨论】:

    • 这可能是真的,但这只是众多问题中的一个,而不是第一个。在致电ResizeArrays 之前,事情就变得很糟糕。
    • 是的,它确实有问题,但修复它似乎可以解决内存分配问题,并且从那里调试其余部分应该相当容易。
    • 我很确定你刚刚保存了我的整个项目。非常感谢!!!我现在明白那里出了什么问题。对于其他所有人,我知道可能有一百万个问题,但我是一名刚刚学习语言的大学生,而我的老师也没有太多的 c++ 经验。非常感谢您的帮助。
    【解决方案3】:

    我看到的问题:

    问题 1

    没有足够的空间来正确保存 ISBN。输入文件中 ISBN 的长度为 14 个字符。要将它们保存在以空字符结尾的字符串中,您需要有一个可以容纳 15 个或更多字符的数组。

    结果,一行

        readBooks.getline(temp_isbn, 14, ',');
    

    将在 13 个字符后停止读取,因为它必须使用第 14 个字符来存储 '\0'

    问题 2

    这条线看起来不对。

        readBooks.getline(temp_numPages, 1000, ',');
    

    我怀疑这是一个错字,你的意思是

        readBooks.getline(temp_numPages, 50, ',');
    

    问题 3

    ResizeArray 中的内存处理存在问题。

    void ResizeArrays(Book * bookArray, unsigned short num_books)
    {
        Book * temp_bookArray = new Book[num_books + 1];
    
        // Here, you are deleting the memory that was allocated in `main`.
        // bookArray in the calling function now points to memory that has been
        // deleted here.
        delete [] bookArray;
    
        // Here, you are changing the value of bookArray but only
        // locally in this function. This assignment doesn't
        // change the value of bookArray in the calling function.
        bookArray = temp_bookArray; 
    
        DisplayBooks(bookArray, num_books); //debugging to make sure bookArray is reassigned
    
    
    }//End Resize Function
    

    如果您将ResizeArray 更改为:

    void ResizeArrays(Book*& bookArray, unsigned short num_books)
    

    一切都会好起来的。

    问题 4

    我看到您已经注释掉了ReadBooks 中的while 循环。如果您决定恢复该循环,则必须在每次循环运行时调整 bookArray 的大小。

    建议 使用std::vector&lt;Book*&gt; 来保存书籍会更容易,而不是为Books 的数组分配内存。

    【讨论】:

    • 不,不应该一切正常。
    • 感谢您的帮助!当我这样做时, resize 函数中的 bookArray[i].title 给出了一个未定义的错误。我想通过这样做 bookArray = temp_bookArray;我正在重新分配指向新动态内存的指针,我的逻辑是,如果我传递 bookArray 指针,它就是一个内存地址,这意味着我更改的任何内容都会在内存中更改它。这是我的逻辑缺陷吗?再次感谢您的帮助!
    • 发送一个指针可以让你改变那个指针指向的内存。但是在这里,您正在更改该内存块的位置。所以实际上你需要向指针发送一个指针,这样你就可以改变指针。您可以通过作为参考发送或返回新值来实现这一点,就像在另一个答案中一样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    • 2013-02-23
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    相关资源
    最近更新 更多