如何从文本文件中读取数据到结构的int数组?

时间:2019-07-28 21:14:33

标签: c++ arrays class struct io

我创建了一个RentalAgency结构,其中包含名称,邮政编码和库存。我还创建了一个包含库存成员的RentalCar类。我试图将数据从文本文件读入各个位置,但遇到了麻烦。

struct RentalAgency {
    char name[25]; //25 characters max
    int zipcode[5]; //5 digits in zipcode
    RentalCar inventory[5]; //5 cars
};


class RentalCar {
    int m_year;
    char m_make[256], m_model[256]; //256 characters max
    float m_price;
    bool m_available;

    public:
    RentalCar();
    RentalCar(int, char[], char[], float, bool);
    void setYear(int);
    void setMake(char[]);
    void setModel(char[]);
    void setPrice(float);
    void setAvailable(bool);
    int getYear();
    char* getMake();
    char* getModel();
    float getPrice();
    bool getAvailable();
    void print();
    float estimateCost(int);
};

我正在尝试从此文本文件中读取。

Hertz 93619
2014 Toyota Tacoma 115.12 1
2012 Honda CRV 85.10 0
2015 Ford Fusion 90.89 0
2013 GMC Yukon 110.43 0
2009 Dodge Neon 45.25 1   

Alamo 89502
2011 Toyota Rav4 65.02 1
2012 Mazda CX5 86.75 1
2016 Subaru Outback 71.27 0
2015 Ford F150 112.83 1
2010 Toyota Corolla 50.36 1

Budget 93035
2008 Ford Fiesta 42.48 0
2009 Dodge Charger 55.36 1
2012 Chevy Volt 89.03 0
2007 Subaru Legacy 59.19 0
2010 Nissan Maxima 51.68 1  

到目前为止,我已经设置了一个读取数据的功能。我已经成功创建了一个for循环,该循环读取了Rental Agency的名称,但是在邮政编码方面我陷入了困境。

void input(struct RentalAgency data[])
{
    char inputFile[50]; //50 characters max
    char tmp;
    std::ifstream inputStream;

    std::cout << "Enter input file name: ";
    std::cin >> inputFile;

    inputStream.open(inputFile);

    for(int i = 0; i < 3; i++) //3 agencies 
    {   
        inputStream >> data[i].name;

        for(int j = 0; j < 5; j++)
        {
            inputStream >> tmp;

            data[i].zipcode[j] = tmp;   
        }
    }

}

我打印数据时的输出是:

data[0].name = Hertz //correct
data[0].zipcode[0] = 57 //wrong
data[0].zipcode[1] = 51 //wrong
data[0].zipcode[2] = 54 //wrong
data[0].zipcode[3] = 49 //wrong
data[0].zipcode[4] = 57 //wrong

我想要的是:

data[0].zipcode[0] = 9
data[0].zipcode[1] = 3
data[0].zipcode[2] = 6
data[0].zipcode[3] = 1
data[0].zipcode[4] = 9

2 个答案:

答案 0 :(得分:0)

您要在邮政编码中存储字符0-9的{​​{3}}值。您需要从读取的字符中减去0的ASCII值:

for(int j = 0; j < 5; j++)
{
    inputStream >> tmp;
    data[i].zipcode[j] = tmp - '0';
}

答案 1 :(得分:0)

请在下面找到一个完整的可行解决方案,包括您的讲师的无意义限制。

所以,我们在这里做,通常没人会做。

  • 使用char数组而不是字符串(为什么?这是什么废话)
  • 使用普通的老式C样式数组
  • 使用幻数代替数组大小,而不使用动态大小。
  • 使用原始指针!
  • 使用设置器和吸气器进行一切操作,制动封装
  • 返回指向成员变量的指针

该程序严格依赖于确切的输入格式,这也不是很好。

更灵活的方法会更好

#include <iostream>
#include <sstream>
#include <fstream>
#include <iterator>
#include <algorithm>

std::istringstream inputFile{ R"(Hertz 93619
2014 Toyota Tacoma 115.12 1
2012 Honda CRV 85.10 0
2015 Ford Fusion 90.89 0
2013 GMC Yukon 110.43 0
2009 Dodge Neon 45.25 1

Alamo 89502
2011 Toyota Rav4 65.02 1
2012 Mazda CX5 86.75 1
2016 Subaru Outback 71.27 0
2015 Ford F150 112.83 1
2010 Toyota Corolla 50.36 1

Budget 93035
2008 Ford Fiesta 42.48 0
2009 Dodge Charger 55.36 1
2012 Chevy Volt 89.03 0
2007 Subaru Legacy 59.19 0
2010 Nissan Maxima 51.68 1
)" };

