Printing birthdates using maps and they end up as Octals - c++

If I create a map for names and birthdays. When i enter birthdates that end in 0 it changes it the number to an octal. how do i print out the birthday ie 010525 == 4437 so when i call it -> second it will print 010525
#include <stdio.h>
#include <iterator>
#include <string>
#include <map>
#include <iostream>
using namespace std;
int main(){
map<string, int>birth;
birth["Chicken"] = 010525;
birth["Dragon"] = 010266;
map<string, int>::iterator it;
for(it = birth.begin() ; it != birth.end(); it++){
cout << it -> first + " ";
cout << it ->second << endl;
}
}
Output:
Chicken 4437
Dragon 4278

There are 2 ways to fix this problem:
(1) The first way is to enter the birthday without the leading 0 as follow:
birth["Chicken"] = 10525;
birth["Dragon"] = 10266;
Then use setfill() and setw() to fill the leading 0.
Please note that the code that uses std:setw() and std::setfill() will compile only with new C++ compiler versions such as C++14 (or C++11)
#include <stdio.h>
#include <iterator>
#include <string>
#include <map>
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
map<string, int>birth;
birth["Chicken"] = 10525;
birth["Dragon"] = 10266;
map<string, int>::iterator it;
for(it = birth.begin() ; it != birth.end(); it++){
cout << it -> first + " ";
cout << setfill('0') << setw(6) << it ->second << endl;
}
}
(2) The second way is to store the birthday as string. This way you can enter the birthday with the leading 0.
Here is the code:
#include <stdio.h>
#include <iterator>
#include <string>
#include <map>
#include <iostream>
using namespace std;
int main(){
map<string, string>birth;
birth["Chicken"] = "010525";
birth["Dragon"] = "010266";
map<string, string>::iterator it;
for(it = birth.begin() ; it != birth.end(); it++){
cout << it -> first + " ";
cout << it ->second << endl;
}
}

You can go with using both as string in map like :
map<string, string>birth;
and rest keep as it is.

Related

How could/should I print text strings above number columns in C++?

I would like to print the strings at the top of columns with a 1 x 3 array.
I have edited this simple function several times, and this produces the least errors. New to C++, reading Deital Chap 6 Recursive.
What am I missing? I started with half brackes around strings, and brackets seemed to produce less errors.
Here is the code:
#include <iostream>
#include <string>
#include <array>
using namespace std;
int main() {
array a[1][3] = ["Car" "Hours" "Charge"]
cout<< a << endl;
}
Terminal produces errors as such:
parking_charges_6_12.cpp: In function ‘int main()’:
parking_charges_6_12.cpp:8:7: error: missing template arguments before ‘a’
8 | array a[1][3] = ["Car" "Hours" "Charge"]
^
This should work:
#include <array>
#include <iostream>
#include <string>
int main(){
std::array<std::string, 3> headlines = {"Car", "Hours", "Charge"};
for( auto const& elem : headlines ){
std::cout << elem << "\t";
}
}
It should be curly braces {} in the initializer, not []. And you need a comma between each element.
On the other hand, in later C++ revisions array can detect the type and number of elements, so you don't have to give that.
#include <iostream>
#include <array>
using namespace std;
int main() {
array a = {"Car", "Hours", "Charge"};
for (auto& item : a)
cout<< item << endl;
}
How about something like this:
#include<iostream>
using namespace std;
int main() {
string data[3] = {"Car", "Hours", "Charge"};
for (int i = 0; i < 3; i++)
cout << data[i] << " ";
}
Obviously it is not using the array header, but it's a working example. If you do need to use the array header, you can try something like :
#include <array>
#include <iostream>
#include <iterator>
#include <string>
using namespace std;
int main() {
array<string, 3> ar3 = {"Car", "Hours", "Charge"};
cout << ar3.size() << endl;
for (auto i : ar3)
cout << i << ' ';
return 0;
}
You can see it working online here

Sorting a textfile that contains player name and score in descending order

