二进制文件作为垃圾值读入动态数组

时间:2018-03-14 23:56:10

标签: c++ structure binaryfiles dynamic-arrays

您试图完成一些代码并遇到问题。我的程序试图将记录写入二进制文件,然后在调用适当的函数时将其读回。每当我尝试将文件读入动态数组以便我可以格式化输出时,只有垃圾值(我认为地址?)打印在第一个文本之后。

这是我现在正在使用的代码,

#include <iostream>
#include<iomanip>
#include <fstream>
using namespace std;

struct Inventory
{
 char desc[30];
 int qty;
 double wholeSaleCost;
};

// Function prototypes
void addRecord(fstream &);
void viewRecord(fstream &);
void changeRecord(fstream &);
bool validInput(char userInput);
// This function will add a record to the file
void addRecord(fstream &inventoryFile)
{
    Inventory recordUserInput;
    cin.ignore();
    char *tempWholeSale;
    char *tempQuantity;
    tempWholeSale = new char[sizeof(Inventory().wholeSaleCost)];
    tempQuantity = new char[sizeof(Inventory().qty)];



    cout << "Enter the following inventory data:" << endl;

    cout << "Description: ";
    cin.getline(recordUserInput.desc, sizeof(Inventory().desc));
    cout << endl;

    cout << "Quantity: ";
    cin.getline(tempQuantity, sizeof(Inventory().qty));
    while (!validInput(*tempQuantity))
    {
        cout << "That is not a valid input, please enter a number greater than 0." << endl;
        cout << "Quantity: ";
        cin.getline(tempQuantity, sizeof(Inventory().qty));
    }

    recordUserInput.qty = atoi(tempQuantity);
    cout << endl;


    cout << "Retail Price: ";
    cin.getline(tempWholeSale, sizeof(Inventory().wholeSaleCost));
    while (!validInput(*tempWholeSale))
    {
        cout << "That is not a valid input, please enter a number greater than 0." << endl;
        cout << "Retail Price: ";
        cin.getline(tempWholeSale, sizeof(Inventory().wholeSaleCost));
    }
    recordUserInput.wholeSaleCost = atof(tempWholeSale);
    cout << endl;



    // Adding record to the end of a binary file
    inventoryFile.open("C:/temp/inventory.dat", ios::out | ios::app | ios::binary);

    if (inventoryFile)
    {
        inventoryFile.write(reinterpret_cast<const char*>(&recordUserInput.desc), sizeof(Inventory().desc));
        inventoryFile.write(reinterpret_cast<const char*>(&recordUserInput.qty), sizeof(Inventory().qty));
        inventoryFile.write(reinterpret_cast<const char*>(&recordUserInput.wholeSaleCost), sizeof(Inventory().wholeSaleCost));
        inventoryFile.close();
    }
    else
    {
        cout << "File Failed to open." << endl;
    }

}

void viewRecord(fstream &inventoryFile)
{
    int recordNumber;
    char * recordReadFromFile;
    int recordIterator = 0;
    recordReadFromFile = new char[sizeof(Inventory)];


    cout << "Enter the record number of the item: ";
    cin >> recordNumber;
    cin.ignore();
    cout << endl;

    // Reading from file

    inventoryFile.open("C:/temp/inventory.dat", ios::in | ios::binary);



    if (inventoryFile)
    {
        inventoryFile.seekg((sizeof(Inventory)*recordNumber), ios::beg);
        inventoryFile.read(recordReadFromFile, sizeof(Inventory));
        inventoryFile.close();
    }
    else
    {
        cout << "File Failed to open." << endl;
    }


    //Record Display
    cout << "Description: ";
    for (recordIterator; recordIterator < 32; )
    {
        cout << recordReadFromFile[recordIterator];
        recordIterator++;
    }

    cout << endl << "Quantity: ";
    for (recordIterator; recordIterator < 38; )
    {
        cout << recordReadFromFile[recordIterator];
        recordIterator++;
    }

    cout << endl << "Retail Price: ";
    for (recordIterator; recordIterator < 48; )
    {
        cout << recordReadFromFile[recordIterator];
        recordIterator++;
    }
}

Main只有一个if / else块来调用不同的函数。我正在使用的fstream对象是&f; fstream inventoryFile&#39;

cout显示的数字来自使用sizeof(Inventory.desc)等,我发现inv.desc是30个字节,.qty是4个字节而.wholeSale是8个字节(预期)但是我可以&# 39;在单独编写每个结构成员时找到解决缓冲区问题的方法。非常感谢任何可以提供的帮助,通过这两个问题使我陷入停滞。

1 个答案:

答案 0 :(得分:0)

