filling a three-value tuple with contents from file

I have this file:
Afghanistan,Afghan afghani,AFN
Akrotiri and Dhekelia,European euro,EUR
Aland Islands,European euro,EUR
Albania,Albanian lek,ALL
Algeria,Algerian dinar,DZD
American Samoa,United States dollar,USD
Andorra,European euro,EUR
Angola,Angolan kwanza,AOA
Anguilla,East Caribbean dollar,XCD
Antigua and Barbuda,East Caribbean dollar,XCD
Argentina,Argentine peso,ARS
Armenia,Armenian dram,AMD
Aruba,Aruban florin,AWG
Ascension Island,Saint Helena pound,SHP
Australia,Australian dollar,AUD
Austria,European euro,EUR
Azerbaijan,Azarbaijan manat,AZN
Bahamas,Bahamian dollar,BSD
Bahrain,Bahraini dinar,BHD
Bangladesh,Bangladeshi taka,BDT
Barbados,Barbadian dollar,BBD
Belarus,Belarusian ruble,BYN
Belgium,European euro,EUR
Belize,Belize dollar,BZD
Benin,West African CFA franc,XOF
Bermuda,Bermudian dollar,BMD
Bhutan,Bhutanese ngultrum,BTN
Bolivia,Bolivian boliviano,BOB
Bonaire,United States dollar,USD
Bosnia and Herzegovina,Bosnia and Herzegovina convertible mark,BAM
Botswana,Botswana pula,BWP
Brazil,Brazilian real,BRL
British Indian Ocean Territory,United States dollar,USD
British Virgin Islands,United States dollar,USD
Brunei,Brunei dollar,BND
Bulgaria,Bulgarian lev,BGN
Burkina Faso,West African CFA franc,XOF
Burundi,Burundi franc,BIF
Cabo Verde,Cape Verdean escudo,CVE
Cambodia,Cambodian riel,KHR
Cameroon,Central African CFA franc,XAF
Canada,Canadian dollar,CAD
Caribbean Netherlands,United States dollar,USD
Cayman Islands,Cayman Islands dollar,KYD
Central African Republic,Central African CFA franc,XAF
Chad,Central African CFA franc,XAF
Chatham Islands,New Zealand dollar,NZD
Chile,Chilean peso,CLP
China,Chinese Yuan Renminbi,CNY
Christmas Islands,Australian dollar,AUD
Cocos (Keeling) Islands,Australian dollar,AUD
Colombia,Colombian peso,COP
Comoros,Comorian franc,KMF
Democratic Republic of Congo,Congolese franc,CDF
Repubic of Congo,Cetral African CFA franc,XAF
Cook Islands,Cook Islands dollar,none
Costa Rica,Costa Rican colon,CRC
Cote d'Ivoire,West African CFA franc,XOF
Croatia,Croatian kuna,HRK
Cuba,Cuban peso,CUP
Curacao,Netherlands Antillean guilder,ANG
Cyprus,European euro,EUR
Czech Republic,Czeck kurona,CZK
Denmark,Danish krone,DKK
Djibouti,Djiboutian franc,DJF
Dominica,East Caribbean dollar,XCD
Dominican Republic,Dominican peso,DOP
Ecuador,United States dollar,USD
Egypt,Egyptian pound,EGP
El Salvador,United States dollar,USD
Equatorial Guinea,Central African CFA franc,XAF
Eritrea,Eritrean nakfa,ERN
Estonia,European euro,EUR
Ethiopia,Ethiopian birr,ETB
Falkland Islands,Falkland Islands pound,FKP
Faroe Islands,Faroese krona,none
Fiji,Fijian dollar,FJD
Finland,European euro,EUR
France,European euro,EUR
French Guiana,European euro,EUR
French Polynesia,CFP franc,XPF
Gabon,Central African CFA franc,XAF
Gambia,Gambian dalasi,GMD
Georgia,Georgian lari,GEL
Germany,European euro,EUR
Ghana,Ghanaian cedi,GHS
Gibraltar,Gibraltar pound,GIP
Greece,European euro,EUR
Greenland,Danish krone,DKK
Grenada,East Caribbean dollar,XCD
Guadeloupe,European euro,EUR
Guam,United States dollar,USD
Guatemala,Guatemalan quetzal,GTQ
Guernsey,Guernsey Pound,GGP
Guinea,Guinean franc,GNF
Guinea-Bissau,West African CFA franc,XOF
Guyana,Guyanese dollar,GYD
Haiti,Haitian gourde,HTG
Honduras,Honduran lempira,HNL
Hong Kong,Hong Kong dollar,HKD
Hungary,Hungarian forint,HUF
Iceland,Icelandic krona,ISK
India,Indian rupee,INR
Indonesia,Indonesian rupiah,IDR
International Monetary Fund,SDR (Special Drawing Right),XDR
Iran,Iranian rial,IRR
Iraq,Iraqi dinar,IQD
Ireland,European euro,EUR
Isle of Man,Manx pound,IMP
Israel,Israeli new shekel,ILS
Italy,European euro,EUR
Jamaica,Jamaican dollar,JMD
Japan,Japanese yen,JPY
Jersey,Jersey pound,JEP
Jordan,Jordanian dinar,JOD
Kazakhstan,Kazakhstani tenge,KZT
Kenya,Kenyan shilling,KES
Kiribati,Australian dollar,AUD
Kosovo,European euro,EUR
Kuwait,Kuwaiti dinar,KWD
Kyrgyzstan,Kyrgyzstani som,KGS
Laos,Lao kip,LAK
Latvia,European euro,EUR
Lebanon,Lebanese pound,LBP
Lesotho,Lesotho loti,LSL
Liberia,Liberian dollar,LRD
Libya,Lybian dinar,LYD
Liechtenstein,Swiss franc,CHF
Lithuania,European euro,EUR
Luxembourg,European euro,EUR
Macau,Macanese pataca,MOP
Macedonia,Macedonian denar,MKD
Madagascar,Malagasy ariary,MGA
Malawi,Malawian kwacha,MWK
Malaysia,Malaysian ringgit,MYR
Maldives,Maldivian, rufiyaa,MVR
Mali,West Afrian CFA franc,XOF
Malta,European euro,EUR
Marshall Islands,United States dollar,USD
Martinique,European euro,EUR
Mauritania,Mauritanian ouguiya,MRO
Mauritius,Mauritian rupee,MUR
Mayotte,European euro,EUR
Mexico,Mexican peso,MXN
Micronesia,United States dollar,USD
Moldova,Moldovan leu,MDL
Monaco,European euro,EUR
Mongolia,Mongolian euro,MNT
Montenegro,European euro,EUR
Montserrat,East Caribbean dollar,XCD
Morocco,Moroccan dirham,MAD
Mozambique,Mozambican metical,MZN
Myanmar,Myanmar kyat,MMK
Namibia,Namibian dollar,NAD
Nauru,Australian dollar,AUD
Nepal,Nepalese rupee,NPR
Netherlands,European euro,EUR
New Caledonia,CFP franc,XPF
New Zealand,New Zealand dollar,NZD
Nicaragua,Nicaraguan cordoba,NIO
Niger,West African CFA franc,XOF
Nigeria,Nigerian naira,NGN
Niue,New Zealand dollar,NZD
Norfolk Island,Australian dollar,AUD
Northern Mariana Islands,United States dollar,USD
North Korea,North Korean won,KPW
Norway,Norwegian krone,NOK
Oman,Omani rial,OMR
Pakistan,Pakistani rupee,PKR
Palau,United States dollar,USD
Palestine,Israeli new shekel,ILS
Panama,United States dollar,USD
Papua New Guinea,Papua New Guinean kina,PGK
Paraguay,Paraguayan guarani,PYG
Peru,Peruvian sol,PEN
Philippines,Philippine peso,PHP
Pitcairn Islands,New Zealand dollar,NZD
Poland,Polish zloty,PLN
Portugal,European euro,EUR
Puerto Rico,United States dollar,USD
Qatar,Qatari riyal,QAR
Reunion,European euro,EUR
Romania,Romanian leu,RON
Russia,Russian ruble,RUB
Rwanda,Rwandan franc,RWF
Saba,United States dollar,USD
Saint Barthelemy,European euro,EUR
Saint Helena,Saint Helena pound,SHP
Saint Kitts and Nevis,East Caribbean dollar,XCD
Saint Lucia,East Caribbean dollar,XCD
Saint Martin,European euro,EUR
Saint Pierre and Miquelon,European euro,EUR
Saint Vincent and the Grenadines,East Caribbean dollar,XCD
Samoa,Samoan tala,WST
San Marino,European euro,EUR
Sao Tome and Principe,Sao Tome and Principe dobra,STD
Saudi Arabia,Saudi Arabian riyal,SAR
Senegal,West African CFA franc,XOF
Serbia,Serbian dinar,RSD
Seychelles,Seychellios rupee,SCR
Sierra Leone,Sierra Leonean leone,SLL
Singapore,Singapore dollar,SGD
Sint Eustatius,United States dollar,USD
Sint Maarten,Netherlands Antillian guilder,ANG
Slovakia,European euro,EUR
Slovenia,European euro,EUR
Solomon Islands,Solomon Islands dollar,SBD
Somalia,Somali shilling,SOS
South Africa,South African rand,ZAR
South Georgia Island,Pound sterling,GBP
South Korea,South Korean won,KRW
South Sudan,South Sudanese pound,SSP
Spain,European euro,EUR
Sri Lanka,Sri Lankan rupee,LKR
Sudan,Sudanese pound,SDG
Suriname,Surinamese dollar,SRD
Svalbard and Jan Mayen,Norwegian krone,NOK
Swaziland,Swazi lilangeni,SZL
Sweden,Swidish krona,SEK
Switzerland,Swiss franc,CHF
Syria,Ryrian pound,SYP
Taiwan,New Taiwan dollar,TWD
Tajikistan,Tajikistani somoni,TJS
Tanzania,Tanzanian shilling,TZS
Thailand,Thai baht,THB
Timor-Leste,United States dollar,USD
Togo,West African CFA franc,XOF
Tokelau,New Zealand dollar,NZD
Tonga,Tongan pa’anga,TOP
Trinidad and Tobago,Trinidad and Tobago dollar,TTD
Tristan da Cunha,Pound sterling,GBP
Tunisia,Tunisian dinar,TND
Turkey,Turkish dinar,TRY
Turkmenistan,Turkmen manat,TMT
Turks and Caicos Islands,United States dollar,USD
Tuvalu,Australian dollar,AUD
Uganda,Ugandan shilling,UGX
Ukraine,Ukrainian hryvnia,UAH
United Arab Emirates,UAE dirham,AED
United Kingdom,Pound sterling,GBP
United States of America,United States dollar,USD
Uruguay,Uruguayan peso,UYU
US Virgin Islands,United States dollar,USD
Uzbekistan,Uzbekistani som,UZS
Vanuatu,Vanuatu vatu,VUV
Vatican City,European euro,EUR
Venezuela,Venezuelan bolivar,VEF
Vietnam,Vietnamese dong,VND
Wake Island,United States dollar,USD
Wallis and Futuna,CFP franc,XPF
Yemen,Yemeni rial,YER
Zambia,Zambian kwacha,ZMW
Zimbabwe,United States dollar,USD


