Click here to Skip to main content
15,868,016 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
#include <fstream>
#include <string>
#include <cstring>
#include <map>

using namespace std;

struct Item {
	int key;
	char value[30];

	Item() {};
	Item(const int key, const string value) {
		this->key = key;

		if (value.length() > 30) {
			throw "String is too long";
		}
		strcpy(this->value, value.c_str());
	}
};

template<typename K, typename V>
//Since the value is also unique then there is no need to return a multimap
map<V, K> invertMap(map<K, V> const& map) {
	std::map<V, K> invMap;

	for (auto const& pair : map) {
		invMap.insert(std::make_pair(pair.second, pair.first));
	}

	return invMap;
}

template<typename K, typename V>
void printMap(map<K, V> const& map) {
	for (auto const& item : map)
	{
		cout << item.first << "  " << item.second << endl;
	}
}

void writeTotextFile(const map<int, string> items, string filename) {
	ofstream file("myfile1.txt");

	for (auto const& item : items)
	{
		Item it(item.first, item.second);
		file.write((char*)&it, sizeof(Item));
	}

	file.close();
}

void writeTotextFile(const map<string, int> items, string filename) {
	ofstream file("myfile1.txt");

	for (auto const& item : items)
	{
		Item it(item.second, item.first);
		file.write((char*)&it, sizeof(Item));
	}

	file.close();
}

map<int, string> readFromtextFile(string filename) {
	ifstream file("myfile1.txt");

	map<int, string> items;
	Item it;
	while (file.read((char*)&it, sizeof(Item))) {
		items.insert(std::make_pair(it.key, it.value));
	}

	file.close();

	return items;
}

void printtxtFile(string filename) {
	ifstream file("myfile1.txt");

	Item it;
	while (file.read((char*)&it, sizeof(Item))) {
		cout << "Key: " << it.key << " Value: " << it.value << endl;
	}

	file.close();
}

int main() {
	//Uncomment to create original file
	//map<int, string> items{ {1, "Peteris Johansons"},{12, "Zilgma Koknese"}, {4,"Janis Pupins"},{2, "Kaija Skarstane" }, {3, "Dagnija Zeltmane"} };
	//writeToBinaryFile(items, "test.bin");

	//Using string because map does not have good support for char arrays
	map<int, string> items = readFromtextFile("myfile1.txt");
	writeTotextFile(items, "orderedByKey.txt");
	writeTotextFile(invertMap(items), "orderedByValue.txt");
	cout << "Sorted by key: " << endl;
	printtxtFile("orderedByKey.txt");
	cout << "--------------------------------" << endl;
	cout << "Sorted by name: " << endl;
	printtxtFile("orderedByValue.txt");

	return 0;
}


What I have tried:

<pre>#include <fstream>
#include <string>
#include <cstring>
#include <map>

using namespace std;

struct Item {
	int key;
	char value[30];

	Item() {};
	Item(const int key, const string value) {
		this->key = key;

		if (value.length() > 30) {
			throw "String is too long";
		}
		strcpy(this->value, value.c_str());
	}
};

template<typename K, typename V>
//Since the value is also unique then there is no need to return a multimap
map<V, K> invertMap(map<K, V> const& map) {
	std::map<V, K> invMap;

	for (auto const& pair : map) {
		invMap.insert(std::make_pair(pair.second, pair.first));
	}

	return invMap;
}

template<typename K, typename V>
void printMap(map<K, V> const& map) {
	for (auto const& item : map)
	{
		cout << item.first << "  " << item.second << endl;
	}
}

void writeTotextFile(const map<int, string> items, string filename) {
	ofstream file("myfile1.txt");

	for (auto const& item : items)
	{
		Item it(item.first, item.second);
		file.write((char*)&it, sizeof(Item));
	}

	file.close();
}

void writeTotextFile(const map<string, int> items, string filename) {
	ofstream file("myfile1.txt");

	for (auto const& item : items)
	{
		Item it(item.second, item.first);
		file.write((char*)&it, sizeof(Item));
	}

	file.close();
}

map<int, string> readFromtextFile(string filename) {
	ifstream file("myfile1.txt");

	map<int, string> items;
	Item it;
	while (file.read((char*)&it, sizeof(Item))) {
		items.insert(std::make_pair(it.key, it.value));
	}

	file.close();

	return items;
}

void printtxtFile(string filename) {
	ifstream file("myfile1.txt");

	Item it;
	while (file.read((char*)&it, sizeof(Item))) {
		cout << "Key: " << it.key << " Value: " << it.value << endl;
	}

	file.close();
}

int main() {
	//Uncomment to create original file
	//map<int, string> items{ {1, "Peteris Johansons"},{12, "Zilgma Koknese"}, {4,"Janis Pupins"},{2, "Kaija Skarstane" }, {3, "Dagnija Zeltmane"} };
	//writeToBinaryFile(items, "test.bin");

	//Using string because map does not have good support for char arrays
	map<int, string> items = readFromtextFile("myfile1.txt");
	writeTotextFile(items, "orderedByKey.txt");
	writeTotextFile(invertMap(items), "orderedByValue.txt");
	cout << "Sorted by key: " << endl;
	printtxtFile("orderedByKey.txt");
	cout << "--------------------------------" << endl;
	cout << "Sorted by name: " << endl;
	printtxtFile("orderedByValue.txt");

	return 0;
}
Posted
Updated 28-Dec-21 6:45am
Comments
k5054 27-Dec-21 16:03pm    
And your question is?
Shao Voon Wong 27-Dec-21 21:58pm    
The key is int type which is binary when written to the file. Convert the key to char array.
jasmeet singh 2021 28-Dec-21 6:08am    
Hi I tried above but didn't worked. Could you make changes to above program from binary to text please?

1 solution

The way you are use the read and write methods of the stream classes does in fact write data in binary form. To have your data written in text form there are several ways to do it but since you are using c++ I would make Read and Write methods for your Item structure. I would also add a Set method for the structure that you can use for objects created with the default constructor. Those things could look like this :
C++
struct Item
{
    int key;
    const int value_size = 29;
    char value[value_size+1];

    Item() {};
    Item( const int k, const string & v )
    {
        Set( k, v );
    }

    void Set( const int k, const string & v )
    {
        key = k;

        if( v.length() > value_size )
        {
            throw "String is too long";
        }
        strcpy( value, v.c_str() );
    }

    void Read( std::ifstream & file )
    {
        // read members from file in text form
    }

    void Write( std::ofstream & file )
    {
        // write members to file in text form
    }
};
This means you now need to implement the Read and Write methods. The question for you is how do you want to the data to look in the file? I would have one piece of data per line which means you write the data and follow it with a newline character. This means you need to make a string to represent the integer member and then write the string. This make sense because the whole point of this is to write the data in textual format.

I will leave that part to you. If you more questions you are welcome to ask them.

Note that I adjusted the code to pass the string by reference. This way you avoid making a copy of the string.
 
Share this answer
 
Comments
merano99 28-Dec-21 20:22pm    
To save and load a string, I would use a string instead of
char value[value_size+1];
You would then no longer have to worry about the length.
jasmeet singh 2021 30-Dec-21 15:20pm    
is it possible to share the entire solution because I have so many errors after implementing above code?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900