c++: Iteration of vector<string> - c++

#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> a;
a.push_back("1 1 2 4");
a.push_back("2 3 3 3");
a.push_back("2 2 3 5");
a.push_back("3 3 3 3");
a.push_back("1 2 3 4");
for (int i=0;i<a.size();i++)
for(int j=0;j<a[i].length();j++)
cout<<a[i].at[j];
return 0;
}
Hi,when I run the code above,there is an error as below:
error C2109: subscript requires array or pointer type
Please help me and tell me why,thanks!

at is a function, need to be called with () not []
update
cout<<a[i].at[j];
// ^^^
to
a[i].at(j)
// ^^^^^
To output string, you don't need to cout each char, just do
for (int i=0; i<a.size(); i++)
{
std::cout << a[i] << "\n";
}
std::cout << std::endl;
Or if C++11:
for(auto const & s : a)
{
cout << s << "\n";
}

It is more simpler to use the range-based for statement. For example
for ( const std::string &s : a )
{
for ( char c : s ) std::cout << c;
std::cout << std::endl;
}

Related

C++: sum of columns of a dynamic 2D vector

In C++, how to use a two-dimensional dynamic vector to sum up each column for the matrix in the txt file, and print out the content of the txt file and the result of summing up each column?
After searching through the Internet, I got the following code, but it only sums up a single column. The result I want to get is that no matter how many columns there are in the txt file, I can do the sum of each column.
data.txt figure
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
int main() {
ifstream myfile("data.txt");
if (!myfile.is_open()) {
cout << "Unable to open myfile";
system("pause");
exit(0);
}
vector<string> vec;
string temp;
while (getline(myfile, temp))
{
vec.push_back(temp);
}
vector <float> radius;
cout << "Processing time: " << endl;
for (auto it = vec.begin(); it != vec.end(); it++)
{
cout << *it << endl;
istringstream is(*it);
string s;
int pam = 0;
while (is >> s)
{
if (pam == 0)
{
float r = atof(s.c_str());
radius.push_back(r);
}
pam++;
}
}
cout << "matrix: " << endl;
double sum;
sum = 0;
for (auto it = radius.begin(); it != radius.end(); it++)
{
sum += *it;
}
cout << sum << endl;
system("pause");
return 0;
}
I want to sum each column in the txt file, as shown in the image below:
result
The first thing you should do is not concern yourself with where the data is coming from. Instead, you should write a function that takes the data, regardless of where it comes from, and outputs the totals.
The simplest way to represent the input data is to use a std::vector<std::vector<float>>. Thus a function to create the totals would return a std::vector<float> that represents the totals.
Here is an example of such a function:
#include <vector>
#include <numeric>
// Pass in the data
std::vector<float> getTotals(const std::vector<std::vector<float>>& myData)
{
std::vector<float> totals(myData[0].size());
for (size_t i = 0; i < totals.size(); ++i)
{
// call std::accumulate for each column i
totals[i] = std::accumulate(myData.begin(), myData.end(), 0,
[&](int total, auto& v)
{ return total + v[i]; });
}
// return the totals
return totals;
}
The above function uses std::accumulate to total the values in column i, and store the total for that column in totals[i].
Once this function is written, it can then be tested. Here is a full example:
#include <vector>
#include <numeric>
#include <iostream>
std::vector<float> getTotals(const std::vector<std::vector<float>>& myData)
{
std::vector<float> totals(myData[0].size());
for (size_t i = 0; i < totals.size(); ++i)
{
totals[i] = std::accumulate(myData.begin(), myData.end(), 0,
[&](int total, auto& v)
{ return total + v[i]; });
}
return totals;
}
void printTotals(const std::vector<std::vector<float>>& data,
const std::vector<float>& totals)
{
for (auto& v : data)
{
for (auto& v2 : v)
std::cout << v2 << " ";
std::cout << "\n";
}
std::cout << "Total: ";
for (auto& t : totals)
std::cout << t << " ";
}
int main()
{
std::vector<std::vector<float>> test1 = {{1,2,3},{4,5,6},{7,8,9}};
std::vector<std::vector<float>> test2 = {{1,2,3,4},{4,5,6,8},{7,8,9,10}};
std::vector<std::vector<float>> test3 = {{1,2},{-3,4},{7,8},{34,12},{12,17}};
printTotals(test1, getTotals(test1));
std::cout << "\n\n";
printTotals(test2, getTotals(test2));
std::cout << "\n\n";
printTotals(test3, getTotals(test3));
}
Output:
1 2 3
4 5 6
7 8 9
Total: 12 15 18
1 2 3 4
4 5 6 8
7 8 9 10
Total: 12 15 18 22
1 2
-3 4
7 8
34 12
12 17
Total: 51 43
Once you have this, the next step is to create the std::vector<std::vector<float>> from the data in the file. Once that is created, it is just a simple matter of calling the getTotals() function with that data.
The file reading can be as follows:
#include <istream>
#include <sstream>
#include <vector>
#include <string>
//...
std::vector<std::vector<float>> readData(std::istream& is)
{
std::vector<std::vector<float>> data;
std::string oneLine;
float oneData;
while (std::getline(is, oneLine))
{
std::vector<float> vOneData;
std::istringstream strm(oneLine);
while (strm >> oneData)
vOneData.push_back(oneData);
data.push_back(vOneData);
}
return data;
}
The function is called by simply passing in the stream object (in your case, myfile). The returned value will be a std::vector<std::vector<float>> of the values that were read in.
Putting this all together:
#include <vector>
#include <numeric>
#include <iostream>
#include <istream>
#include <string>
#include <sstream>
std::vector<float> getTotals(const std::vector<std::vector<float>>& myData)
{
std::vector<float> totals(myData[0].size());
for (size_t i = 0; i < totals.size(); ++i)
{
totals[i] = std::accumulate(myData.begin(), myData.end(), 0,
[&](int total, auto& v)
{ return total + v[i]; });
}
return totals;
}
void printTotals(const std::vector<std::vector<float>>& data,
const std::vector<float>& totals)
{
for (auto& v : data)
{
for (auto& v2 : v)
std::cout << v2 << " ";
std::cout << "\n";
}
std::cout << "Total: ";
for (auto& t : totals)
std::cout << t << " ";
}
std::vector<std::vector<float>> readData(std::istream& is)
{
std::vector<std::vector<float>> data;
std::string oneLine;
float oneData;
while (std::getline(is, oneLine))
{
std::vector<float> vOneData;
std::istringstream strm(oneLine);
while (strm >> oneData)
vOneData.push_back(oneData);
data.push_back(vOneData);
}
return data;
}
int main()
{
std::string fileData = "2 3 4 1 5 2\n6 1 2 6 1 8\n8 7 3 9 6 4";
std::istringstream fileDataStream(fileData);
auto dataFromFile = readData(fileDataStream);
printTotals(dataFromFile, getTotals(dataFromFile));
}
Output:
2 3 4 1 5 2
6 1 2 6 1 8
8 7 3 9 6 4
Total: 16 11 9 16 12 14
Note that I didn't use a file stream, but a stringstream to illustrate it doesn't matter how the data is created.

