Strange behaviour of for_each and push_back() - c++11

I was doing some testing with for_each and the use of lambda functions and I'm stuck on this (compiled with g++ -std=c++11, gcc version 5.3.1)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> vi = {1,1,1,1};
int end =0;
cout << "vi contains: ";
for_each(vi.begin(), vi.end(),[](int i){
cout << i << " ";
});
cout << endl;
for_each(vi.begin(),vi.end(),[&](int i){
cout << "i="<<i<<" ";
if(i==1){
vi.push_back(1);
end++;
}
});
cout << endl;
cout << "end=" << end << endl;
cout << "now vi contains: ";
for_each(vi.begin(), vi.end(),[](int i){
cout << i << " ";
});
cout << endl;
return 0;
}
and this is the output of this code
vi contains: 1 1 1 1
i=1 **i=0** i=1 i=1
end=3
now vi contains: 1 1 1 1 1 1 1
why is, at the first iteration of the loop, i equal to 0?

Related

Generate C++ string with space behind such that space is automatically adjusted

I am trying to create a text generator which shall generate following output:
localparam OR_CHANNEL_DATA_WIDTH = 2;
localparam RQ_CHANNEL_DATA_WIDTH = 18;
localparam RSP_CHANNEL_DATA_WIDTH = 8;
localparam VIN_CHANNEL_DATA_WIDTH = 43;
localparam VOUT_CHANNEL_DATA_WIDTH = 123;
I used std::stringstream to build the stream:
std::stringstream ss;
ss << "localparam OR_CHANNEL_DATA_WIDTH" << std::right << std::setw(80) << " = " << Sth::get() << ";\n";
ss << "localparam RQ_CHANNEL_DATA_WIDTH" << std::right << std::setw(80) << " = " << Sth::get() << ";\n";
ss << "localparam RSP_CHANNEL_DATA_WIDTH" << std::right << std::setw(80) << " = " << Sth::get() << ";\n";
Sth::get() will return number. There are many such lines that needs to be generated. But the text in the middle is not fixed. How can I achieve the above output
I am not sure you can do it in a simple streaming operation, but easily write a small function that does the job:
#include <iostream>
#include <sstream>
#include <iomanip>
const std::string adjust_width(const std::string& s, int width)
{
std::stringstream temp;
temp << std::left << std::setw(width) << s;
return temp.str();
}
int main()
{
std::stringstream ss;
ss << adjust_width("localparam OR_CHANNEL_DATA_WIDTH", 80) << " = " << 1 << ";\n";
ss << adjust_width("localparam RQ_CHANNEL_DATA_WIDTH", 80) << " = " << 12 << ";\n";
ss << adjust_width("localparam RSP_CHANNEL_DATA_WIDTH", 80) << " = " << 123 << ";\n";
ss << adjust_width("localparam VIN_CHANNEL_DATA_WIDTH", 80) << " = " << 1234 << ";\n";
std::cout << ss.str();
return 0;
}

How to append more items to an existing vector contained in the value field of a std::map?

I have a std::vector<std::string>>. Following is my full program:
#include <iostream>
#include <vector>
#include <string>
#include <map>
int main() {
std::cout << " -- Beginining of program -- " << std::endl;
std::map<std::string, std::vector<std::string>> my_map_2;
std::vector<std::string> s = {"a", "b", "c"};
my_map_2.insert(std::make_pair("key1", s));
std::vector<std::string> s2 = {"d", "e", "f"};
my_map_2.insert(std::make_pair("key1", s2));
for(auto const &map_item: my_map_2) {
std::cout << map_item.first << " " << map_item.second[0] << std::endl;
std::cout << map_item.first << " " << map_item.second[1] << std::endl;
std::cout << map_item.first << " " << map_item.second[2] << std::endl;
std::cout << map_item.first << " " << map_item.second[3] << std::endl;
std::cout << map_item.first << " " << map_item.second[4] << std::endl;
std::cout << map_item.first << " " << map_item.second[5] << std::endl;
}
std::cout << " -- End of program -- " << std::endl;
return 0;
}
Problem:
I don't see the items of s2 when I print values of my_map_2. I see them only if I add s2 with a new key! If I do my_map_2.insert(std::make_pair("key2", s2)) instead of my_map_2.insert(std::make_pair("key1", s2)), I do see the items.
Question:
So, my question is, how to I append more items to the vector pointed to by key1 of my_map_2?
The below fails because the key is already taken:
std::vector<std::string> s2 = {"d", "e", "f"};
my_map_2.insert(std::make_pair("key1", s2)); // fails
To append to the mapped vector, you could do like this:
auto& vec = my_map_2["key1"]; // get reference to the existing vector
vec.insert(vec.end(), s2.begin(), s2.end()); // append to it
To view the keys and all the values in the vector you could change your loop to this:
for(auto const&[key, value]: my_map_2) {
for(const std::string& str : value) {
std::cout << key << ' ' << str << '\n';
}
}
my_map_2["key1"] is always a valid vector. You can insert into it directly
#include <iostream>
#include <vector>
#include <string>
#include <map>
int main() {
std::cout << " -- Beginining of program -- " << std::endl;
std::map<std::string, std::vector<std::string>> my_map_2;
std::vector<std::string> s = {"a", "b", "c"};
my_map_2["key1"].insert(my_map_2["key1"].end(), s.begin(), s.end());
std::vector<std::string> s2 = {"d", "e", "f"};
my_map_2["key1"].insert(my_map_2["key1"].end(), s2.begin(), s2.end());
for(auto const &map_item: my_map_2) {
for(auto const &value: map_item.second) {
std::cout << map_item.first << " " << value << std::endl;
}
}
std::cout << " -- End of program -- " << std::endl;
return 0;
}
Get iterator to key1, and just pushs back new items to existing vector:
std::vector<std::string> s2 = {"d", "e", "f"};
auto it = my_map_2.find("key1");
if (it != my_map_2.end())
std::move(s2.begin(), s2.end(), std::back_inserter(it->second));
else
my_map_2.insert(std::make_pair("key1",std::move(s2)));
To see: d,e,f you have to access 3,4 and 5 indices of vector. (You want to append new items, or just override existed items for given key?)

