C++类中包含string类型数据使用read和write实现文件读取和输出时遇到的问题

本人一渣,曾经遇到这样的问题:

类中包含string类型的数据,在使用read和write时,程序运行会崩溃。听学长介绍,string不是一整块内存都是字符串数据的,是有比较复杂的内存管理的,read进去不做处理是没什么问题,但是退出函数时定义的类的对象会析构,然后也会调用string类型数据的析构,这时候会导致内存混乱。想用getline函数解决这个问题,后来发现类中有int类型数据时会导致int后的数据在读取时出错。

打算将类中的string类型换成char类型,就可以解决这个问题,但是又觉得string类型用着比char要舒服,而且类已经写完,不想再改,所以采取一种折中的方法,在输出时采用一般的"file<<"的输出方法,只是在读取时,先按照char类型读取,再将char类型转换为string类型和int类型。

代码如下:

class Book_Number_Info
{
public:
    Book_Number_Info(){}
    Book_Number_Info(string isbn,string book_number,int status)
    {
        ISBN = isbn;
        Book_Number = book_number;
        Status = status;
    }
    void SetBook_Number(string book_number)
    {
        Book_Number = book_number;
    }
    void SetStatus(int status)
    {
        Status =  status;
    }
    string returnISBN()
    {
        return ISBN;
    }
    string returnBook_Number()
    {
        return Book_Number;
    }
    int returnStatus()
    {
        return Status;
    }
private:
    string ISBN;
    string Book_Number;
    int Status;
};



void NumberOut(string name)
{
    string filename = name + ".txt";
    ofstream file(filename.c_str(),ios_base::out);
    vector<Book_Number_Info>::iterator its;
    if(!file.is_open())
    {
        ypos++;     gotoxy(xpos,ypos);
        cout<<"#         文件输出失败!         #"<<endl;
        return ;
    }
    for(its=numberlist.begin();its!=numberlist.end();its++)
    {
        file<<(*its).returnISBN()<<endl;
        file<<(*its).returnBook_Number()<<endl;
        file<<(*its).returnStatus()<<endl;
    }
    vector<Book_Number_Info>(numberlist).swap(numberlist);
    //清空vector容器
    file.close();
    return;
}


void NumberIn(string name)
{
    string filename = name + ".txt";
    ifstream file;
    file.open(filename.c_str());
    if(!file.is_open())
    {
        ypos++;     gotoxy(xpos,ypos);
        cout<<"#         文件读取失败!         #"<<endl;
        return ;
    }
    char isbn[20],booknumber[20],status[5];
    string ISBN,Book_Number;
    int Status;
    while(true)
    {
        if(!file.getline(isbn,20))
            break;
        file.getline(booknumber,20);
        file.getline(status,5);
        ISBN = isbn;
        Book_Number = booknumber;
        Status = atoi(status);
        //atoi()函数用于将char类型转换为int类型,包含在头文件<stdlib.h>中
        Book_Number_Info temp(ISBN,Book_Number,Status);
        numberlist.push_back(temp);
    }
    file.close();
    return;
}



这是本人的方法,如果有别的方法,还请分享