map,vector in c++ [duplicate]

This question already has answers here:
How do I print out the contents of a vector?
(31 answers)
Closed 2 years ago.
error: no match for ‘operator<<’ (operand types are ‘std::basic_ostream’ and ‘std::pair<const std::__cxx11::basic_string, std::vector >’)
i want to same key and mutiple values, for example key is 10 values are 2,3,4
but "*iter" is wrong..
how to cout map,vector in c++?
In your code snippet the value of the expression *iter is an object of the type std::pair<std::string, std::vector<int>> for which the operator << is not defined.
And the error message
error: no match for ‘operator<<’ (operand types are ‘std::basic_ostream’ and
‘std::pair<const std::__cxx11::basic_string, std::vector >’)
says about this.
The simplest way is to use the range-based for loop.
Here is a demonstrative program.
#include <iostream>
#include <string>
#include <vector>
#include <map>
int main()
{
std::map<std::string, std::vector<int>> m;
m["10"].assign( { 2, 3, 4 } );
for ( const auto &p : m )
{
std::cout << p.first << ": ";
for ( const auto &item : p.second )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
return 0;
}
The program output is
10: 2 3 4
If you want to write ordinary for-loops using iterators then the loops can look the following way.
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <iterator>
int main()
{
std::map<std::string, std::vector<int>> m;
m["10"].assign( { 2, 3, 4 } );
for ( auto outer_it = std::begin( m ); outer_it != std::end( m ); ++outer_it )
{
std::cout << outer_it->first << ": ";
for ( auto inner_it = std::begin( outer_it->second );
inner_it != std::end( outer_it->second );
++inner_it )
{
std::cout << *inner_it << ' ';
}
std::cout << '\n';
}
return 0;
}
Again the program output is
10: 2 3 4
I suggest using structured bindings and range-based for loops:
std::map<std::string,std::vector<int>> m;
for (auto&[str, vec] : m) { // bind str to "first" in the pair and vec to "second"
std::cout << str << ':';
for(auto lineno : vec) std::cout << ' ' << lineno;
std::cout << '\n';
}
You can define how to print things via std::ostream like this:
#include <iostream>
#include <map>
#include <vector>
#include <string>
// define how to print std::pair<std::string, std::vector<int>>
std::ostream& operator<<(std::ostream& stream, const std::pair<std::string, std::vector<int>>& pair) {
stream << "(" << pair.first << ", {";
bool first = true;
for (int e : pair.second) {
if (!first) stream << ", ";
stream << e;
first = false;
}
stream << "})";
return stream;
}
int main(void) {
std::string yytext = "hoge";
int lineno = 42;
// below is copied from the question
std::map<std::string,std::vector<int>> m;
m[yytext].push_back(lineno);
std::map<std::string,std::vector<int>>::iterator iter;
for (iter=m.begin(); iter!=m.end(); iter++){
std::cout<<iter->first<<":"<<*iter<<std::endl;}
}

C++ String Stream

I'm just learning how to use streams in C++ and I have one question.
I thought that each stream has state true or false. I want to enter each word from the string below and 1 until there is a word, but I get an error:
cannot convert 'std::istringstream {aka std::__cxx11::basic_istringstream<char>}' to 'bool' in initialization
bool canReadMore = textIn;
It should be like:
antilope
1
ant
1
antagonist
1
antidepressant
1
What am I doing wrong?
int main() {
std:: string text = "antilope ant antagonist antidepressant";
std:: istringstream textIn(text);
for(int i = 0; i < 5; i++ ){
std:: string s;
textIn >> s;
bool canReadMore = textIn;
std::cout << s << std:: endl;
std::cout << canReadMore << std:: endl;
}
return 0;
}
``1
Since C++11, std::istringstream operator bool is explicit. What this means is that you must explicitly make the cast yourself:
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::string text = "antilope ant antagonist antidepressant";
std::istringstream textIn(text);
for (int i = 0; i < 5; i++) {
std::string s;
textIn >> s;
bool canReadMore = bool(textIn);
std::cout << s << std::endl;
std::cout << canReadMore << std::endl;
}
return 0;
}
Output:
./a.out
antilope
1
ant
1
antagonist
1
antidepressant
1
0
Now, if you use a std::stringstream in a bool context, the conversion will be automatic. This is an idiomatic use:
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::string text = "antilope ant antagonist antidepressant";
std::istringstream textIn(text);
std::string s;
while (textIn >> s) {
std::cout << s << "\n";
}
}
Output:
antilope
ant
antagonist
antidepressant

