If I had a list of integers separated by a space on one line (eg: 50 34 1 3423 5 345) then what would be the best way of making each of them a separate integer variable - collecting the list of integers with cin?
#include <iostream>
#include <vector>
#include <iterator>
std::vector<int> ints;
std::copy(std::istream_iterator<int>(cin),
std::istream_iterator<int>(),
std::back_inserter(ints));
Done. If you really need to explicetely read line-wise:
#include <sstream>
#include <iostream>
#include <vector>
#include <iterator>
std::string singleline;
std::istringstream iss; // out of loop for performance
while (std::getline(cin, singleline))
{
iss.str(singleline);
std::copy(std::istream_iterator<int>(iss),
std::istream_iterator<int>(),
std::back_inserter(ints));
}
An istream_iterator<int> will repeatedly apply operator>>(int&) to the referenced stream (until the end of the stream). By default this will silently ignore whitespace, and it will throw an exception if the input operation failed (e.g. non-integer input is encountered)
The back_inserter is an output iterator that you can use with all container types (like vector) that support the .push_back operation. So in fact what is written there in STL algorithmese is similar to
std::vector<int> ints;
while (iss>>myint)
{
ints.push_back(myint);
}
In follow-up to sehe's answer, here's how you'd do it a little more verbosely (ahem).
The algorithms sehe used basically do this internally. This answer is included mostly for clarity.
#include <iostream>
#include <vector>
int main()
{
std::vector<int> myInts;
int tmp;
while (std::cin >> tmp) {
myInts.push_back(tmp);
}
// Now `myInts` is a vector containing all the integers
}
Live example.
Have a look at the man pages for strtok( ) and atoi( )
Related
I have a text file which looks like this:
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
and etc. 20 lines in total.
What I want to do is to read every digit from the text file and put them into an array of integers(one element = one digit). How can I read only one digit from this text file, not the whole line?
There are several ways to accomplish what you are looking for, in this post I'll describe three different methods. All three of them assume that you open your file using an std::ifstream ifs ("filename.txt") and that your "array" is actually a vector declared as std::vector<int> v.
At the end of this post there is also a little advice on how to speed up insertion into your vector.
I'd like to keep it simple..
The most simple approach is to read one char at a time using operator>> and then subtract '0' from the value returned.
The standard guarantee that '0' through '9' are sequential, and since a char is nothing but a numeric value printed in a different matter it can implicitly be casted to int.
char c;
while (ifs >> c)
v.push_back (c - '0');
I love the STL, and hate writing loops..
This will by many be treated as the "c++ way to do it", espacially if you are talking to STL-fanboys, though it requires a lot more code to write..
#include <algorithm>
#include <functional>
#include <iterator>
...
std::transform (
std::istream_iterator<char> (ifs),
std::istream_iterator<char> (),
std::back_inserter (v),
std::bind2nd (std::minus<int> (), '0')
);
I don't want to write loops, but why not use a lambda? c++11
#include <algorithm>
#include <functional>
#include <iterator>
...
std::transform (
std::istream_iterator<char> (iss),
std::istream_iterator<char> (),
std::back_inserter (v),
[](char c){return c - '0';}
);
Will my std::vector reallocate storage upon each insertion?
Yes, probably. To speed things up you can reserve storage in your vector before you start doing any insertions, as in the below.
ifs.seekg (0, std::ios::end); // seek to the end of your file
v.reserve (ifs.tellg () ); // ifs.tellg () -> number of bytes in it
ifs.seekg (0, std::ios::beg); // seek back to the beginning
char digit;
std::ifstream file("digits.txt");
std::vector<int> digits;
// if you want the ASCII value of the digit.
1- while(file >> digit) digits.push_back(digit);
// if you want the numeric value of the digit.
2- while(file >> digit) digits.push_back(digit - '0');
My task is that I don't know number of words in a file and the words are repeating several times,but how many times - It's unknown and I have to find that words. I use classes and vector to work with words,and fstream to work with files. But I cannot find resource or algorithm of finding repeating words and I'm so puzzled. I have vector of variable type and I pushed the words in it. It works successfully,I test it with v.size() output. I made all of things except algorithm of finding repeating words,which solve turned difficult to me.
My full code that I wrote:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <iterator>
using namespace std;
class Wording {
private:
string word;
vector <string> v;
public:
Wording(string Alternateword, vector <string> Alternatev) {
v = Alternatev;
word = Alternateword;
}
};
int main() {
ifstream ifs("words.txt");
ofstream ofs("wordresults.txt");
string word;
vector <string> v;
Wording obj(word,v);
while(ifs >> word) v.push_back(word);
for(int i=0; i<v.size(); i++) {
//waiting for algorithm
//ofs << v[i] << endl;
}
return 0;
}
Try using a hash map. If you are using gnu c++, it's std::hash_map. In C++11, you could use std::unordered_map, which would give you the same capabilities. Otherwise, hash_map is available from Boost, and probably elsewhere.
Key concept here is hash_map<word, count>.
Is the unique words in input file what you want? If so then you can do this with set (unordered_set if you don't really need them to be sorted) like so:
std::set<std::string> words; //can be changed to unordered_set
std::copy(ifs, std::ifstream(), std::inserter(words, words.begin());
std::copy(words.begin(), words.end(), ostream_iterator<std::string>(ofs));
You can also use vector, but you'll have to sort it and then use unique on it.
I can't compile this code now, so there might be some errors in my code snippet.
If what you want is the number of occurrences of a different words in file then you'll have to use some kind of map, as was already suggested. Of course using vector, sorting it and then counting consecutive words is also an solution, but wouldn't be too clear.
I already asked, how I can parse single words from a stream into variables, and that works perfectly, but I don't know how many words the user will give as input. I thought I could parse it into a dynamic array, but I don't know where to start. How can I write "for each word in line"?
This is how I parse the words into the vars:
string line;
getline( cin, line );
istringstream parse( line );
string first, second, third;
parse >> first >> second >> third;
Thanks!
EDIT: Thanks to all of you, I think I get it know... and it works!
You could use std::vector<std::string> or std::list<std::string> -- they handle the resizing automatically.
istringstream parse( line );
vector<string> v;
string data;
while (parse >> data) {
v.push_back(data);
}
A possibility would be to use std::vector with istream_iterator:
#include <iostream>
#include <sstream>
#include <vector>
#include <iterator>
#include <algorithm>
int main()
{
std::istringstream in(std::string("a line from file"));
std::vector<std::string> words;
std::copy(std::istream_iterator<std::string>(in),
std::istream_iterator<std::string>(),
std::back_inserter(words));
return 0;
}
The vector will grow as required to store whatever number of words is provided by the user.
You can write as follows:
string line;
getline( cin, line );
istringstream parse( line );
string word;
while (parse >> word)
// do something with word
Since you tagged the question with foreach, here's a way to do it with with standard for_each algorithm and C++11 lambdas:
#include <string>
#include <sstream>
#include <iostream>
#include <algorithm> // for for_each
#include <vector> // vector, obviously
#include <iterator> // istream_iterator
using namespace std;
int main()
{
string line;
vector<string> vec;
getline(cin, line);
istringstream parse(line);
for_each(
istream_iterator<string>(parse),
istream_iterator<string>(),
// third argument to for_each is a lambda function
[](const string& str) {
// do whatever you want with/to the string
vec.push_back(str); // push it to the vector
}
);
}
A vector is exactly what you asked for - a dynamically resizable array that you should almost always prefer over C-style arrays. It's size need not to be known at compile time.
I'm trying to read multiple integers from a single input line into an array
eg. Input: 100 200 300 400, so the array is: a[0] = 100, a[1] = 200, a[2] = 300, a[3] = 400
The thing is, the number of integers are unknown, so the size of the array is unknown.
You should use a container that automatically resizes itself, such as std::vector.
For example, something like this:
#include <string>
#include <iostream>
#include <sstream>
#include <utility>
#include <iterator>
std::string line;
getline(instream, line);
std::istringstream this_line(line);
std::istream_iterator<int> begin(this_line), end;
std::vector<int> values(begin, end);
You could use std::vector for this:
std::vector<int> myVector;
std::string line;
std::getline(std::cin, line);
std::istringstream os(line);
int i;
while(os >> i)
myVector.push_back(i);
This code requires following includes: <iostream>, <string>, <sstream> and <vector>.
Inserters and stream iterators can do this nicely:
#include <iterator>
#include <vector>
#include <iostream>
#include <algorithm>
std::vector<int> numbers;
std::copy(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
std::back_inserter(numbers));
Or, as #Ben Voigt has it, construct the vector from the input in one go (if that's an option):
std::vector numbers(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>());
You can replace std::cin by a suitable string stream if your input requirements are more complex.
I have a vector string filled with some file extensions as follows:
vector<string> vExt;
vExt.push_back("*.JPG;*.TGA;*.TIF");
vExt.push_back("*.PNG;*.RAW");
vExt.push_back("*.BMP;*.HDF");
vExt.push_back("*.GIF");
vExt.push_back("*.JPG");
vExt.push_back("*.BMP");
I now want to get a string of union set from the above-mentioned vector string, in which each file extension must be unique in the resulting string. As for my given example, the resulting string should take the form of "*.JPG;*.TGA;*.TIF;*.PNG;*.RAW;*.BMP;*.HDF;*.GIF".
I know that std::unique can remove consecutive duplicates in range. It con't work with my condition. Would you please show me how to do that? Thank you!
See it live here: http://ideone.com/0fmy0 (FIXED)
#include <iostream>
#include <sstream>
#include <iterator>
#include <algorithm>
#include <vector>
#include <set>
int main()
{
std::vector<std::string> vExt;
vExt.push_back("*.JPG;*.TGA;*.TIF");
vExt.push_back("*.PNG;*.RAW");
vExt.push_back("*.BMP;*.HDF");
vExt.push_back("*.GIF");
vExt.push_back("*.JPG");
vExt.push_back("*.BMP");
std::stringstream ss;
std::copy(vExt.begin(), vExt.end(),
std::ostream_iterator<std::string>(ss, ";"));
std::string element;
std::set<std::string> unique;
while (std::getline(ss, element, ';'))
unique.insert(unique.end(), element);
std::stringstream oss;
std::copy(unique.begin(), unique.end(),
std::ostream_iterator<std::string>(oss, ";"));
std::cout << oss.str() << std::endl;
return 0;
}
output:
*.BMP;*.GIF;*.HDF;*.JPG;*.PNG;*.RAW;*.TGA;*.TIF;
I'd tokenize each string into constituent parts (using semicolon as the separator), and stick the resulting tokens into a set. The resultant contents of that set is what you're looking for.
You need to parse the strings that contain multiple file extensions and then push them into the vector. After that std::unique will do what you want. Have a look at the Boost.Tokenizer class, that should make this trivial.