The most likely cause of the failure is "Measured-Isotopes.txt"
isn't in the current working directory when you run your program leading to ifstream in("Measured-Isotopes.txt");
failing.
For any I/O operation, including file opening, you must always validate the stream state after each operation. In your case, you would want at minimum to validate the open succeeds, e.g.
if (!in.good()) {
std::cerr << "error: file open failed.\n";
return;
}
You may want to reconsider refactoring your code to provide the filename to read as the first argument to the program (that's what int main (int argc, char **argv)
are for), or prompting the user to enter a filename and read the filename as input. You should not need to recompile your code simply to read from a different filename.
Further, consider opening the file stream in the calling function (main()
here) and passing a reference to the open file stream as an argument to the function. If the file open fails, there is no need to make the function call to begin with.
Taking that approach, you could write your duplicate()
function as:
#include <iostream>
#include <fstream>
#include <vector>
/* since I/O is performed in function, providing a return type that can
* indicate success/failure is useful.
*/
bool duplicate (std::ifstream& in, std::vector<std::pair<int, int>>& vec)
{
int A, Z;
while (in >> A && in >> Z){
vec.push_back((std::make_pair(A, Z)));
}
if(vec.empty()){
return false;
}
return true;
}
(note: the return type is changed to bool
so success/failure of the read is indicated through the return)
You can then write your main()
as
int main (int argc, char **argv) {
if (argc < 2) { /* validate at least 1 argument given */
std::cerr << std::string {"error: insufficient arguments\n"
"usage: "} + argv[0] + " filename\n";
return 1;
}
std::vector<std::pair<int, int>> vec;
std::ifstream in (argv[1]); /* open file */
if (!in.good()) { /* validate open succeeds */
std::cerr << "error: file open failed.\n";
return 1;
}
if (duplicate (in, vec)) { /* pass open stream, reference to vec, validate return */
for (const auto p : vec) { /* output vec contents on success */
std::cout << p.first << ", " << p.second << '\n';
}
}
else { /* handle error on failure */
std::cout << "oops - vector empty\n";
}
}
(note: the use of '\n'
instead of std::endl
, see C++: “std::endl” vs “\n” for the differences (among other things std::endl
causes the output buffer to be flushed))
Example Use/Output
With your data in the file dat/vectpairs.txt
you would have:
./bin/vect_read_pairs dat/vectpairs.txt
10, 8
5, 6
15, 4
Look things over and let me know if you have questions.