why c++ std accumulate is always return 0

I am trying to use c++ to sum 3 integers from the input, but I keep get 0. Please help thx.
vector<int> x;
x.reserve(3);
cin >> x[0] >> x[1] >> x[2];
int sum = std::accumulate(x.begin(), x.end(), 0);
cout << sum << endl;
return 0;
1
2
3
0
vector::reserve(size_type n) will request a change in the capacity of the vector, not the size. You can use the resize function, or even better the constructor.
int main()
{
std::vector<int> x(3,0); //set the size to 3 and fill with zeros.
std::cin >> x[0] >> x[1] >> x[2];
int sum = std::accumulate(x.begin(), x.end(), 0);
std::cout << sum << std::endl;
}
You can read this answer here for the differences between reserve vs resize.
Fill your vector first with something if not you will probably get undefined
vector<int> x(3,0);
use c++ to sum 3 integers from the input
why accumulate always return 0
This answer uses push_back(), and does not need to know how many integers are input, as the vector will auto expand; In this way it sidesteps the issues of std::vector that were defeating your code.
Consider that, because a "how many int" might be submited is seldom fixed you are more likely to want to count how many input "on the fly". So perhaps use a loop, cin to a local var, then x.push_back( a_local_var), and repeat until some condition (maybe eof(), or local var == -1, etc.) x.size() is your counter.
Here is a functioning example, using command line vars and eof() (and a vector and accumulate).
// Note: compile with -std=c++17 for the using comma list
#include <iostream>
using std::cout, std::cerr, std::endl, std::hex, std::dec, std::cin, std::flush; // c++17
#include <vector>
using std::vector;
#include <string>
using std::string;
#include <sstream>
using std::stringstream;
#include <numeric>
using std::accumulate;
#include <cassert>
class T951_t // ctor and dtor compiler provided defaults
{
public:
int operator()(int argc, char* argv[]) { return exec(argc, argv); } // functor entry
private:
stringstream ssIn; // to simulate user input
int exec(int argc, char* argv[])
{
int retVal = initTest(argc, argv); // transfer command line strings into ssIn
if(retVal != 0) return retVal;
// ------------------------------------------------------------
// simulate unknown quantity of ints
vector<int> x;
do {
int localInt = 0;
ssIn >> localInt;
if(!ssIn.good()) // was transfer ok?
{ // no
if (ssIn.eof()) break; // but we tolerate eof
// else err and exit
cerr << "\n !ssIn.good() failure after int value "
<< x.back() << endl;
assert(0); // harsh - user typo stops test
}
x.push_back(localInt); // yes transfer is ok, put int into vector
//cout << "\n " << localInt; // diagnostic
} while(true);
showResults(x);
return 0;
}
// this test uses a stringstream (ssIn) to deliver input to the app
// ssIn is initialized from the command line arguments
int initTest(int argc, char* argv[])
{
if (argc < 2) {
cerr << "\n integer input required" << endl;
return -1;
}
// test init
for (int i=1; i < argc; ++i) {
// cout << "\n " << argv[i]; // diagnostic
ssIn << argv[i] << " "; // user text into stream
}
cout << endl;
return 0;
}
// display size and contents of vector x
void showResults(vector<int> x)
{
cout << "\n x.size(): " << x.size() << endl;
int sum = std::accumulate(x.begin(), x.end(), 0);
for (auto i : x)
cout << " " << i;
cout << endl;
cout << "\n sums to: " << sum << '\n' << endl;
}
}; // class T951_t
int main(int argc, char* argv[]) { return T951_t()(argc, argv); } // call functor
Tests:
./dumy951 1 2 3 55 12345678900 <-- fail after 55 because last int too big
./dumy951 1 2 3 y 55 12345678900 <-- fail after int value 3 (invalid int)
./dumy951 1 2 3 4 5 6 7 8 9 10 <-- success, result is 55