constexpr size_t MakeAndModelSize = 256;
constexpr size_t MaxInputLineSize = 1024;
constexpr size_t ZipCodeSize = 5;
constexpr size_t InventorySize = 5;
constexpr size_t NameOfAgenySize = 25;

class RentalCar {

public:
    RentalCar() {
        std::fill(m_make, m_make + MakeAndModelSize, 0);
        std::fill(m_model, m_model + MakeAndModelSize, 0);
    };
    RentalCar(int y, char* make, char* model, float price, bool available) : m_year(y), m_price(price), m_available(available)  {
        std::copy_n(make, MakeAndModelSize, m_make);
        std::copy_n(model, MakeAndModelSize, m_model);
    }

    // I am breaking the whole encapsulation 
    // We make some more noensense and define setters and getters for everything. 
    // so, we can also make all data public . . .
    void setYear(int year) { m_year = year; }
    void setMake(char* make) { std::copy_n(make, MakeAndModelSize, m_make); } 
    void setModel(char* model) { std::copy_n(model, MakeAndModelSize, m_model); }
    void setPrice(float price) { m_price = price; }
    void setAvailable(bool avail) { m_available = avail; }
    int getYear() { return m_year; };
    char* getMake() { return m_make; }; 
    char* getModel() { return m_model; } 
    float getPrice() { return m_price;  }
    bool getAvailable() { return  m_available; };
    void print() { std::cout << *this;  } // This function is not needed. We overlaoded the inserter already for that purpose
    double estimateCost(int days) { return days * m_price * (m_available ? 1.0 : 0.0);}

    // Overload inserter and extractor
    friend std::ostream& operator << (std::ostream& os, const RentalCar& rc) {
        return os << rc.m_year << ' ' << rc.m_make << ' ' << rc.m_model << ' ' << rc.m_price << ' ' << rc.m_available;
    }

    friend std::istream& operator >> (std::istream& is, RentalCar& rc) {
        is >> rc.m_year >> rc.m_make >> rc.m_model >> rc.m_price >> rc.m_available;
        return is;
    }

protected:
    // The data of the car
    int m_year{};
    char m_make[MakeAndModelSize];   // Lord, forgive me, I am using a fixed size plain char array for a string
    char m_model[MakeAndModelSize];  // Lord, forgive me, I am using a fixed size plain char array for a string
    float m_price{ 0.0 };
    bool m_available{ false };
};


class RentalAgency {

public:
    // Extractor operator. Read all data from stream
    friend std::istream& operator >> (std::istream& is, RentalAgency& ra) {
        is >> ra.name ;
        std::copy_n(std::istream_iterator<char>(is), ZipCodeSize, ra.zipcode);
        // Read all inventory data
        std::copy_n(std::istream_iterator<RentalCar>(is), InventorySize, ra.inventory);
        return is;
    }

    // Inserter operator. Output Data
    friend std::ostream& operator << (std::ostream& os, const RentalAgency& ra) {

        // Show name and zip code
        os << ra.name << ' ';
        std::copy_n(ra.zipcode, ZipCodeSize, std::ostream_iterator<char>(os));
        os << '\n';
        // Print inventory data
        std::copy_n(ra.inventory, InventorySize, std::ostream_iterator<RentalCar>(os, "\n"));
        return os << '\n';
    }

protected:
    char name[NameOfAgenySize]{};
    int zipcode[ZipCodeSize]{};
    RentalCar inventory[InventorySize]{};
};

int main()
{
    RentalAgency ra1{};
    RentalAgency ra2{};
    RentalAgency ra3{};

    // Read all data
    inputFile >> ra1 >> ra2 >> ra3;

    // For verification. Write all data to std::cout
    std::cout << ra1 << ra2 << ra3;

    return 0;
}

请注意。我正在重载类的提取器和插入器运算符。这样,阅读和写作就变得非常容易。请参阅主要内容。

然后我从istringstream中读取。但这与从文件读取相同。因此,这里没有文件,所以我选择此解决方案。