Use of cin to enter value pairs into STL map

How do you write a function that reads value pairs from cin and places them in map msi?

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 //	C21Drill Map.cpp
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
#include <iomanip>

// Write a function that reads value pairs from cin and places them in msi.
void fread(std::map<std::string, int>& pam);

int main()
{// Define a map<string,int> called msi and insert ten pairs into it.
	std::map<std::string, int> msi = {
		{ "lecture", 21 },
		{ "matinee", 53 },
		{ "musical", 24 },
		{ "broadway", 66 },
		{ "seminar", 12 },
		{ "panel", 37 },
		{ "ad hoc", 79 },
		{ "jury", 81 },
		{ "forum", 97 },
		{ "committee", 45 }
	};

	// Output the (name,value) pairs to cout in some format of your choice
	for (const auto& p : msi)
		std::cout << std::setw(10) << p.first << std::setw(5) << p.second << '\n';
	
	// Erase the (name, value) pairs from msi
	msi.clear();

	//	Read ten pairs from input and enter them into msi
	fread(std::map<std::string, int>& msi);


}


void fread(std::map<std::string, int>& pam) {
	for (std::string s; std::cin >> s;) {
		for (int n; std::cin >> n;)
			pam.emplace(s, n);
	}
}
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
std::map< std::string, int > read_map( std::istream& stm = std::cin )
{
    std::map< std::string, int > map ;
    std::string key ;
    int value ;

    // key does not contain white space
    while( stm >> key >> value ) map.emplace( key, value ) ;

    /*
    // key may contain white space
    while( std::getline( stm, key ) && // read a complete line as key (unformatted input)
           stm >> value && // read an int as value (formatted input)
           stm.ignore( 1000000, '\n' ) ) // extract and discard the trailing new line
    {
        map.emplace( key, value ) ;
    }
    */

    return map ;
}

http://coliru.stacked-crooked.com/a/d71da761e4a060fd
JLBorges,

I could not compile the code. It looks like read_map in the for statement needs a parameter.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//	C21Drill Map.cpp
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
#include <iomanip>

//	Write a function that reads value pairs from cin and places them in msi.
std::map< std::string, int > read_map(std::istream& stm = std::cin);


int main()
{
	// Define a map<string,int> called msi and insert ten pairs into it.
	std::map<std::string, int> msi = {
		{ "lecture", 21 },
		{ "matinee", 53 },
		{ "musical", 24 },
		{ "broadway", 66 },
		{ "seminar", 12 },
		{ "panel", 37 },
		{ "adhoc", 79 },
		{ "jury", 81 },
		{ "forum", 97 },
		{ "committee", 45 }
	};

	// Output the (name,value) pairs into it
	for (const auto& p : msi)
		std::cout << std::setw(10) << p.first << std::setw(5) << p.second << '\n';
	
	// Erase the (name, value) pairs from msi
	msi.clear();

	//	Read ten pairs from input and enter them into msi
	for (auto p : read_map()) std::cout << p.first << ' ' << p.second << '\n';
        // looks like read_map() needs a parameter
}


std::map< std::string, int > read_map(std::istream& stm = std::cin)
{
	std::map< std::string, int > map;
	std::string key;
	int value;

	// key does not contain white space
	while (stm >> key >> value) map.emplace(key, value);

	return map;
}
Last edited on
Problem is here because you provided default value in both declaration and definition.
Standard prohibits this:
A default argument shall not be redefined by a later declaration (not even to the same value).


You can either get rid of default value in definition; get rid of declaration (moving definition before main) or get rid of default value altogether and specify stream which you want to read from explicitely.
Thank you MiiNIPaa. I tried getting rid of the default value in the definition, and it worked. I also tried getting rid of the declaration and moving the definition before main() and it worked.

However, now that I know you need to use istream for user-defined types, I did some research that was for a struct, but I tried to modified it to fit the exercise that I am working on. There are several errors that I was not able to resolve. They are boldfaced in the code below. Please help me resolve the errors.

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
32
33
34
35
36
37
38
39
//	C21 I-O.cpp
#include <iostream>
#include <map>
#include <string>


