简体   繁体   English

如何将类值分配给向量<string> ?

[英]How to assign class values to vector<string>?

I have a large textfile in which each line represents a city with postalcode and state.我有一个大文本文件,其中每一行都代表一个带有邮政编码和州的城市。 It is written like this:它是这样写的:

Brandenburg  35432 Potsdamm
Niedersachsen 35698 Hannover

I've already read the file in a vector and I have written a class and want to assign the classvalues to the vector.我已经在向量中读取了文件,并且我编写了一个类并希望将类值分配给向量。

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;
        }
};

So I have a class with std::string zipCode, the state and the cityname.所以我有一个带有 std::string zipCode、州和城市名的类。 I assume that this would be better to work with, especially when I want to be able to search for city's by zip or name.我认为这会更好地使用,尤其是当我希望能够通过 zip 或名称搜索城市时。 How can I realize this?我怎么能意识到这一点? I thought about to simply modify my while-loop as it follows, but I'm realy not sure if this is the way to go.我想简单地修改我的 while 循环,但我真的不确定这是否是要走的路。 Here is my full code:这是我的完整代码:

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
    }
}

I would recommend a slightly different approach.我会推荐一种稍微不同的方法。 You defined a class City, but you read the data outside of the class.您定义了一个类 City,但是您读取了该类之外的数据。

In C++ we should put data on operations that are working on that data, all in one class.在 C++ 中,我们应该将数据放在处理该数据的操作上,所有这些都在一个类中。 In this case you would (in your class) overwrite the inserter and extractor operator.在这种情况下,您将(在您的班级中)覆盖插入器和提取器运算符。 The class knows, how to read and write its data.该类知道如何读取和写入其数据。 Even if you change the algorithm later, the rest of the code will work without modification.即使您稍后更改算法,其余代码也无需修改即可运行。

In the following example code I put an ultra simple extractor and inserter (No error checking).在下面的示例代码中,我放置了一个超简单的提取器和插入器(无错误检查)。 Reading all data from the source file is then just one simple statement.从源文件中读取所有数据只是一个简单的语句。

It is the definition of the variable "cl" as std::vector , using its range constructor.它是使用其范围构造函数将变量“cl”定义为std::vector Very short and simple.非常简短和简单。

Usage of range constructor for std::vector. std::vector 的范围构造函数的使用。

We can define the std::vector without template argument.我们可以在没有模板参数的情况下定义 std::vector。 The compiler can deduce the argument from the given function parameters.编译器可以从给定的函数参数中推导出参数。 This feature is called CTAD ("class template argument deduction").此功能称为 CTAD(“类模板参数推导”)。

Additionally, you can see that I do not use the "end()"-iterator explicitely.此外,您可以看到我没有明确使用“end()”-迭代器。

This iterator will be constructed from the empty brace-enclosed initializer list with the correct type, because it will be deduced to be the same as the type of the first argument due to the std::vector constructor requiring that.该迭代器将从具有正确类型的空的大括号括起来的初始化列表中构造,因为由于 std::vector 构造函数要求,它将被推导出与第一个参数的类型相同。

Having modified the class as described, you can then use all algorithm from the std library.按照所述修改类后,您可以使用 std 库中的所有algorithm

Please see:请参见:

#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";
    }
}

Of course there are many other possible solutions .当然还有许多其他可能的解决方案。 . . . .

just go on什么都别管,继续
first obtaining the number of object approximately by a loop precede it to count the total space delimited string then it's divided by the number of member data首先通过循环获得大约对象的数量,然后计算总空格分隔的字符串,然后除以成员数据的数量

 // ...
 //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
    }

  //..

this way need estimate the array size earlier approximately plus some guarding amount, then can resize, refit it eg.这种方式需要更早地估计数组大小加上一些保护量,然后可以调整大小,重新调整它,例如。 cityVector.resize(i+1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM