For loop in cpp for stringstream operations - c++

while using stringstream, I came across a piece for Parsing a comma-delimited std::string as below; I find for loop operation unique and new contrary to conventional operation as for(statement 1;statement 2;statement 3), I would like to understand this for loop for (int i; ss >> i;) used in below code, please let me know about these different use, thanks a lot.
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
int main()
{
std::string str = "1,2,3,4,5,6";
std::vector<int> vect;
std::stringstream ss(str);
for (int i; ss >> i;) {
vect.push_back(i);
if (ss.peek() == ',')
ss.ignore();
}
for (std::size_t i = 0; i < vect.size(); i++)
std::cout << vect[i] << std::endl;
}

Related

free(): invalid pointer when using scanf

Hello guys so this is my code.
I could not use cin nor getline() so I had to use scanf.
It reads all the values in as expected but after entering the last value it says:
free(): invalid pointer ./comp: line 8: 877 Aborted (core dumped) ./$BIN
Anyways, here is the code.
Help would be appreciated.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
// n -> amount of lines of code.
// q -> amount of queries.
int n, q;
cin >> n >> q;
// Handle source code Input.
vector<string> v(n);
for (unsigned i = 0; i < n; ++i)
{
cout << "i: " << i << endl;
scanf("%s", &v[i]);
}
return 0;
}
scanf is designed to work with character buffers, not strings. You probably want to use std::string (it's more intuitive and manages memory for you), so scanf is a poor fit. There's a version of getline that works with string.
std::vector<std::string> v(n);
for (int i = 0; i < n; i++) {
cout << "i: " << i << endl;
std::getline(std::cin, v[i]);
}
The %s specifier of scanf() expects a pointer to a char[] array, not a std::string object. By reading directly into a std::string object, you are corrupting its internals.
So, you need to either:
read into a char[] first, then assign that to your std::string:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
// n -> amount of lines of code.
// q -> amount of queries.
int n, q;
cin >> n >> q;
// Handle source code Input.
vector<string> v(n);
char buf[256];
for (unsigned i = 0; i < n; ++i)
{
cout << "i: " << i << endl;
scanf("%255s", buf);
v[i] = buf;
/* or:
int len = scanf("%255s", buf);
v[i] = string(buf, len);
*/
}
return 0;
}
pre-allocate the std::string's internal character buffer, then read directly into it (note, this approach is only guaranteed to work in C++11 and later, but in practice will typically work in most implementations of std::string in earlier versions, too):
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
// n -> amount of lines of code.
// q -> amount of queries.
int n, q;
cin >> n >> q;
// Handle source code Input.
vector<string> v(n);
for (unsigned i = 0; i < n; ++i)
{
cout << "i: " << i << endl;
v[i].resize(256);
int len = scanf("%255s", &v[i][0]/* or: v[i].data() in C++17 and later */);
v[i].resize(len);
}
return 0;
}

Extract words from a file and put them into a `std::vector` of `std::array<string,4>`