How do I read its contents into a three-value tuple (std::tuple<std::string, std::string, std::string>)? I'm lost on this.

I've got it up to this, but it's for reading into a std::map<std::string, std::string>:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void fill_map(std::map<std::string, std::string> &map)
{
	std::ifstream ifs{ 
		"C:/Users/Osman/programming/visual_studio_2017/Projects/programming_principles_practice_using_c++/map_fill_test/Debug/currency_code_mapping.txt" 
	};

	std::string currency_code;
	std::string country;
	while (ifs)
	{
		while (std::getline(ifs, country, ',') && std::getline(ifs, currency_code, '\n'))
		{
			map[country] = currency_code;
		}
	}
}
Actually, no, std::map<std::string, std::string, std::string> would probably be better. How do I fill a map that has three values?

What I have right now is this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void fill_map(std::map<std::string, std::string, std::string> &map)
{
	std::ifstream ifs{
		"C:/Users/Osman/programming/visual_studio_2017/Projects/Wt/currency_conv/Debug/currency_code_mapping.txt"
	};

	std::string currency_code;
	std::string currency_name;
	std::string country;
	while (ifs)
	{
		while (std::getline(ifs, country, ',') && std::getline(ifs, currency_code, '\n'))
		{
			map[country] = currency_name;
			map[currency_name] = currency_code;
		}
	}
}