I am trying to open a text file and then rearrange it in descending order, to show who has the highest score. In the text file there's the player name and their score.
I've managed to print out the textfile in c++, but I cannot find a way to sort it since the variables are in the text file.
#include <string>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <functional>
using namespace std;
struct player {
string name;
int score;
int position;
};
int main()
{
string line;
ifstream inFile;
inFile.open("C:/Users/kkpet/Desktop/highscore.txt");
if (inFile.is_open()) {
while (getline(inFile, line)) {
player x;
ifstream inFile;
inFile.open("C:/Users/kkpet/Desktop/highscore.txt");
cout << line << '\n';
}
inFile.close();
}
else
cout << "Unable to open text";
}
Assuming your text file looks like this:
Name1 1
Name2 1
Name4 5
Name3 6
you could do something like this:
#include <string>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <functional>
#include <vector>
int main()
{
std::string line;
std::ifstream inFile;
inFile.open("/C:/Users/kkpet/Desktop/highscore.txt");
if (inFile.is_open()) {
std::vector<std::pair<int, std::string> > score_vector;
std::string name;
int score;
while (inFile >> name >> score) {
score_vector.push_back(std::make_pair(score, name));
std::cout << line << '\n';
}
inFile.close();
std::sort(score_vector.begin(), score_vector.end());
std::reverse(score_vector.begin(), score_vector.end());
for(auto it = score_vector.begin(); it != score_vector.end(); ++it){
std::cout << "Name: " << it->second << " Score: " << it->first << std::endl;
}
}
else
std::cout << "Unable to open text";
}
You first read the file line by line using inFile << name << score directly gives you the name and score of the player. You then create a pair out of them with score as first, which just makes it easier to sort, you could also sort by the second element of a pair using your own compare function, but for simplicity I put it this way around. Then you can easily sort the vector with the std::sort method. Afterwards it needs to be reverted.
Full code with custom compare function:
#include <string.h>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <functional>
#include <vector>
// This is a compare funciton for the sort algorithm of std::sort. See [1]
bool compareScorePair(std::pair<std::string, int>&a, std::pair<std::string, int>&b){
if(a.second > b.second){return true;}
if(a.second == b.second){return a.first.compare(b.first) > 0;}
return false;
}
int main()
{
std::ifstream inFile;
inFile.open("C:/Users/kkpet/Desktop/highscore.txt");
if (inFile.is_open()) {
std::vector<std::pair<std::string, int> > score_vector;
std::string name;
int score;
while (inFile >> name >> score) { // Can be used to directly assign istream data to variables. See [2]
score_vector.push_back(std::make_pair(name, score)); // Storing data as pair, to keep relationships between score and name.
}
inFile.close();
std::sort(score_vector.begin(), score_vector.end(), compareScorePair); // Sort the vector with the custom compare function, See top of code.
int place = 1;
//auto is used purely for convenience. auto represents std::vector<std::pair<std::string, int> >::iterator here.
for(auto it = score_vector.begin(); it != score_vector.end(); ++it){
std::cout << "Place: " << place << " Name: " << it->first << " Score: " << it->second << std::endl;
++place;
}
// The whole for loop could look like this:
/*
for(uint i = 0; i < score_vector.size(); ++i){
std::string name_out = score_vector[i].first;
int score_out = score_vector[i].second;
std::cout << "Place: " << i << " Name: " << name_out << " Score: " << score_out << std::endl;
}
*/
}
else
std::cout << "Unable to open text";
}
Output:
Place: 1 Name: Name3 Score: 6
Place: 2 Name: Name4 Score: 5
Place: 3 Name: Name2 Score: 1
Place: 4 Name: Name1 Score: 1
Links:
[1]: https://en.cppreference.com/w/cpp/named_req/Compare
[2]: http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
Information on pair:
https://en.cppreference.com/w/cpp/utility/pair
Information on iterators (see auto keyword):
https://www.geeksforgeeks.org/iterators-c-stl/
No need to use C++ for this problem! Just enter this in the shell prompt.
sort -rk 2 highscore.txt > sorted_scores.txt
Explanation:
'sort' sorts a file, typically by the first letter.
The -k 2 option means to sort by the second column.
The -r option means to reverse (so highest score is on top).

How do I correctly find a value from part of a vector?

I was expecting the following code should print out only "2 is found", however it prints out both. The second one should not happen because 4 is not in the first 3 elements of the vector. Where did I make the mistake?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> a = {1,2,3,4,5};
if(find(a.begin(),a.begin()+3,2) != a.end()) cout << "2 found" << endl;
if(find(a.begin(),a.begin()+3,4) != a.end()) cout << "4 found" << endl;
}
Result:
2 found
4 found
find returns the end/"last" value you passed it if the value is not found, which in this case is not a.end(). The code should compare a la ... != a.begin() + 3....
Change find(a.begin(),a.begin()+3,2) != a.end() to find(a.begin(),a.begin()+3,2) != a.begin()+3
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> a = {1,2,3,4,5};
if(find(a.begin(),a.begin()+3,2) != a.begin()+3) cout << "2 found" << endl;
if(find(a.begin(),a.begin()+3,4) != a.begin()+3) cout << "4 found" << endl;
}

