C++ 如何将类值指定给向量<;字符串>;?

C++ 如何将类值指定给向量<;字符串>;?,c++,C++,我有一个很大的文本文件,其中每一行代表一个有邮政编码和州的城市。 它是这样写的: Brandenburg 35432 Potsdamm Niedersachsen 35698 Hannover 我已经阅读了向量中的文件,并且已经编写了一个类,希望将类值分配给向量 class City { private: float lat; //latitude float lon; //longitude public: City city

我有一个很大的文本文件,其中每一行代表一个有邮政编码和州的城市。 它是这样写的:

Brandenburg  35432 Potsdamm
Niedersachsen 35698 Hannover
我已经阅读了向量中的文件,并且已经编写了一个类,希望将类值分配给向量

class City
{
    private:
        float lat; //latitude
        float lon; //longitude
    public:
        City cityclass(std::string state, std::string zipCode, std::string name);
        //std::string name;
        //std::string state;
        //std::string zipCode;

        float getLatitude() const
        {
            return lat;
        }
        float getLongitude() const
        {
            return lon;
        }
};
因此,我有一个包含std::string zipCode、state和cityname的类。我认为这将是更好的工作,尤其是当我想能够搜索城市的邮政编码或名称。 我怎样才能意识到这一点?我想简单地修改我的while循环,如下所示,但我真的不确定这是否是一种方式。 这是我的全部代码:

class City
{
    private:
        /*float lat; //latitude
        float lon; //longitude*/
    public:
        std::string zipCode;
        std::string name;
        std::string state;

        /*float getLatitude() const
        {
            return lat;
        }
        float getLongitude() const
        {
            return lon;
        }*/
};

int main ()
{
    std::ifstream input("bundesland_plz_ort_de.txt");
    //initilazing a vector of type string to store the data
    std::vector<City> cityVector;
    City city; //creating instance of class


    //check if file can be accessed
    if(!input)
    {
        std::cout << "ERROR!\tFile could not be opened!" << std::endl;
    }
    else
    {   

        while(input >> city.state >> city.zipCode >> city.name)
        {
            cityVector.push_back(city);
        }
        input.close(); // close after finishing
    }
}
class城市
{
私人:
/*浮动纬度;//纬度
float lon;//经度*/
公众:
std::字符串zipCode;
std::字符串名;
std::字符串状态;
/*浮点getLatitude()常量
{
返回lat;
}
float getLongitude()常量
{
返回离子;
}*/
};
int main()
{
std::ifstream输入(“bundesland_plz_ortu de.txt”);
//初始化字符串类型的向量以存储数据
std::矢量城市矢量;
City;//正在创建类的实例
//检查文件是否可以访问
如果(!输入)
{
std::cout city.state>>city.zipCode>>city.name)
{
城市导向器。推回(城市);
}
input.close();//完成后关闭
}
}

我建议采用稍微不同的方法。您定义了一个类City,但读取了该类之外的数据

C++中,我们应该把数据放在那些数据上的操作上,所有的操作都在一个类中。在这种情况下,您将(在您的类中)覆盖inserter和extractor操作符。这个类知道如何读写它的数据。即使稍后更改算法,其余代码也可以不经修改地工作

在下面的示例代码中,我放置了一个超简单的提取器和插入器(无错误检查)。从源文件读取所有数据只是一个简单的语句

它是使用其范围构造函数将变量“cl”定义为
std::vector
。非常简短

std::vector的范围构造函数的用法

我们可以在没有模板参数的情况下定义std::vector。编译器可以从给定的函数参数推断参数。此功能称为CTAD(“类模板参数推断”)

此外,您可以看到,我没有明确地使用“end()”-迭代器

此迭代器将从空括号内的初始值设定项列表中构造,类型正确,因为由于std::vector构造函数需要,它将被推断为与第一个参数的类型相同

如前所述修改类后,您可以使用std库中的所有
算法

请参阅:

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <fstream>

struct City {
    // Data
    std::string state{};
    std::string zipCode{};
    std::string name{};

    // Member functions
    // Extractor
    friend std::istream& operator >> (std::istream& is, City& c) {
        return is >> c.state >> c.zipCode >> c.name;
    }
    // Inserter
    friend std::ostream& operator << (std::ostream& os, const City& c) {
        return os << "\nState:    " << c.state << "\nZip Code: " << c.zipCode << "\nName:     " << c.name;
    }
};