std::ostream& operator<<(std::ostream& os, const std::map<std::string, int>& e) {
	return os << "{\"" << e.first << "\"," << e.second << "}";
}// no member first, no member second

std::istream& operator>>(std::istream& is, std::map<std::string, int>& e);


int main()
{
	std::map<std::string, int> msi;

	for (std::map<std::string, int> msi; std::cin >> msi;)
		std::cout << msi << '\n';
}


std::istream& operator>>(std::istream& is, std::map<std::string, int>& e) {
	char c, c2;
	if (is >> c && c == '{' && is >> c2 && c2 == '"') {
		std::string name;
		while (is.get(c) && c != '"')
			name += c;

		if (is >> c && c == ',') {
			int number = 0;
			if (is >> number >> c && c == '}')
				e = { name, number };// no operator "=" matches these operands
			return is;
		}
	}
	is.setf(std::ios_base::failbit);
	return is;
}
no member first, no member second
map indeed does not have those members. You probably want to iterate over its elements and output each.

no operator "=" matches these operands
you are trying to assign a pair of value to a map as whole (overwriting previous content). Yu probably want to do same thing that read_map din and insert/emplace elements to the map
I believe I found the solution. I haven't tested it yet, but the program compiles and runs. It needs some refinement. What I did was replace std::map<std::string, int> with std::pair<std::string, int> because the elements of a map<string, int> are of type pair<string, int>. In addition, the first member of pair is called first, and the second member second. Here is the code:
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
32
33
34
35
36
37
38
39
//	C21 I-O.cpp
#include <iostream>
#include <map>
#include <string>


std::ostream& operator<<(std::ostream& os, const std::pair<std::string, int>& e) {
	return os << "{\"" << e.first << "\"," << e.second << "}";
}

std::istream& operator>>(std::istream& is, std::map<std::string, int>& e);


int main()
{
	std::map<std::string, int> msi;

	for (std::pair<std::string, int> msi; std::cin >> msi.first >> msi.second;)
		std::cout << msi.first << '\t' << msi.second << '\n';
}


std::istream& operator>>(std::istream& is, std::pair<std::string, int>& e) {
	char c, c2;
	if (is >> c && c == '{' && is >> c2 && c2 == '"') {
		std::string name;
		while (is.get(c) && c != '"')
			name += c;

		if (is >> c && c == ',') {
			int number = 0;
			if (is >> number >> c && c == '}')
				e = { name, number };
			return is;
		}
	}
	is.setf(std::ios_base::failbit);
	return is;
}
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
32
33
34
//    C21 I-O.cpp
#include <iostream>
#include <map>
#include <string>
#include <sstream>

std::ostream& operator<< ( std::ostream& os, const std::map< std::string, int >& map ) {

    os << "{ " ;
    for( const auto& pair : map ) os << "{'" << pair.first << "'," << pair.second << "} " ;
    return os << "}";
}

std::istream& operator>> ( std::istream& is, std::map<std::string, int>& map ) {

    map.clear() ;

    std::string str ;
    int i ;
    while( is >> str >> i ) map.emplace( str, i ) ;

    if( !map.empty() ) { is.clear() ; is.ignore(1000,'\n') ; }
    return is ;
}

int main() {

    std::map<std::string, int> msi;

    std::istringstream str_in( "map 34 set 9 string 26 vector 5 istream 1001 stringbuf 87" ) ;
    str_in >> msi;

    std::cout << msi << '\n';
}

http://coliru.stacked-crooked.com/a/3b862773bf822211
JLBorges,

1. How come you were able to use pair.first and pair.second when first and second are not members of std::map<std::string, int>?

2. What does the statement str_in >> msi; do?
1. How come you were able to use pair.first and pair.second ...

1
2
for( const auto& pair : map ) // for each pair in the map
          os << "{'" << pair.first << "'," << pair.second << "} " ; // first and second of the pair 



2. What does the statement str_in >> msi; do?

Reads the contents of the input stream str_in into the map.
std::cin >> map ; // read the contents from std::cin
Thank you very much, JLBorges.
Topic archived. No new replies allowed.