C++ reading sentences

string a = MwZwXxZwDwJrBxHrHxMrGrJrGwHxMrFrZrZrDrKwZxLrZrFwZxErMrXxArZw;
Assume i have this data in my string . I want to record how many M , Z , X , D , J (including those capital letters i didn't mentions ) in in string how can do it ? My friends say use vector can do it but i does not really know how to use vector is there any alternative way to do it .
I tried using for loops to do and find the M , and reset the pointer to 0 to continue find the next capital value , but not sure is there any easier way to do it .
first I'll show you a 'easier' way to me.
#include <iostream>
#include <map>
using namespace std;
int main(int argc, const char * argv[]) {
string str = "MwZwXxZwDwJrBxHrHxMrGrJrGwHxMrFrZrZrDrKwZxLrZrFwZxErMrXxArZw";
map<char,int> map;
for (int i=0; i<str.length(); i++) {
char ch = str[i];
if (isupper(ch)) {
map[ch] ++;
}
}
for (auto item : map) {
cout<<item.first<<':'<<item.second<<endl;
}
return 0;
}
you'll only need to use 1 loop to solve your problem.
the 'isupper(int _c)' is a function from the standard library, it can tell you wether a character is a capital letter.
the 'map' is a data structure from the standard library too, it can do key-value storage for you.
this program outputs this:
A:1
B:1
D:2
E:1
F:2
G:2
H:3
J:2
K:1
L:1
M:4
X:2
Z:8
is this what you want?
Use regex.
using namespace std;
// regex_search example
#include <iostream>
#include <string>
#include <regex>
int main ()
{
std::string s ("MwZwXxZwDwJrBxHrHxMrGrJrGwHxMrFrZrZrDrKwZxLrZrFwZxErMrXxArZw;");
std::smatch m;
std::regex e ("[A-Z\s]+");
map<string,int> map;
std::cout << "Target sequence: " << s << std::endl;
std::cout << "Regular expression: [A-Z\s]+" << std::endl;
std::cout << "The following matches and submatches were found:" << std::endl;
while (std::regex_search (s,m,e)) {
for (auto x:m)
{
//cout << x << " ";
map[x.str()] ++;
}
//cout << std::endl;
s = m.suffix().str();
}
for (auto item : map) {
cout<<item.first<<':'<<item.second<<endl;
}
return 0;
}
The most direct translation of "loop through the string and count the uppercase letters" into C++ I can think of:
#include <iostream>
#include <map>
#include <cctype>
int main()
{
string a = "MwZwXxZwDwJrBxHrHxMrGrJrGwHxMrFrZrZrDrKwZxLrZrFwZxErMrXxArZw";
std::map<char, int> count;
// Loop through the string...
for (auto c: a)
{
// ... and count the uppercase letters.
if (std::isupper(c))
{
count[c] += 1;
}
}
// Show the result.
for (auto it: count)
{
std::cout << it.first << ": " << it.second << std::endl;
}
}