Trying to print an unordered_map - c++

I am writing a simple program to find anagrams. I am using a hash table with sorted strings as the keys, and the unsorted strings as the values. When I try to print the unordered_map (hash map) it gives me this error.
Error 1 error C2675: unary '++' : 'std::string' does not define this
operator or a conversion to a type acceptable to the predefined
operator c:\program files (x86)\microsoft visual studio
12.0\vc\include\xhash 672 1
#include <iostream>
#include <list>
#include <cstdlib>
#include <map>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <cstring>
void Anagrams(std::vector<std::string> &v){
std::unordered_map<std::string, std::string> wordTable;
char sortedString[256];
for (std::string tmp : v){
strcpy(sortedString, tmp.c_str());
std::sort(sortedString, sortedString + tmp.size());
std::string backToString(sortedString);
wordTable.insert(backToString, tmp);
}
std::cout << "Map contains" << std::endl;
std::cout << "mymap's buckets contain:\n";
for (unsigned i = 0; i < wordTable.bucket_count(); ++i) {
std::cout << "bucket #" << i << " contains:";
for (auto local_it = wordTable.begin(i); local_it != wordTable.end(i); ++local_it)
std::cout << " " << local_it->first << ":" << local_it->second;
std::cout << std::endl;
}
}
int main()
{
std::vector<std::string> words{ "debitcard", "badcredit", "cat", "act", "evils", "elvis" };
Anagrams(words);
return 0;
}
For some reason it thinks the iterator "local_it" is a string. Can anyone help?

The issue is that the std::unorderd_map::insert() function takes a std::pair<key, value>, not key, value:
wordTable.insert(std::make_pair(backToString, tmp));

Related

Build incremental std::string

I try to build an std::string in the form of "start:Pdc1;Pdc2;Pdc3;"
With following code I can build the repeated "Pdc" and the incremental string "123" but I'm unable to combine the two strings.
#include <string>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iterator>
#include <numeric>
int main()
{
std::ostringstream ss;
std::string hdr("start:");
std::fill_n(std::ostream_iterator<std::string>(ss), 3, "Pdc;");
hdr.append(ss.str());
std::string v("abc");
std::iota(v.begin(), v.end(), '1');
std::cout << hdr << std::endl;
std::cout << v << std::endl;
std::cout << "Expected output: start:Pdc1;Pdc2;Pdc3;" << std::endl;
return 0;
}
How can I build this string? Preferable without a while or for loop.
The expected output is: start:Pdc1;Pdc2;Pdc3;
std::strings can be concatenated via their operator+ (or +=) and integers can be converted via std::to_string:
std::string res("start:");
for (int i=0;i<3;++i){
res += "Pdc" + std::to_string(i+1) + ";";
}
std::cout << res << "\n";
If you like you can use an algorithm instead of the handwritten loop, but it will still be a loop (your code has 2 loops, but only 1 is needed).
Code to generate your expected string, though with a small for loop.
#include <iostream>
#include <string>
#include <sstream>
std::string cmd(const std::size_t N)
{
std::ostringstream os;
os << "start:";
for(std::size_t n = 1; n <= N; ++n) os << "Pdc" << n << ";";
return os.str();
}
int main()
{
std::cout << cmd(3ul);
return 0;
}

How can I find the positions from characters in a string with string::find?