Is it possible to sort such strings: "30/11/2012:13:49:55" by date, as they're map keys? [duplicate]

This question already has answers here:
std::map - how to change key sorting?
(4 answers)
Closed 7 years ago.
I have a map with string date-time keys, and int values. I would like to sort my map by the date and time (by the map keys actually) which are in format like this: 30/11/2012:13:49:55. Is that possible? How to sort them? When sorting only string there's no such a big deal, but I really don't know how to do this with date/time string.
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<string, int> mymap;
mymap["30/11/2012:13:49:09"] = 122;
mymap["30/11/2012:13:49:55"] = 100;
mymap["30/11/2012:13:49:12"] = 123;
mymap["29/11/2012:19:26:11"] = 45;
for (std::map<string, int>::iterator i = mymap.begin(); i != mymap.end(); i++)
{
cout << i->first << "\n";
}
};
The output of the program suggests that this map is already ordered, however, I'm not quite sure if it always (in every case) sort it like I want it to.
Ok folks, will something like this work fine?
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <ctime>
using namespace std;
time_t string_to_time_t(string s)
{
struct tm tmp;
time_t t;
memset(&tmp, 0, sizeof(struct tm));
strptime(s.c_str(), "%d/%m/%Y:%H:%M:%S", &tmp);
t = mktime(&tmp);
return t;
}
int main()
{
time_t t, u;
t = string_to_time_t("30/11/2012:13:49:09");
u = string_to_time_t("30/11/2012:13:49:08");
if (u>t)
{
cout << "true" << endl;
}
else if (u==t)
{
cout << "same" << endl;
}
else
{
cout << "false" << endl;
}
return 0;
}
EDIT:
Huh, it seems to work now, thanks!
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <map>
using namespace std;
time_t string_to_time_t(string s)
{
struct tm tmp;
time_t t;
memset(&tmp, 0, sizeof(struct tm));
strptime(s.c_str(), "%d/%m/%Y:%H:%M:%S", &tmp);
t = mktime(&tmp);
return t;
}
int main()
{
map<time_t, int> mymap;
mymap[string_to_time_t("30/11/2012:13:49:09")] = 122;
mymap[string_to_time_t("30/11/2012:13:49:55")] = 100;
mymap[string_to_time_t("30/11/2012:13:49:12")] = 123;
mymap[string_to_time_t("29/11/2012:19:26:11")] = 45;
for (std::map<time_t, int>::iterator i = mymap.begin(); i != mymap.end(); i++)
{
cout << i->first << " " << i->second << "\n";
}
};
You can provide your own functor as a template argument when instantiating your map, cf. std::map - how to change key sorting?. The sort functor should parse the string and give the proper relations.
That said, I am a big fan of date strings whose alphabetical order is the same as their logical one, e.g. 2015-12-31-23-59-49.999 or such (for 11.59 pm plus a few sconds on new year's eve). I use such strings when I name pictures and when I print to log files.

Using setw and left from iomanip

I want to print out the keys and values in a map in a organized table. I am trying to use setw and left but the output is
The 1
hello1
and I want it to be like
The 1
hello 1
what i have done so far
// System includes
#include <iostream>
#include <string>
#include <cstdlib>
#include <map>
#include <unordered_map>
#include <fstream>
#include <iomanip>
/************************************************************/
Local includes
/************************************************************/
// Using declarations
using std::cout;
using std::map;
using std::unordered_map;
using std::string;
using std::cin;
using std::endl;
using std::ifstream;
using std::left;
using std::setw;
/************************************************************/
Function prototypes/global vars/typedefs
/************************************************************/
int
main (int argc, char* argv[])
{
//call the wordCount function on the user specified input file
unordered_map <string,int> exampleMap;
exampleMap["The"]++;
exampleMap["hello"]++;
cout << left;
//iterate through the map and print out the elements
for( unordered_map<string, int>::iterator i=exampleMap.begin(); i!=exampleMap.end(); ++i)
{
cout << setw(5) << (*i).first << setw(15) << (*i).second << endl;
}
return EXIT_SUCCESS;
}
you need to specify a width larger than 5(If you want the field to be larger than 5 characters). You don't need the second call to setw.
try
for( auto i=exampleMap.begin(); i!=exampleMap.end(); ++i)
{
cout << setw(8) << i->first << i->second << '\n';
}