But it won't compile.
Last edited on
Try
 
std::map<std::string, std::pair<std::string, std::string>>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <sstream>
#include <tuple>
#include <map>
using namespace std;

int main ()
{
    ifstream fin("currency_code_mapping.txt");

    std::map<std::string, std::pair<std::string, std::string>> currencies;
    
    for (string line; getline(fin, line); )
    {
        istringstream ss(line);
        string a, b, c;
        if (getline(ss, a, ','), getline(ss, b, ','), getline(ss, c) )
        {      
            currencies[a] = {b, c};
        } 
    }

    for (const auto & cur : currencies)
    {
        cout << left << setw(40) << cur.first <<  setw(40) << cur.second.first  << cur.second.second << '\n';  
    }

}


Note: four values on this line:
Maldives,Maldivian, rufiyaa,MVR

Last edited on
OP: any particular reason why you're using std::tuple? Extracting values out of tuples is not intuitive as you have to use index numbers like std::get<0>(tuple_element) to extract the 0'th data-member from the std::tuple object tuple_element and have to remember if 0 was country or currency or something else. Wouldn't a struct be more intuitive?
I do not know how that source file is generated, but it appears to me to mix two tables’ worth of data together.

Table 1: country->currency_type

Table 2: currency_type ::= (name, abbreviation)