可以使用以下库来读取和处理.dbf、.sbn、.shx和.abx文件: 1. libdbf - 用于读取和处理.dbf文件C++库。 2. ShapeLib - 用于读取和处理.shp、.shx和.dbf文件C++库。 3. libSHP - 用于读取和处理.shp、.shx和.dbf文件C++库。 4. MapServer - 用于读取和处理.shp、.sbn、.shx和.abx文件C++库。 要加水印并输出到其他文件,您可以使用以下步骤: 1. 从原始文件读取数据。 2. 在内存中对数据进行处理,加入水印。 3. 将处理后的数据写入新文件中。 以下是代码示例: ```c++ #include <iostream> #include <fstream> #include <string> #include <vector> #include "libdbf/dbf_file.h" #include "ShapeLib/shapefil.h" int main() { // 读取.dbf文件 DBFHandle hDBF = DBFOpen("data.dbf", "rb"); if (hDBF == nullptr) { std::cerr << "Error: Unable to open data.dbf" << std::endl; return 1; } int nRecords = DBFGetRecordCount(hDBF); int nFields = DBFGetFieldCount(hDBF); // 读取.shp、.shx和.dbf文件 SHPHandle hSHP = SHPOpen("data.shp", "rb"); if (hSHP == nullptr) { std::cerr << "Error: Unable to open data.shp" << std::endl; return 1; } // 创建输出文件 DBFHandle hDBFOut = DBFCreate("data_out.dbf"); if (hDBFOut == nullptr) { std::cerr << "Error: Unable to create data_out.dbf" << std::endl; return 1; } SHPHandle hSHPOut = SHPCreate("data_out.shp", SHPT_POINT); if (hSHPOut == nullptr) { std::cerr << "Error: Unable to create data_out.shp" << std::endl; return 1; } // 复制.dbf字段 for (int i = 0; i < nFields; i++) { const char* pszFieldName = DBFGetFieldName(hDBF, i); DBFFieldType eType = DBFGetFieldInfo(hDBF, i, nullptr, nullptr); int nWidth = DBFGetFieldWidth(hDBF, i); int nDecimals = DBFGetFieldDecimals(hDBF, i); if (DBFAddField(hDBFOut, pszFieldName, eType, nWidth, nDecimals) == -1) { std::cerr << "Error: Unable to add field " << pszFieldName << std::endl; return 1; } } // 处理.shp文件 for (int i = 0; i < nRecords; i++) { SHPObject* pSHP = SHPReadObject(hSHP, i); if (pSHP == nullptr) { std::cerr << "Error: Unable to read object " << i << std::endl; return 1; } // 在内存中添加水印 std::vector<double> adfX(pSHP->nVertices); std::vector<double> adfY(pSHP->nVertices); for (int j = 0; j < pSHP->nVertices; j++) { adfX[j] = pSHP->padfX[j]; adfY[j] = pSHP->padfY[j]; } // TODO: 在坐标中添加水印 // 在新文件中写入.shp对象 SHPObject* pSHPOut = SHPCreateObject(pSHP->nSHPType, pSHP->nShapeId, pSHP->nParts, pSHP->panStart, pSHP->panLength, pSHP->nVertices, &adfX[0], &adfY[0], nullptr, nullptr); if (pSHPOut == nullptr) { std::cerr << "Error: Unable to create output object " << i << std::endl; return 1; } if (SHPWriteObject(hSHPOut, -1, pSHPOut) == -1) { std::cerr << "Error: Unable to write output object " << i << std::endl; return 1; } SHPDestroyObject(pSHPOut); // 在新文件中写入.dbf记录 for (int j = 0; j < nFields; j++) { const char* pszFieldName = DBFGetFieldName(hDBF, j); DBFFieldType eType = DBFGetFieldInfo(hDBF, j, nullptr, nullptr); int nWidth = DBFGetFieldWidth(hDBF, j); int nDecimals = DBFGetFieldDecimals(hDBF, j); switch (eType) { case FTString: { const char* pszValue = DBFReadStringAttribute(hDBF, i, j); if (DBFWriteStringAttribute(hDBFOut, i, j, pszValue) == false) { std::cerr << "Error: Unable to write string attribute " << pszFieldName << std::endl; return 1; } break; } case FTInteger: { int nValue = DBFReadIntegerAttribute(hDBF, i, j); if (DBFWriteIntegerAttribute(hDBFOut, i, j, nValue) == false) { std::cerr << "Error: Unable to write integer attribute " << pszFieldName << std::endl; return 1; } break; } case FTDouble: { double dfValue = DBFReadDoubleAttribute(hDBF, i, j); if (DBFWriteDoubleAttribute(hDBFOut, i, j, dfValue) == false) { std::cerr << "Error: Unable to write double attribute " << pszFieldName << std::endl; return 1; } break; } case FTLogical: { bool bValue = DBFReadLogicalAttribute(hDBF, i, j); if (DBFWriteLogicalAttribute(hDBFOut, i, j, bValue) == false) { std::cerr << "Error: Unable to write logical attribute " << pszFieldName << std::endl; return 1; } break; } default: break; } } } // 关闭文件 DBFClose(hDBF); SHPClose(hSHP); DBFClose(hDBFOut); SHPClose(hSHPOut); return 0; } ``` 请注意,此示例仅用于演示如何读取和处理这些文件。要添加水印,您需要编写自己的代码来修改内存中的数据
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值