The following is the file(ka.txt) from which I want to read lines :-
ASD|BSD|CSdsa|ood
fmads|aok|pdski
kdijf|okmdsomf|opkasd|okd
asdas
kamkd|aoda|kked|ok
The following is the code that I've written to put this data into a vector of std::array<std::string, 4>.
#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <fstream>
#include <sstream>
int main(){
std::fstream file("ka.txt");
std::vector<std::array<std::string, 4>> darr; darr.reserve(5);
std::array<std::string, 4> istd;
std::string * line = new std::string; std::string * word = new std::string;
while(std::getline(file, *line)){
std::stringstream ss(*line);
int per = 0;
while(!ss.eof()){
std::getline(ss, *&istd[per], '|');
per++;
}
darr.emplace_back(istd);
}
file.close();
for(int i = 0; i < darr.size(); i++){
for(int j = 0; j < 4; j++){
std::cout << darr[i][j] << "\t";
}
std::cout << "\n";
}
return 0;
}
Basically, I have a vector which has std::array's and each std::array is of size 4. So I am reading the data from the file with | delimiter. And I want to store each element in every row of the text file as a std::array. And storing these std::arrays in one vector. Also, if one row has 4 elements separated by |, then there should be four elements in the std::array. If there is only one element in the row, then there should be only one element in the std::array
So when I run this code I get the following output:-
ASD BSD CSdsa ood
fmads aok pdski
kdijf okmdsomf opkasd okd
asdas opkasd okd
kamkd aoda kked ok
So, the fourth row has a wrong std::array since it should only have one element, but instead it should have only one. How can I achieve this?
Also, I think the probable problem is in the while loop which begins at line 12 of the code.
This is because the array istd is used without initializing, so data from previous lines remains when no data is read there.
std::array<std::string, 4> istd;
should be after
while(std::getline(file, *line)){
I tested the below code. Usage of istd made it to show wrong output as it remembers the previous values. I changed it to use vector instead of array.
As pointed by Paul,we don't need to use new for string. So removed it.
#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <fstream>
#include <sstream>
int main(){
std::fstream file("file.txt");
vector<vector<string>> darr;
std::string line,word;
while(std::getline(file, line))
{
std::stringstream ss(line);
vector<string> temp;
string str;
while(!ss.eof())
{
std::getline(ss, str, '|');
temp.push_back(str);
}
darr.emplace_back(temp);
}
file.close();
for(int i = 0; i < darr.size(); i++)
{
for(int j = 0; j < 4; j++)
std::cout << darr[i][j] << " ";
printf("\n");
}
return 0;
}
I also have a shortened version of the same code incase if you dont want to store.
int main(){
std::fstream file("file.txt");
std::string line,word;
while(std::getline(file, line))
{
std::stringstream ss(line);
vector<string> temp;
string str;
while(!ss.eof())
{
std::getline(ss, str, '|');
std::cout << str << " ";
}
printf("\n");
}
file.close();
return 0;
}
Output:
ASD BSD CSdsa ood
fmads aok pdski
kdijf okmdsomf opkasd okd
asdas
kamkd aoda kked ok

C++ simple string program

beginner here
i wrote the below in C++, it's a short program that currently takes 2 words as inputs, and outputs the same words back but the words are split into even and odd instead. I would like to be able to do this for 'T' words instead, but I can't figure it out. I would like to be able to first input the number of words that will follow, for example 10. Then to input the words and get T results back. So instead of just 2 words, an unlimited amount with the user specifying.
I need to put the below into a function and go from there sometime, but I want to learn the best technique to do so - any advice please?
Thanks!
Alex
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main() {
int T;
cin >> T;
string FirstWord;
cin >> FirstWord;
int LengthFirst;
LengthFirst = FirstWord.length();
string EvenFirst;
string OddFirst;
for (int i = 0; i < LengthFirst; i += 2){
EvenFirst = EvenFirst + FirstWord[i];
}
for (int i = 1; i < LengthFirst; i += 2){
OddFirst = OddFirst + FirstWord[i];
}
string SecondWord;
cin >> SecondWord;
int LengthSecond;
LengthSecond = SecondWord.length();
string EvenSecond;
string OddSecond;
for (int i = 0; i < LengthSecond; i += 2){
EvenSecond += SecondWord[i];
}
for (int i = 1; i < LengthSecond; i += 2){
OddSecond += SecondWord[i];
}
cout << EvenFirst << " " << OddFirst << endl;
cout << EvenSecond << " " << OddSecond << endl;
return 0;
}
Think I got it here, I was over-thinking this one
I put it in a for loop, as below - so any number of words can be input, user has to input the number of test cases at the
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main() {
int T;
cin >> T;
for (int i = 0; i < T; i++){
string FirstWord;
cin >> FirstWord;
int LengthFirst;
LengthFirst = FirstWord.length();
string EvenFirst;
string OddFirst;
for (int i = 0; i < LengthFirst; i += 2){
EvenFirst = EvenFirst + FirstWord[i];
}
for (int i = 1; i < LengthFirst; i += 2){
OddFirst = OddFirst + FirstWord[i];
}
cout << EvenFirst << " " << OddFirst << endl;
}
return 0;
}
Ultimately, you are performing the same task N times.
First, let's discuss how to store the information. Functionally, we have one string as input which yields two strings as output. std::pair (from <utility>) lets us easily represent this. But for sake of even-odd, std::array might be a better representation for us. Since we have a variable number of words as input, a variable number of std::array will be output. std::vector (from <vector>) is our friend here.
Second, let's discuss how to process the information. Using named variables for each output component does not scale, so let's switch to a fixed array (noted below as array<string,2>. By switching to a fixed array for output, addressing each split becomes a function of the loop index (index % 2). Below is a solution that generalizes on a known split size at compile time.
#include <string>
#include <array>
#include <vector>
#include <iostream>
int main() {
int N;
std::cin >> N;
constexpr const int Split = 2;
using StringPack = std::array<std::string, Split>;
std::vector<StringPack> output;
for (int wordIndex = 0; wordIndex < N; ++wordIndex) {
std::string word;
std::cin >> word;
StringPack out;
{
int index = 0;
for (char c : word) {
out[index % Split] += c;
++index;
}
}
output.emplace_back(out);
}
for (const auto & out : output) {
for (const auto & word : out) {
std::cout << word << ' ';
}
std::cout << '\n';
}
}

getline() with delim not working as intended

I'm trying to split this a string with a comma as a delimeter. I put a string "Smith,Erdos,William" and it just outputs "William" but not Smith and Erdos. There must be something wrong here that I just can't see, can anyone help?
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
int main() {
int numScenarios(0);
int numPapers(0);
int numWriters(0);
std::vector<std::string> paperTitles (1);
std::vector<std::string> paperAuthors (1);
std::vector<std::string> splitAuthors (1);
std::string token;
std::string input;
std::cin >> numScenarios;
std::cin >> numPapers >> numWriters;
for (int i(0); i < numPapers; ++i) {
std::getline(std::cin,input);
std::istringstream iss(input);
while(getline(iss,token,','));
{
std::cout << token << std::endl;
}
//paperTitles.push_back(input);
//input = '\0';
}
for (int i(0); i < numWriters; ++i) {
getline(std::cin,input);
paperAuthors.push_back(input);
input = '\0';
}
return 0;
}
while(getline(iss,token,',')); // <== look closely

get list of numbers from stdin and tokenize them

How would I get a list of numbers from the user and then tokenize them.
This is what I have but it doesn't get anything except for the first number:
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string line = "";
cin >> line;
stringstream lineStream(line);
int i;
vector<int> values;
while (lineStream >> i)
values.push_back(i);
for(int i=0; i<values.size(); i++)
cout << values[i] << endl;
system("PAUSE");
return 0;
}
Related Posts:
C++, Going from string to stringstream to vector
Int Tokenizer
Here is probably the easiest way to read values from cin into a container:
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> values;
std::copy(
std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
std::back_inserter(values));
// For symmetry with the question copy back to std::cout
std::copy(
values.begin(),
values.end(),
std::ostream_iterator<int>(std::cout,"\n"));
}
I believe cin >> breaks on whitespace, which means you're only getting the first number entered.
try:
getline(cin, line);
Like Donnie mentioned cin breaks on whitespace, so do overcome this we can use a 'getline()', the following example works nicely:
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string line = "";
::getline(std::cin,line,'\n');
std::stringstream lineStream(line);
int i;
std::vector<int> values;
while (lineStream >> i)
values.push_back(i);
for(int i=0; i<values.size(); i++)
cout << values[i] << endl;
system("PAUSE");
return 0;
}
on top of main
string line = "";
getline (cin, line );
stringstream lineStream(line);
Yep, and is the string version of getline, no the istream one.
OK: Pavel Minaev has the best answer.
But all the people mentioning that cin breaks on white space.
That is a good thing (because it also ignores white space);
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
int i;
vector<int> values;
// prefer to use std::copy() but this works.
while (std::cin >> i)
{
values.push_back(i);
}
// prefer to use std::copy but this works.
for(vector<int>::const_iterator loop = values.begin();loop != values.end();++loop)
{
cout << *loop << endl;
}
return 0;
}