int main() {

    // Try to open file and check, if it worked
    if (std::ifstream sourceFile("r:\\bundesland_plz_ort_de.txt"); sourceFile) {

        // Read complete source file into a city list
        std::vector cl(std::istream_iterator<City>(sourceFile), {});

        // Give some Debug output
        std::copy(cl.begin(), cl.end(), std::ostream_iterator<City>(std::cout, "\n"));
    }
    else {
        std::cerr << "\nError: Source file could not be opened\n";
    }
}
#包括
#包括
#包括
#包括
#包括
#包括
结构城市{
//资料
std::字符串状态{};
std::字符串zipCode{};
std::字符串名{};
//成员函数
//提取器
friend std::istream&operator>>(std::istream&is,City&c){
返回值为>>c.state>>c.zipCode>>c.name;
}
//插入器

friend std::ostream&operator我推荐一种稍有不同的方法。您定义了一个类城市,但您读取的数据不在类中

在C++中,我们应该把数据放在那些在数据上运行的操作中,所有的都在一个类中。在这种情况下,你将(在你的类中)覆盖插入器和提取器操作符。该类知道,如何读取和写入它的数据。即使你在稍后改变算法,其余的代码也将不修改。 在下面的示例代码中,我放置了一个超简单的提取器和插入器(无错误检查)。从源文件读取所有数据只需一条简单的语句

这是变量“cl”的定义,即使用其范围构造函数将其定义为
std::vector
。非常简短

std::vector的范围构造函数的用法

我们可以在没有模板参数的情况下定义std::vector。编译器可以从给定的函数参数推断参数。此功能称为CTAD(“类模板参数推断”)

此外,您可以看到,我没有明确地使用“end()”-迭代器

此迭代器将从空括号内的初始值设定项列表中构造,类型正确,因为由于std::vector构造函数需要,它将被推断为与第一个参数的类型相同

如前所述修改类后,您可以使用std库中的所有
算法

请参阅:

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <fstream>

struct City {
    // Data
    std::string state{};
    std::string zipCode{};
    std::string name{};

    // Member functions
    // Extractor
    friend std::istream& operator >> (std::istream& is, City& c) {
        return is >> c.state >> c.zipCode >> c.name;
    }
    // Inserter
    friend std::ostream& operator << (std::ostream& os, const City& c) {
        return os << "\nState:    " << c.state << "\nZip Code: " << c.zipCode << "\nName:     " << c.name;
    }
};

int main() {

    // Try to open file and check, if it worked
    if (std::ifstream sourceFile("r:\\bundesland_plz_ort_de.txt"); sourceFile) {

        // Read complete source file into a city list
        std::vector cl(std::istream_iterator<City>(sourceFile), {});

        // Give some Debug output
        std::copy(cl.begin(), cl.end(), std::ostream_iterator<City>(std::cout, "\n"));
    }
    else {
        std::cerr << "\nError: Source file could not be opened\n";
    }
}
#包括
#包括
#包括
#包括
#包括
#包括
结构城市{
//资料
std::字符串状态{};
std::字符串zipCode{};
std::字符串名{};
//成员函数
//提取器
friend std::istream&operator>>(std::istream&is,City&c){
返回值为>>c.state>>c.zipCode>>c.name;
}
//插入器
friend std::ostream&operator继续
首先通过一个循环获得对象的大致数目,然后在该循环之前计算以空格分隔的字符串的总数,然后除以成员数据的数目

 // ...
 //City city; //creating instance of class


 if(!input)
    {
        std::cout << "ERROR!\tFile could not be opened!" << std::endl;
    }
 else if (input.is_open())  {

    string buf(25);
    int i=0;
    while( input >> buf) ++i;

    std::vector<City> cityVector(i /3 +5);   // the number of member data plus some extra for sureness

    input.clear();
    input.seekg(0, ios::beg);                // point back to start
    i=0;
        while( input >> cityVector[i].state >> cityVector[i].zipCode >> cityVector[i].name) ++i;


    input.close(); // close after finishing
    }

  //..
/。。。
//City;//正在创建类的实例
如果(!输入)
{
标准:cout-buf)+i;
std::vector cityVector(i/3+5);//成员数据的数量加上一些额外的数据以确保
input.clear();
input.seekg(0,ios::beg);//指向后面开始
i=0;
while(输入>>cityVector[i].state>>cityVector[i].zipCode>>cityVector[i].name)++i;
input.close();//完成后关闭
}
//..
这种方法需要提前估计阵列大小,再加上一些保护量,然后可以调整大小,重新安装,例如调整cityVector.resize(i+1)

继续
首先获取