How to use OpenMP to deal with two for loops with

I am new to OpenMP... Please help me with this dumb question. Thank you :)
Basically, I want to use OpenMP to speed up two for loops. But I do not know why it keeps saying: invalid controlling predicate for the for loop.
By the way, my GCC version is gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005, and OS I am using is Ubuntu 16.10.
Basically, I generate a toy data that has a typical Key-Value style, like this:
Data = {
"0": ["100","99","98","97",..."1"];
"1": ["100","99","98","97",..."1"];
...
"999":["100","99","98","97",..."1"];
}
Then, for each key, I want to compare its value with the rest of the keys. Here, I sum them up through "user1_list.size()+user2_list.size();". As for each key, the sum-up process is totally independent of other keys, which means this works for parallelism.
Here is my toy example code.
#include <map>
#include <vector>
#include <string>
#include <iostream>
#include "omp.h"
using namespace std;
int main(){
// Create Data
map<string, vector<string>> data;
for(int i=0; i != 1000; i++){
vector<string> list;
for (int j=100; j!=0; j--){
list.push_back(to_string(j));
}
data[to_string(i)]=list;
}
cout << "Data Total size: " << data.size() << endl;
int count = 1;
#pragma omp parallel for private(count)
for (auto it=data.begin(); it!=data.end(); it++){
//cout << "Evoke Thread: " << omp_get_thread_num();
cout << " count: " << count << " / " << data.size() << endl;
count ++;
string user1 = it->first;
vector<string> user1_list = it->second;
for (auto it2=data.begin(); it2!=data.end(); it2++){
string user2 = it2->first;
vector<string> user2_list = it2->second;
cout << "u1:" << user1 << " u2:" << user2;
int total_size = user1_list.size()+user2_list.size();
cout << " total size: " << total_size << endl;
}
}
return 0;
}

C ++ , My for loop doesn't work when I run it on the terminal. Any ideas?

When I run it on the terminal it works fine but the loop. The for loop just doesn't do anything at all. I'm learning C++, so I don't know much.
#include <iostream>
#include <cstring>
using namespace std;
int main( int argc, char *argv[] ) {
if (argc == 2) {
cout << "The first argument is " << argv[0] << endl;
cout << "The second argument is " << argv[1] << endl;
} else if (argc > 2) {
cout << "Too many arguments" << endl;
exit(0);
} else {
cout << "Only one argument" << endl;
cout << "The argument is " << argv[0] << endl;
exit(0);
}
if (atoi(argv[1]) < 0) {
cout << "Error negative number" << endl;
exit(0);
}
// this loop does not work, everything else does.
for (int i = 1; i >= atoi(argv[1]); i++){
int count = atoi(argv[1]--);
cout << count << endl;
int sum = sum + i;
}
cout << "The sum is: " << endl;
return(0);}
I think that could be the if statements what are messing around with the loop.
I think you made mistake in the for loop.
You show use "<=" instead of ">=" in the for loop.
Hope this might helps you.
I guess your code is not reaching the for loop as you have exit() conditions on each and every condition of if. Your code only reaches the loop if you are passing 2 arguments in the terminal while you are running your code

Why doesn't the lock lock?

I have this minimal code:
#include <mutex>
#include <iostream>
std::mutex themutex;
void f1()
{
std::cout << "1" << std::endl;
std::lock_guard<std::mutex> local_mutex(themutex);
std::cout << "2" << std::endl;
}
void f2()
{
std::cout << "3" << std::endl;
std::lock_guard<std::mutex> local_mutex(themutex);
std::cout << "4" << std::endl;
f1();
std::cout << "5" << std::endl;
}
int main(void)
{
f2();
return 0;
}
I compile and run with
g++ -std=c++11 test_mutex.cc -o test_mutex && ./test_mutex
and I get this output:
3
4
1
2
5
Why?
I expect the program to lock after printing "1" and never to return.
From 30.4.1 ("Mutex requirements"):
The expression m.lock() shall be well-formed and have the following semantics:
Requires: If m is of type std::mutex or std::timed_mutex, the calling thread does not own the mutex.
You're violating the requirements, and so you cannot expect any behaviour guaranteed by the standard.

Resources