Ideally, you should have the two tables separately. But you can easily separate them by code.

Note: I am also not personally a fan of using tuple or pair — generic containers for variable type — when a fixed (known) type exists. When you know the type of a thing, use a concrete struct.
> Wouldn't a struct be more intuitive?

How is a struct any more intuitive? You have to remember the name of the member.
1
2
3
4
5
enum pos { country, currency /* ... */ };
struct my_struct{ std::string  country, currency /* ... */ ; };
// ...
const auto x = std::get<country>(tup) ;
const auto y = object.country ;
Mistake in text file fixed on PC. Thanks for the heads-up, Chervil.

Anyway, look at the post right below the opening post. Would a map with three values also not be good? And how can a struct be used as a container? I need a container.

@Chervil: Would commas be a good idea? I'd think the || operator would be better in that case.
Would commas be a good idea? I'd think the || operator would be better in that case.

I presume the context here is line 20 in the code I posted last time:
 
    if (getline(ss, a, ','), getline(ss, b, ','), getline(ss, c) )


I tend to use the >> operator to chain a series of operations where it is suitable, but that doesn't work with getline(). Here the && operator would give the same outcome as the comma. So long as the last part getline(ss, c) succeeded, we know that the previous parts worked too.

The || operator would be problematic. It might seem that if at least one of the getlines worked, then there is some data which should be processed. However, because of the shortcut evaluation used in C++, if the first operation succeeds, the compiler can deduce that the whole condition is true and hence the remaining parts are not even executed. The result is string a contains valid content, but b and c remain empty.
So it in this case, it's better to use the operator &&.

By the way, anyone know a good way to download information about places in the world, like the name of the place, name of the country and the longitude and latitude? I could put that into CSV file and upload to a database if I need to.
Topic archived. No new replies allowed.