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

Cant figure out how to create an structure array based on a certain part of another structure

本文关键字:结构 个部 创建 数组 弄清楚 何基于 另一个      更新时间:2023-10-16

inb4 问题是 - 在我的国家我们有城市,然后城市在更大的事物中,有点像美国的州,所以对于这个任务,我将城市称为城市,而那些更大的事物是州,例如有城市 A、B 和 C。A 和 B 处于状态 X,C 处于状态 Y。

我正在通过做几年前的考试来准备我的考试,有这个任务,它要求你输出到一个文件结构,它由州的名称组成,然后是居住在州最小城市的人数,然后是居住在该州的总人数。一开始,你会得到一个信息文件。第一个数字是该计划必须处理的城市数量,我们称之为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,所以它看起来像这样:

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

在结构中,它看起来像:

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

现在问题来了 - 我需要找到给定城市中有多少个不同的州,并为它们构建一系列结构(结构如下:

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

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

请告诉我如何找到有多少以及有哪些不同的州,我想我可以从那里开始。

这是我到目前为止所做的:

#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 

编辑2:谢谢你的所有答案。我注意到你们中的大多数人都建议使用向量、map、bool 等,但我甚至还没有听说过这些东西,因为我刚刚高中毕业,我的 IT 期末考试是今天。我很高兴地说,我肯定通过了,可能会有大约 85-95%,所以它真的很好。由于我打算在大学学习计算机科学,我将检查您提到的内容,因为我将来可能需要它们。

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

你的城市结构在我看来是合理的。

状态可以是类似

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

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

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() .

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

维尔

纽斯的人口总和:

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
}

看看你拥有什么和你想要什么通常会有所帮助:

您有一个条目列表,每个条目代表一个城市以及一些相关信息。这可以 - 就像你所做的那样 - 很好地打包到一个结构中:

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提供两者)。扩展它以实际适合您的问题。

完整的示例代码。