尝试更像这样的事情:

#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <sstream>
#include <limits>

#pragma pack(push, 1) // or your compiler's equivilent...
struct Inventory
{
    char desc[30];
    int qty;
    double wholeSaleCost;
};
#pragma pack(pop)

// Function prototypes
void addRecord();
void viewRecord();
void changeRecord();

void resetInput()
{
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');            
    std::cin.clear();
}

template<typename T>
void promptforNumber(const char *prompt, T &value)
{
    do
    { 
        std::cout << prompt << ": ";
        if (std::cin >> value)
        {
            if (value >= T(0))
                break;

            std::cout << "Please enter a number greater than or equal to 0." << std::endl;
        }
        else
        {
            resetInput();
            std::cout << "That is not a valid number, please try again." << std::endl;
        }
    }
    while (true);
}

void promptforRecordData(Inventory &item)
{
    std::cout << "Enter the following inventory data:" << endl;    

    do
    {
        std::cout << "Description: ";
        if (std::cin.getline(item.desc, sizeof(item.desc)))
            break;

        resetInput();
        std::cout << "Please enter a string less than " << sizeof(item.desc) << " chars." << std::endl;
    }
    while (true);
    std::cout << std::endl;

    promptforNumber("Quantity", item.qty);
    std::cout << std::endl;

    promptforNumber("Retail Price", item.wholeSaleCost);
    std::cout << std::endl;
}

void displayRecord(const Inventory &item)
{
    std::cout << "Description: " << item.desc << std::endl;
    std::cout << "Quantity: " << item.qty << std::endl;
    std::cout << "Retail Price: " << item.wholeSaleCost << std::end;
}

bool readRecord(std::istream &in, Inventory &item)
{
    if (!in.read(reinterpret_cast<char*>(&item), sizeof(item)))
        std::cout << "Failed to read inventory item." << std::endl;
    return in.good();
}

bool writeRecord(std::ostream &out, const Inventory &item)
{
    if (!out.write(reinterpret_cast<const char*>(&item), sizeof(item)))
        std::cout << "Failed to write inventory item." << std::endl;
    return out.good();
}

bool seekInToRecord(std::istream &in, int recordNumber)
{
    if (!in.seekg(sizeof(Inventory) * recordNumber))
        std::cout << "Failed to seek file." << std::endl;
    return in.good();
}

bool seekOutToRecord(std::ostream &out, int recordNumber)
{
    if (!out.seekp(sizeof(Inventory) * recordNumber))
        std::cout << "File Failed to seek." << std::endl;
    return out.good();
}

// This function will add a record to the file
void addRecord()
{
    Inventory inventoryItem;    
    promptforRecordData(inventoryItem);

    // Adding record to the end of a binary file
    std::ofstream inventoryFile("C:/temp/inventory.dat", std::ios::app | ios::binary);    
    if (!inventoryFile.is_open())
    {
        std::cout << "Failed to open file." << std::endl;
        return;
    }

    writeRecord(inventoryFile, inventoryItem);
}

// This function will display a record from the file
void viewRecord()
{
    int recordNumber;
    promptForNumber("Enter the record number of the item", recordNumber);
    std::cout << endl;

    // Reading from file    

    std::ifstream inventoryFile("C:/temp/inventory.dat", std::ios::binary);
    if (!inventoryFile.is_open())
    {
        std::cout << "Failed to open file." << std::endl;
        return;
    }

    if (recordNumber > 0)
    {
        if (!seekInToRecord(inventoryFile, recordNumber))
            return;
    }

    Inventory inventoryItem;
    if (!readRecord(inventoryFile, inventoryItem))
        return;

    inventoryFile.close();

    //Record Display
    displayRecord(inventoryItem);
}

// This function will change a record in the file
void changeRecord()
{
    int recordNumber;    
    promptForNumber("Enter the record number of the item", recordNumber);
    std::cout << endl;

    // Reading from file

    std::fstream inventoryFile("C:/temp/inventory.dat", std::ios::in | std::ios::out | std::ios::binary);
    if (!inventoryFile.is_open())
    {
        std::cout << "File Failed to open." << std::endl;
        return;
    }

    if (recordNumber > 0)
    {
        if (!seekInToRecord(inventoryFile, recordNumber))
            return;
    }

    Inventory inventoryItem;
    if (!readRecord(inventoryFile, inventoryItem))
        return;

    //Record Display
    displayRecord(inventoryItem);

    // Overwrite record in binary file
    promptForRecordData(inventoryItem);
    if (seekOutToRecord(inventoryFile, recordNumber))
        writeRecord(inventoryFile, inventoryItem);
}