I need the positions of characters in a string.
The String contains:
"username":"secret", "password":"also secret", "id":"secret too", "token":"secret"
and I need the positions of the quotation marks from the token that are bold: "token":"secret".
I have experimented with the code from http://www.cplusplus.com/reference/string/string/find
but everything didn't work. Can anyone help me?
Here is what i have tried but it only gives out a 0:
#include <iostream>
#include <string>
int main() {
std::string buffer("\"username\":\"secret\", \"password\":\"also secret\", \"id\":\"secret too\", \"token\":\"secret\"");
size_t found = buffer.find('"');
if (found == std::string::npos)std::cout << "something went wrong\n";
if (found != std::string::npos)
std::cout << "first " << '"' << " found at: " << found << '\n';
for (int j = 0; j <= 17; ++j) {
found = buffer.find('"');
found + 1, 6;
if (found != std::string::npos)
std::cout << "second " << '"' << " found at : " << found << '\n';
}
return 0;
There are so many possible solutions. So, it is hard to answer.
What basically needs to be done, is to iterate through the string, position by position, then check if the character is the searched one, and then do something with the result.
A first simple implementation could be:
#include <iostream>
#include <string>
const std::string buffer("\"username\":\"secret\", \"password\":\"also secret\", \"id\":\"secret too\", \"token\":\"secret\"");
int main() {
for (size_t position{}, counter{}; position < buffer.length(); ++position) {
if (buffer[position] == '\"') {
++counter;
std::cout << "Character \" number " << counter << " found at position " << position << '\n';
}
}
return 0;
}
But then, your question was about the usage of std::string.find(). In your implementation, you start always the search at the beginning of the std::string. And because of that, you will always find the same " at position 0.
Solution: After you have found the first match, use the resulting pos (incremented by one) as the second parameter to the std::string.find() function. Then you will start the search after the first found " and hence find the next one. And all this can be done in a normal for-loop.
See below the next easy example:
#include <iostream>
#include <string>
const std::string buffer("\"username\":\"secret\", \"password\":\"also secret\", \"id\":\"secret too\", \"token\":\"secret\"");
int main() {
for (size_t position{}, counter{}; std::string::npos != (position = buffer.find("\"", position)); ++position, ++counter) {
std::cout << "Character \" number " << counter << " found at position " << position << '\n';
}
return 0;
}
There are more solutions, depending on what you really want to do. You coud extract all keywords and data with a simple regex.
Something like this:
#include <iostream>
#include <string>
#include <regex>
#include <vector>
const std::regex re{ R"(\"([ a-zA-Z0-9]+)\")" };
const std::string buffer("\"username\":\"secret\", \"password\":\"also secret\", \"id\":\"secret too\", \"token\":\"secret\"");
int main() {
std::vector part(std::sregex_token_iterator(buffer.begin(), buffer.end(), re, 1), {});
std::cout << part[7] << '\n';
return 0;
}
Or, you can split everything into tokens and values. Like this:
#include <iostream>
#include <string>
#include <regex>
#include <vector>
#include <map>
#include <iomanip>
const std::regex re1{ "," };
const std::regex re2{ R"(\"([^\"]+)\")" };
const std::string buffer("\"username\":\"secret\", \"password\":\"also secret\", \"id\":\"secret too\", \"token\":\"secret\"");
int main() {
std::vector<std::string> block(std::sregex_token_iterator(buffer.begin(), buffer.end(), re1, -1), {});
std::map<std::string, std::string> entry{};
for (const auto& b : block) {
std::vector blockPart(std::sregex_token_iterator(b.begin(), b.end(), re2, 1), {});
entry[blockPart[0]] = blockPart[1];
}
for (const auto& [token, value] : entry)
std::cout << std::setw(20) << token << " --> " << value << '\n';
return 0;
}
But if you have a complex given format, like JSON, there are so many special cases that the only meaningful approach is to use an existing library.

error c2679 binary '=' no operator found which takes right hand operand of type std::tuple

I know there are multiple other questions like this but I've tried all the suggestions I've seen to no avail. I am attempting to write a vector (made of tuples containing a bool, int, and another int) with ostream. I've made sure to add std:: in front of everything it might need as I know that can be the problem often. I would appreciate any help. (the error in question happens at the bottom two lines, specifically the std::copy one, not sure if the rest of the code is important).
#include "Options.h"
#include <fstream>
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <vector>
#include <tuple>
#include <stdbool.h>
#include <stdint.h>
using namespace std;
using namespace smf;
int main(int argc, char** argv) {
Options options;
options.process(argc, argv);
MidiFile midifile;
midifile.read("lowtest.mid");
midifile.linkNotePairs();
midifile.sortTracks();
midifile.joinTracks();
midifile.deltaTicks();
std::tuple <bool, int, int> out;
std::vector <std::tuple<bool, int, int>> outlist;
int track = 0;
int i = 0;
for (int event = 0; event < midifile[track].size(); event++) {
if (midifile[track][event].isNoteOn()) {
out = std::make_tuple(true, (int)midifile[track][event][1], (int)midifile[track][event].getTickDuration());
outlist.push_back(out);
std::cout << std::get<0>(outlist[i]) << ' ' << std::get<1>(outlist[i]) << ' ' << std::get<2>(outlist[i]);
i = i + 1;
std::cout << " " << "I = " << i << std::endl;
}
}
std::cout << "done";
std::ofstream output_file("./output.txt");
std::ostream_iterator<std::tuple <bool, int, int>> output_iterator(output_file, "\n");
std::copy(outlist.begin(), outlist.end(), output_iterator);
return 0;
}
error:
Error C2679 binary '<<': no operator found which takes a right-hand operand of type 'const _Ty' (or there is no acceptable conversion) midiparser C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\include\iterator 336

C++: Unable to change the value of a std::pair using the "=" operator

I'm attempting to update the value of an std::pair, but that results in a compiler error. How can this be resolved?
#include <unordered_map>
#include <utility>
#include <string>
#include <iostream>
int main(int argc, char *argv[])
{
std::unordered_map<int, std::pair<std::string, std::string>> test1;
test1.insert(std::make_pair(1, std::make_pair("good1", "bad1")));
test1.insert(std::make_pair(2, std::make_pair("good2", "bad2")));
test1.insert(std::make_pair(3, std::make_pair("good3", "bad3")));
test1.insert(std::make_pair(4, std::make_pair("good4", "bad4")));
std::unordered_map<int, std::pair<std::string, std::string>>::const_iterator test2
= test1.find(1);
if (test2 == test1.end())
{
std::cout << "Could not find test2 in test1\n";
return 0;
}
std::cout << "First item is: " << test2->second.first << "...second item is: " << test2->second.second << "\n";
/* This line is throwing an error about "No operator '=' matches this operands. */
test2->second.second = "good";
std::cout << "First item is: " << test2->second.first << "...second item is: " << test2->second.second << "\n";
return 0;
}
You are using const_iterator instead of iterator for test2:
std::unordered_map<int, std::pair<std::string, std::string>>::const_iterator test2 ...
Use:
std::unordered_map<int, std::pair<std::string, std::string>>::iterator test2 ...
Or simplify it using auto:
auto test2 = test1.find(1);

Converting a code from c++ 11 to c++ 98?

I'm a beginner in c++ and my compiler (c-free 5.0) can't compile this code :-
#include <iostream>
#include <map>
#include <string>
int main()
{
std::string input = "slowly";
std::map<char, int> occurrences;
for (char character : input)
{
occurrences[character] += 1;
}
for (auto& entry : occurrences)
{
std::cout << entry.first << '=' << entry.second << std::endl;
}
}
Can anyone please tell me how to make it work in my compiler ?
Convert the range-based for to loops using iterator
Stop using auto and write the type manually
code:
#include <iostream>
#include <map>
#include <string>
int main()
{
std::string input = "slowly";
std::map<char, int> occurrences;
for (std::string::iterator character = input.begin(); character != input.end(); character++)
{
occurrences[*character] += 1;
}
for (std::map<char, int>::iterator entry = occurrences.begin(); entry != occurrences.end(); entry++)
{
std::cout << entry->first << '=' << entry->second << std::endl;
}
}