I am attempting to write a program that reads in integers from an input file and outputs a dynamic array. This array would be the size of the input. For verification, I'd also like to print the array. The output will be passed to a function to create a sorted linked list.
I tried the following, but it did not work:
istringstream input(R"inp(
23 43 12 67
18 15 22
12 xxx 23 12 xx 34556 11 11 www
)inp");
int get, count = 0;
while (input >> get)
count++;
cout << "Number of integers: " << count << endl;
int *array = new int [count];
for (int i = 0; i < count; i++)
{
input >> array[i];
}
for (int i = 0; i < count; i++)
{
cout << *(array+i) << endl;
}
delete[] array;
Here's an online example of my code.
The problem is that the output shows some weird numbers, completely unrelated to the input:
Number of integers: 8
-1217944384
-1217944384
-1
538976266
540226080
824193844
Where did I go wrong?
As πάντα ῥεῖ pointed out, the solutions that I did provide are not totally safe, that's why I will provide a third example, using boost::spirit.
See the points fast fix and good solution, as well as πάντα ῥεῖ's answer to get it working without using boost.
my personal favourite solution: note that this example does require to have read the text file into a string.
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
template<typename Iterator>
bool
parse_numbers(Iterator first, Iterator last, std::vector<int>& v)
{
bool r =
boost::spirit::qi::parse(first, last,
// Begin grammar
(boost::spirit::qi::int_[boost::phoenix::push_back(
boost::phoenix::ref(v), _1)]
% *(boost::spirit::qi::char_("a-zA-Z")
| boost::spirit::ascii::space)));
if (first != last) // fail if we did not get a full match
return false;
return r;
}
const std::string s = "23 43 12 67 \n18 15 22\n12 xxx 23 12 xx 34556 11 11 www";
std::string::const_iterator start = s.begin(), stop = s.end();
std::vector<int> results;
parse_numbers(start, stop, results)));
for(int i : results)
std::cout << value << ' ';
the result would be, as expected:
23 43 12 67 18 15 22 12 23 12 34556 11 11
The above example is partially built on the example given in the boost::spirit documentation.
input >> get
moves the current curser position, so after your while loop you have nothing left to read.
fast fix:
ifstream input;
input.open("file.txt");
int get, count = 0;
while (input >> get)
count++;
input.close();
input.open("file.txt");
int *array = new int [count];
for (int i = 0; i < count; i++)
{
input >> array[i];
}
for (int i = 0; i < count; i++)
{
cout << *(array+i) << endl;
}
input.close();
delete[] array;
To close and reopen the stream should work, but there are more efficient solutions out there...
good solution:
One could be to read and insert into a dynamically growing vector for example. See the documentation for further reference.
std::vector<int> dataArray;
while (input >> get)
{
dataArray.insert(dataArray.end(), get);
}
for(auto&& value : dataArray)
{
std::cout << value << std::endl;
}
That would have multiple advantages: