I am trying to read integers from a file to an array, but when I try to read the elements of said array, I get numbers that have little to nothing to do with the numbers in the file.
#include <fstream>
#include <istream>
#include <iterator>
#include <string>
using namespace std;
//Main Function
int main()
{
//Declare variables and ask user for file names
string f1, f2;
int s1, s2, n = 0;
cout<<"Please enter the names of the files you would like to merge, file extensions included."<<endl;
cout<<"File 1 Name: ";
cin>>f1;
cout<<"File 2 Name: ";
cin>>f2;
//Opening files
ifstream fs1, fs2;
fs1.open(f1);
fs2.open(f2);
//Checking if both files exist
if (fs1 && fs2)
{
//Getting length of files
s1 = distance(istream_iterator<int>(fs1), istream_iterator<int>());
s2 = distance(istream_iterator<int>(fs2), istream_iterator<int>());
//Declaring arrays and writing values to them
int a1[s1], a2[s2];
while(!fs1.eof())
{
fs2 >> a2[n];
n++;
}
//Closing files
fs1.close();
fs2.close();
//Reading array
for (int i=0; i<s2; i++)
{
cout<<a2[i]<<endl;
}
}
//If the requested files do not exist
else
{
cout<<"No file exists with that name."<<endl;
}
}
I have two text files, file1.txt and file2.txt. The code opens the files, determines the number of integers within, and creates an array with the number of integers.
file1.txt: 45 69 87 3 9 32 11 9 6 66
file2.txt: 4
The output I get when reading the array for file1.txt (a1[]) gives very unexpected numbers:
File 1 Name: file1.txt
File 2 Name: file2.txt
0
0
1878276352
6421656
4
6422016
3756032
48
16
4199922
As you can see, this is not the output I expected. file2.txt only consists of the number 4, and its ouput was simply 16
I am somewhat new to c++ and programming in general, so you might have to bear with me. Does anybody see what I've done wrong?
I am using Code::Blocks and gcc is my compiler. Thank you for your time.
Tested, using std:
std::vector<int> read_file(std::string filename) {
int n;
std::vector<int> vector;
std::ifstream file;
file.open(filename);
if (file.is_open()) {
std::string line;
while (std::getline(file, line)) {
std::istringstream is(line);
while (is >> n) {
vector.push_back(n);
}
}
file.close();
}
return vector;
}
int main() {
std::vector<int> vector = read_file("file1.txt");
for (auto element: vector) {
std::cout << element << std::endl;
}
}
Note: int a1[s1], a2[s2]; doesn't comply with the ISO C++ standard. For details, see Why aren't variable-length arrays part of the C++ standard? If you cannot know the length of an array prior to runtime, consider using std::vector.
It is as #user4581301 says, you need to rewind the files, since std::distance() will read the files to the end.
Otherwise you will already be at the end of the files, and you won't read any data into your arrays, which means your arrays will be holding uninitialized memory.
Here is a solution:
// Rewind the files
fs1.clear();
fs2.clear();
fs1.seekg(0);
fs2.seekg(0);
// Read into array 1
for (n = 0; fs1 >> a1[n]; ++n) {}
// Read into array 2
for (n = 0; fs2 >> a2[n]; ++n) {}
seekg() sets the position in the stream to the given offset. seekg(0) resets to the beginning of the stream.
clear() clears the stream's internal error state flags, including the eofbit.
Related
I have a .txt file that contains in which the content of an array is written. But if the program closes, the array's content is of course deleted, because of which I need to read the .txt file to "remind" the array of its previous content.
That's my code:
#include <fstream>
unsigned short int highscores[11]{0};
int main()
{
highscores[0] = score;
std::sort(highscores, highscores + 11);
std::ofstream outputFile("scores.txt", std::ios::trunc);
for (short int i = 10; i > 0; i--) {
outputFile << highscores[i] << std::endl;
}
outputFile.close();
}
and that's my scores.txt file:
22
15
13
10
5
5
3
1
1
1
Any recommendations to this code are also welcome!
You are only writing in a file and not reading. If you close your program and start it again your array will be empty like you said. So if you want to read the files from the file you have written in you have to use
std::ifstream inputFile("scores.txt",std::ios::in);
Then there are many ways how to read the file.
One would be to declare a string:
std::string line;
then using a while loop and getline.
usigned short int highscores[11]{0};
int i=0;
while(getline(inputFile,line)
{
highscores[i]=stoi(line);
// stoi means string to int. We use that because line is a string but we need the numbers
}
I have two text files like these:
11.txt:
1 5.66
2 4.95
3 2.55
4 0.99
5 2.87
NB.txt:
1 2 3 4 5
4 5 3 2 1
3 4 5 1 2
I have written the below code to fine, for example, "1" from File 1, and search it in File 2, then substitute "1" with "5.66". and repeat it for other numbers, i.e. 2,3,4,5. but I don't know why it doesn't work. additionally, it doesn't read the first line of 11.txt.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
string line;
double AtomId, Atom_radius,search ;
ifstream AtomId_file ("11.txt");
string namefile;
if (AtomId_file.is_open()){
for (int linenox = 0; getline (AtomId_file,line) && linenox < 6; linenox++){
if (linenox == 0) AtomId_file>>AtomId>>Atom_radius;
}
cout<<"AtomId: "<<AtomId<<" Atom_radius: "<<Atom_radius<<endl;
cout<<namefile<<"\n";
}
ifstream NB("NB.txt");
size_t pos;
if (NB.is_open())
{
search = AtomId;
getline(NB,line);
pos=line.find(search);
if(pos!=string::npos)
{
search = Atom_radius;
cout <<"Found!";
}
}
ofstream myfile;
myfile.open ("12.txt");
myfile << search << "\n";
}
the output in 12.txt is:
2
instead of :
5.66 4.95 2.55 0.99 2.87
0.99 2.87 2.55 4.95 5.66
2.55 0.99 2.87 5.66 4.95
I understand that your are new to C++.
I analyzed your code and put in tons of comments, where the errors are. You need to change your design. Before starting to type in code, you must first write down, what should be done. Then, and this is most important, you think (without taking any language into consideration) how you can solve the problem. This is most important. Also for you later programming career. The design is most important. So think 3 hours, how it could be done. Search possible design solutions in the internet. Write it on a piece of paper or somewhere.
Then, after hours of thinking, select an apropriate language and check, how it could be implemented.
I show a standard C++ solution below. You will not understand it immediately. So please try to understand the design first. Then lookup all used C++-statements in the internet and try to understand.
Read some good C++ books, before starting to code.
Please see first your commented code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std; // You should not use this line at all. Use qualified names.
int main()
{
string line;
double AtomId, Atom_radius, search; // These variables are not initalized
ifstream AtomId_file("r:\\11.txt");
string namefile;
if (AtomId_file.is_open()) { // You should not use is_open but simply if (AtomId_file)
// Here you have a loop running from 0,1,2,3,4,5. That are 6 loops. But you have only 5 lines in your sourcefile
// The you read one line, each time the loops runs. So in the beginning, this will read the first line
for (int linenox = 0; getline(AtomId_file, line) && linenox < 6; linenox++) {
// And only for the first loop event, when linenox==0, you read then next line "2 4.95"
// So you read already lines. But not more.
// ypu need to read line by line (only one per loop) and then store the result in an appropriate STL Container
if (linenox == 0) AtomId_file >> AtomId >> Atom_radius;
}
// Since you assigned the data only once, the values will be 2, 4.95
// They will never change
cout << "AtomId: " << AtomId << " Atom_radius: " << Atom_radius << endl;
// The variable namefile has never been initailized and is always emtpy, So ""
cout << namefile << "\n";
}
ifstream NB("r:\\NB.txt");
size_t pos; // Not initialized
if (NB.is_open()) // Not recommended. Use "if (NB) instead". In general, use more meaningful variable names
{
search = AtomId; // search is now 2 and never somthing else
getline(NB, line); // Read exactly one (and only this one time) a line containing 1, 5.66
pos = line.find(search); // So, 2 will never be found
if (pos != string::npos) // Always false, can never be true
{
search = Atom_radius; // Will never be executed
cout << "Found!"; // Will never be executed
}
}
ofstream myfile; // You can write directly ofstream myfile("12.txt");
myfile.open("12.txt");
myfile << search << "\n"; // And the output will always be 2.
}
And here is a correct and working example:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <unordered_map>
#include <vector>
#include <iterator>
int main() {
// Open the file 11.txt and check, if it could be opened
if (std::ifstream file11("11.txt"); file11) {
// Define variable id and attribute and initialize them to theire default values.
unsigned int id{};
double attribute{};
// Here we will store all values (id, attribute) of all lines that we read in the follwing loop
std::unordered_map<unsigned, double> replacement{};
// Read in a llop ALL lines and extract id and attribute, and, check if this worked
while (file11 >> id >> attribute) {
// Create a new replacement value for id
replacement[id] = attribute;
}
// So, now, all data from file 11.txt is read and stored.
// We will now read the next file and store the data
// Open next input file NB.txt and check, if that worked
if (std::ifstream fileNB("NB.txt"); fileNB) {
// And already now, open output file 12.txt and check, if open worked
if (std::ofstream myfile("12.txt"); myfile) {
// Read a complete line and check, if that worked. Read all lines in a loop
for (std::string line; std::getline(fileNB, line); ) {
// Put the line in a std::istringstream, so that we can extract each single value
std::istringstream iss(line);
// We will store the single values of the just read line into a vector
// This we do, because we do not know, how many values will be in that line
// We use a so called iterator, to iterate over all elements in the just read line
// The result will be stored in a vector
// The istream_iterator will call the ">>"-operator, until the line is empty
// For the vector, we use its range constructor
std::vector values(std::istream_iterator<unsigned>(iss), {});
// Now go through all values, replace them and out the result into the output file
for (const unsigned& u : values) myfile << replacement[u] << " ";
myfile << "\n";
}
}
}
}
return 0;
}
Of course there are many other possible solutions
So I have two simple questions. One is my function okay for reading a text file composed of one number on each line and passing it an array inside main()? And is the text file opening/closing properly or do I not understand the code?
And secondly, I can't seem to fill my array correctly. There's 92 numbers/lines, but I can only seem to get 91 elements. It seems to skip the first number, but I'm not sure why. When I'm debugging I can see "number" reading the the first line, but I don't know where it goes.
The text file is 92 numbers with decimals, with a number in each line like this..and the first number is in the first line, no space above and no vertical space between the numbers.
31.11
25.22
...
int getTempData(double temperatures[]) {
ifstream input("pgm6.txt");
if (!input)
return 1; // closes input file
string number;
while (input >> number)
for (int i = 0; i < 91; i++)
{
input >> temperatures[i];
}
}
and inside main()
const int ARRAY_SIZE = 91;
double temperatures[ARRAY_SIZE];
getTempData(temperatures);
Edit: Thanks so much for the help everyone. I learned my lesson in not using code I don't quite understand from here: https://www.reddit.com/r/learnprogramming/comments/2wwv6i/c_creating_writing_to_and_displaying_text_files/
#include <fstream> // Instead of <iostream>
#include <string>
using namespace std; // Nothing too much wrong with this...
int main() {
ifstream input("input.txt"); // Open the file "input.txt" for reading
(if = input file)
if ( !input ) // Did the file open correctly?
return 1;
ifstream output("output.txt"); // Open the file "output.txt" for writing
(of = output file)
if ( !output ) // Did the file open correctly?
return 1; // C++ automatically closes the input file!
string word;
**while ( input >> word )** // Read a word while the file isn't at its
end
output << word << '\n'; // Write the word on its own line
// C++ automatically closes the output file
// C++ automatically closes the input file
}
What you are trying to achieve seems to boil down to this:
#include <fstream>
int getTempData(double temperatures[]) {
std::ifstream input("pgm6.txt");
int i;
for (i = 0; i < 92 && input >> temperatures[i]; i++) {
// deliberate empty line
}
// input will close file on exiting function
return i; // returns number of elements found
}
int main() {
const int ARRAY_SIZE = 92;
double temperatures[ARRAY_SIZE];
getTempData(temperatures);
}
while (input >> number)
This reads the first number and throws it away. Simply remove this line of code.
Also, you should probably add error checking to input >> temperatures[i];. And your function needs to return something if all is well -- currently there is no return statement at the end. Also, your loop only collects 91 elements.
I have a .txt file that has a sequence of numbers and spaces on the first line that I wish to read into a vector. Then there is a '$' symbol on the next line. On the line after that is another line containing a sequence of numbers and spaces (like the first) that I'd like to read into another vector. For example
1 2 3 4 5
$
4 3 2 1 6
I've tried everything but can't keep reading after the initial while loop reads in integers. How do I move past the second line and read the third? Right now It just outputs the first line. Currently, this is my code:
int main(int argc, const char * argv[]) {
ifstream file(argv[1]);
if (file.is_open() && file.good()){
int addMe;
vector<int> addMeList;
while(file>>addMe){
cout <<addMe<<endl;
addMeList.push_back(addMe);
}
string skip;
while(file >> skip)
cout << skip << endl;
int searchQuery;
vector<int> searchQueries;
while(file>>searchQuery){
searchQueries.push_back(searchQuery);
}
for (int i=0; i<searchQueries.size();i++)
{
cout << searchQueries[i]<<endl;
}
}
return 0;
}
Two problems:
The first loop will cause the streams failbit to be set (when it attempts to read the '$' from the second line). If that bit is set, you can't read more from the stream. You need
to clear the stream state.
Once you've done the above, the second loop will read the rest of the file.
One possible solution is to read lines instead. Use e.g. std::getline to read a line. Put the line into a std::istringstream, and read the values from that.
The program logic seems to be flawed. Using the first while loop you read the entire file word-by-word till the very end (not till the end of line), after that trying to read again fails, which is evaluated as false, thus it never even gets into the other loops. Instead, consider reading line by line using getline and then breaking it into ints using istringstream.
Here's how I'd improve it:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <sstream> // include this header to use istringstream
using namespace std;
int main() {
ifstream file("text.txt"); // my test file; Replace with yours
if (file.is_open() && file.good()) {
string lineIn; // general line to read into
int i; // general int to read into
vector<int> addMeList;
// int addMe; // not needed anymore
getline(file, lineIn); // read a line 1
istringstream istr(lineIn); // string stream we can use to read integers from
while (istr >> i) {
cout << i << endl;
addMeList.push_back(i);
}
// string skip; // not needed anymore
getline(file, lineIn); // skips line 2
// int searchQuery; // not needed anymore
vector<int> searchQueries;
getline(file, lineIn); // read a line 2
istringstream istr2(lineIn); // string stream we can use to read integers from
while (istr2 >> i) {
searchQueries.push_back(i);
}
for (int i = 0; i < searchQueries.size(); i++)
{
cout << searchQueries[i] << endl;
}
}
return 0;
}
Input file:
1 2 3 4 5
$
4 3 2 1 6
Output:
1
2
3
4
5
4
3
2
1
6
I need to read some files containing a lot of numbers (int). Lines of every file are different.
1
3
5
2
1
3
2
I have to read one of those files and create an array of int dynamically.
I'm going to read the file twice because I'm not able to know the length of the file.
Do you know another way ?
This is what I did:
int main()
{
int *array;
int tmp, count;
ifstream fin("inputfile");
while(fin >> tmp)
count++;
array = new int[count];
fin.close();
fin.open("inputfile");
int i=0;
while(fin >> tmp)
array[i++]=tmp;
delete[] array;
return 0;
}
Thanks for your help.
Use a std::vector rather that a raw array.
That way you can add to the vector as you read each item, rather than having to read the file once in order to work out how many items are in the file and then again to populate the array.
int main()
{
std::vector<int> data;
int tmp;
ifstream fin("inputfile");
while(fin >> tmp)
{
data.push_back(tmp)
}
return 0;
}
Here is an idiomatic way of reading numbers from a file into an std::vector<int>:
#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
int main()
{
std::ifstream is("inputfile");
std::istream_iterator<int> start(is), end;
std::vector<int> numbers(start, end);
std::cout << "Read " << numbers.size() << " numbers" << std::endl;
}
if there are same numbers of int in a line for all files, you can get the count of line of the file by calculating the size of it, and then the lines of this file is equal to size(file)/(n*sizeof(int)), n is the number of int for every line. I think you can try instead of read the file twice.
If you don't want use std::vector, you can add a count for in the while loop, if it reaches the up limit of the array, realloc another buffer with size*2 and copy the data to it, then start read the file again.
vector use the same logic.