无法弄清楚如何根据另一个结构的某个部分创建结构数组

时间:2015-06-16 20:40:59

标签: c++ arrays string sorting struct

inb4问题 - 在我的国家,我们有城市,然后城市有更大的东西,有点像美国的州,所以对于这个任务,我会称城市为城市,而那些更重要的东西,例如有城市A,B和C. A和B处于状态X,C处于Y状态。

我正在通过多年前的考试准备我的考试tommorow,并且有这个任务,要求你输出到文件结构,其中包括州的名称,然后是生活在陈述最小的城市,然后是居住在该州的总人数。在开始时,您将获得一个信息文件。 第一个数字是程序必须处理的城市数量,让我们称之为k。然后有很多行,看起来像这样:

例如

CITYNAME STATE NUMBEROFPPL

Buffalo  New York     300000

这是我的信息文件:

15

Vilnius             Vilniaus     541278

Dusetos             Utenos       4211

Alytus              Alytaus      69859

Druskininkai        Alytaus      16890

Ignalina            Utenos       6307

Kavarskas           Utenos       753

Lazdijai            Alytaus      5027

Simnas              Alytaus      1940

Trakai              Vilniaus     5504

Utena               Utenos       33086

Veisiejai           Alytaus      1673

Vievis              Vilniaus     5246

Lentvaris           Vilniaus     11832

Visaginas           Utenos       28438

Zarasai             Utenos       8001 

我可以轻松地读取文件,我构造了一个名为City的结构数组,所以它在main中看起来像这样:

City A[102] // Thats the maximum number of cities

并在struct中看起来像:

struct City 
{ string name;
  string state;
  int peoplelivinginit;
}

现在这就是问题 - 我需要找到给定城市中有多少不同的状态,并为它们构建一个结构数组(结构如下:

string nameofthestate;
string citiesinstate[102];
int overallnumberofpeopleinstate;
int peoplelivinginthesmallestcityofthestate;

我不知道如何在结构数组中找到多少不同的状态,我尝试排序它们然后可能删除重复项,但它听起来像是一个麻烦,我也没有使用排序,因为我们还没有学会如何使用它,我不认为这就是我们应该如何完成这项任务。

请告诉我如何找到有多少和不同的状态,我想我可以从那里开始。

以下是我到目前为止所做的事情:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <algorithm>

using namespace std;
struct City
{
    string name;
    string state;
    int n; //number of people in the city
};

void Read (City A[], int & k)
{
    ifstream fd;
    fd.open("Info.txt");
    fd >> k;
    for (int i = 0; i < k; i++)
    {
        fd.ignore();
        char namee[21];
        fd.get(namee, 21);
        A[i].name = namee;
        char statee[14];
        fd.get(statee, 14);
        A[i].state = statee;
        fd >> A[i].n;
    }
    fd.close();
}


int main()
{
    City A[102];
    int k;
    Read (A, k);
    City B[102] = A;

    for (int i = 0; i < k; i++)
    {
        cout << B[i].name << " " << B[i].state << " " << B[i].n << endl;
    }
    return 0;
}

编辑:::最终结果如下:

3
Utenos   753  80796
Alytaus  1673 95389
Vilniaus 5246 563860 

EDIT2: 感谢您提供所有答案。我注意到你们大多数人都建议使用矢量,地图,布尔等等,但我还没有听说过这些事情,因为我刚读完高中并且今天的期末考试是IT。我很高兴地说我肯定已经过去了,可能会有85-95%,所以它非常好。由于我计划在大学学习计算机科学,我会检查你提到的事情,因为我将来可能会需要它们。

2 个答案:

答案 0 :(得分:1)

你有一个城市,你有关于它的信息,以及概念状态,你只需要知道它包含城市的名称和知识。

你的城市结构对我来说似乎很合理。

状态可以是

std::map<std::string, std::vector<City>> states;

这是一个字符串(将是每个州的名称)到城市列表的有序映射。州的城市列表可以访问状态[&#34;州名称&#34;]就像您对数组一样,除了您使用州名而不是数字。

bool Read (std::map<std::string, std::vector<City>> & states)
{
    int k;
    ifstream fd("Info.txt");
    if (!(fd >> k))
    {
        //bad file. do something.
        return false;
    }
    for (int i = 0; i < k; i++)
    {
        std::string name;
        std::string state;
        int population;

        if (fd >> name >> state >> population)
        {
            City city(name, state, population);
            states[state].push_back(city);
        }  
        else
        {
            //bad file. do something.
            return false;
        }
    }
    return true;
}

在此功能结束时,所有城市都已分配给对象。每个城市对象都被放置在由州组织的列表中。

查找状态数很简单:states.size()

查找Vilniaus的城市数量:states["Vilniaus"].size()

总结Vilniaus的人口:

int sum = 0;
for(City city: states["Vilniaus"])
{
    sum += city.n;
}

最少的人数相似:

int min = std::numeric_limits<int>::max(); // or just use some arbitrary huge number
for(City city: states["Vilniaus"])
{
    if (city.n < min)
    {
        min = city.n;
    }
}

获取状态列表有点棘手,因为地图存储了std::pairstd::pair组状态名称和城市:

for (auto state: states)
{
    string statename = state.first; // City is at state.second
    // do something with statename
}

答案 1 :(得分:0)

通常有助于查看您拥有的和您想要的内容:

您有一个条目列表,每个条目代表一个城市,其中包含一些相关信息。这可以 - 正如你所做的那样 - 很好地融入了一个结构:

struct CityEntry {
    string name;
    string state;
    unsigned int inhabitants;
};

您需要一个状态列表,其中包含必须根据您的输入计算的一些信息。所以你也可以试着把它放到一个结构中:

struct StateEntry {
    string name;
    unsigned int total_inhabitants;
    unsigned int lowest_inhabitants;
};

,还有一个额外要求:唯一性。您不希望具有相同名称的上述结构的多个实例。因此实际上对于每个(州的)名称,只有一个相关的“包”信息。这是一种非常常见的模式,因此有一个解决方案:std::map

您可以将州的每个名称映射到其相关信息:

struct StateInhabitants {
    unsigned int total;
    unsigned int lowest;
    // constructor needed, see full source
};
// ... map<string, StateInhabitants> 

这是“我想要的”的表示。接下来,您需要将“我拥有的”转换为“我想要的”。由于您的输入是一个列表,其元素之间没有任何依赖关系,您可以简单地迭代它,提取 您需要的信息:

vector<CityEntry> cities = read_cities();
map<string, StateInhabitants> state_info;
for (CityEntry const & city : cities) {
    // accessing an entry of a map via operator[] creates
    // the entry if it isn't there yet.
    StateInhabitants & inhabitants = state_info[city.state];
    inhabitants.total += city.inhabitants;
    inhabitants.lowest = std::min(inhabitants.lowest, city.inhabitants);
}

最后,您可以通过迭代地图来打印结果。

您可能会问我为什么不为每个州存储州的城市:在这种情况下,我会尝试关注YAGNI。存储它们会增加复杂性:因为它不是我打算作为解决方案呈现的表示,我需要另一步将该中间表示转换为最终表示。

当然,除非您确实需要每个州的城市列表。

所以,总结一下:看看你有什么,看看你想要什么,包括可能相当隐藏的要求(例如在这种情况下的唯一性)。搜索是否有部分解决方案符合您的要求(std::set提供唯一性但没有其他信息,std::map同时提供这两种信息。扩展它以实际适合您的问题。

Full example code.