Perform calculation seperately on values from file in C++ [duplicate] - c++

This question already has answers here:
Read file line by line using ifstream in C++
(8 answers)
Closed 3 years ago.
So I have a input file which contains several different integer values(each in a seperate line), now I need to read each value, find the square root and get the output. The issue I am having is that my code only reads the first value from the input file. I have a feeling I am supposed to be using a loop to read each value seperately, so if someone can help me out it would be really appreciated.
float file_inp() //reads values from file and calculates the square root
{
float y = 0;
ifstream fin;
fin.open("input.txt",ios::in);
if (fin)
{
int x = 0;
fin >> x;
y=sqrt(x);
}
return y;
}
int main()
{
float y = 0;
cout << file_inp();
system("Pause");
return 0;
}

The main problem is that you have a function that reads the file and returns one number.
No amount of looping can make that function produce more than one number.
Instead of one function that does all the work, it's often better to have functions that do a little bit of work and use them over and over.
It's also a good idea to separate I/O from data processing.
This the common "elementwise processing of whitespace-separated input" loop:
int main()
{
std::ifstream input("input.txt"); // No 'ios::in'; it's already an input stream.
SomeType piece;
while (input >> piece) // Read until you can't read no more.
{
process(piece); // Do whatever you want to do.
}
}
Adjust types and processing as necessary.
In your case,
int main()
{
std::ifstream input("input.txt");
int x;
while (input >> x)
{
std::cout << std::sqrt(x) << std::endl;
}
}

Related

Looping through strings in c++

I have text file which has n words. I am trying to read it and print using c++. But, I am able to print only last string. Please help me
int main()
{
ifstream inFile;
inFile.open("test.txt");
if (inFile.fail()) {
cerr << "Error opening file" << endl;
exit(1);
}
string x;
string a[100];
int count = 0, i = 0;
while (!inFile.eof()) {
inFile >> x;
a[i] = x;
count++;
}
for (i = 0; i < 100; i++) {
cout << a[i];
}
return 0;
}
You did not increment the i variable in your while loop, therefore assigning and overwriting always the first element:
int main() {
ifstream inFile;
inFile.open("test.txt");
if(inFile.fail()) {
cerr << "Error opening file"<< endl ;
exit(1);
}
string x;
string a[100];
int count=0,i=0;
while( !inFile.eof()) {
inFile >> x;
a[i]=x;
i++; // i think you meant i++ not count++
}
for (i=0;i<100;i++){
cout<< a[i];
}
return 0;
}
Your bug is that you forgot to increment i in the loop:
while (!inFile.eof()) {
inFile >> x;
a[i] = x;
// You don't increment the `i`
// That is why you only see the last word.
count++;
}
But that is not enough there is another bug that was previously hidden.
while (!inFile.eof()) { // The last read read up to but not past the eof
// So the eof() is still false but there are no
// words left in the file.
inFile >> x; // So this read will fail
a[i++] = x; // Even though your read failed you still
// Add it to the array.
count++;
}
Let us fix this bug by testing to see if the read worked.
while (!inFile.eof()) {
if (inFile >> x) {
a[i++] = x;
count++;
}
}
Here you can see we test the state of the stream after the read. But this puts all the meaningful code inside the if branch. Why not just push this out one level.
while (inFile >> x) {
a[i++] = x;
count++;
}
Here we read a word from the file. If it works enter the loop, otherwise don't.
That should fix all the bugs for small files, but it is worth going through the rest of the file to look for bad practice and improvements.
// You don't show your headers.
// You should include them.
// Also through the code you don't use `std::` objects with the prefix. This means
// your code contains a `using namespace std;` I know all the books use this
// but it is considered exceedingly bad practice in real code. You should
// avoid it (even for small programs as the habit may cause you to use it
// large programs).
int main()
{
// Not sure why you want to take two lines here?
// There is a constructor that takes a file name.
ifstream inFile;
inFile.open("test.txt");
// The stream object when used by itself in a boolean context
// (i.e. when used in an if expression like here. Will convert itself
// to bool checking the current state. So you don't need to explicitly
// call the `fail()` method.
if (inFile.fail()) {
// It's not going to make much difference here.
// But in general you should prefer to use '\n' unless you
// absolutely must force a flush of the stream (which generally is no
// as the stream will flush itself at the most appropriate time). In
// this case it is also useless as `cerr` is unbuffered and `exit()`
// would force a flush of any other buffers.
cerr << "Error opening file" << endl;
exit(1);
}
string x;
// You only ever have 100 words in the input file?
// Arrays are not resizable and force the initialization of all members.
// So this will either be too little space and you will overflow (or need
// to add specific code to check for overflow and prevent it) or it is
// way too much space and you have needlessly constructed all those objects.
//
// For dynamic array like storage prefer std::vector
string a[100];
// Come on. Every coding standard in the world says one variable per line.
// A lot of people are fine with short variables like `i` but I prefer
// to use meaningful names for all variables. Especially if the code
// may grow in the future.
int count = 0, i = 0;
// This `while (!inFile.eof())` is WRONG and an anti-pattern.
//
// Testing for `eof` here will find the EOF after the you
// have read the last word from the file. Remember the last
// read will read up to but not past the eof. So when your read
// in the loop reads the last word `eof()` is still false.
// So now you will re-enter the loop and try and read past the
// end and the read will fail. Since the read fails `x` is
// unchanged and the last word will be added to `a` twice.
//
// The correct way to do this is to read in the while condition.
// while(inFile >> x) {
//
// This will read a word from the file and return the stream to
// be used in a bool context (which will be true if you read a
// word correctly from the stream). So what this does is try
// and read a word if it works enter the loop if it fails (i.e.
// you reach the end of the file) the loop will not be entered
// as the stream object returned is in a bad state with eof set
while (!inFile.eof()) {
inFile >> x; // read a string
a[i] = x; // Copy the string
// You can do this in a single line
// inFile >> a[i]
// You don't increment the `i`
// That is why you only see the last word.
// Whats the difference between `count` and `i`?
count++;
}
// That was a nice loop but with a vector you can read the whole
// file into the vector in a single line.
// std::vector<std::string> a(std::istream_iterator<std::string>(inFile),
// std::istream_iterator<std::string>());
// Here `i` is normal and OK (single line loop variable).
for (i = 0; i < 100; i++) {
cout << a[i]; // No space between words?
}
// But you can declare it as part of the for loop and prevent it leaking
// into the scope of the rest of your code.
// for(int i = 0; i < count; ++i) {
//
// Note 1: declare and initialize.
// Note 2: the number of words read is not 100 but count.
// Note 3: Prefer the prefix increment ++i
// It makes no difference here. But when using some objects it
// can. A lot of C++ code is changed simply by changing the type
// of the variables. So if you use the most efficient version of
// the code in all contexts then it will remain the most
// efficient even after maintenance.
//
// In C++ we usually loop over containers using begin() and end()
// to get iterators. This make sit easy to convert to standard
// algorithms if we need to. This is easier when you use a container
// rather than an array as they maintain an accurate end. But it can
// be done with arrays.
// for(auto loop = std::begin(a); loop != std::end(a); ++loop) {
//
// Also note that in modern C++ you can use `range based for`.
// So it will find the begin and end of the array for you.
// for(auto const& obj: a) {
//
// More useful for std::vector than an array but worth mentioning.
// It allows things like the trick I do with creating the vector
// directly from the file as the vector can be constructed using
// iterators and the iterator library has input iterators that
// work on streams.
// Not required in main()
// If your application can not fail then prefer to not return
// anything.
return 0;
}
I would write it like this:
#include <string>
#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::ifstream inFile("test.txt");
if (!inFile) {
std::cerr << "Error opening file" << "\n";
exit(1);
}
std::vector<std::string> data(std::istream_iterator<std::string>(inFile),
std::istream_iterator<std::string>());
for(auto const& word: data) {
std::cout << word << "\n";
}
}
You need to increment i, as per RoQuOTriX's answer, but you probably also want to increment count so you know how many words you have. Also you should avoid over filling your array/
Try this:
int main() {
ifstream inFile;
inFile.open("test.txt");
if(inFile.fail()) {
cerr << "Error opening file"<< endl ;
exit(1);
}
string x;
string a[100];
int count=0,i=0;
while( (!inFile.eof()) && (count<100)) // avoid array overrun!
inFile >> x;
a[i]=x;
i++; // i think you meant i++ not count++ (as per RoQuOTriX)
count++; // as per your original answer
}
for (i=0;i<count;i++){ // only show values you actually read!
cout<< a[i];
}
return 0;
}
On this line:
a[i] = x;
You use i but it's never incremented. Instead do:
a[i++] = x;
You don't require to implement everything again. This is already implemented in C++ directory
#include <iostream>
#include <fstream>
int main()
{
std::ifstream f("file.txt");
if (f.is_open())
std::cout << f.rdbuf();
}
Hope this works!!
Another part that would require attention is your while loop.
while( !inFile.eof() ) {
inFile >> x; (2)
a[i]=x;
i++;
}
In this way, the last string of your input file will be written twice. This is because your check happens before you grab the last x (2).
What you need to do is,
while( inFile >> x ) {
a[i++] = x;
count ++;
}
Lastly, what happens if there are more than 100 variables in the input file? Do you ignore them or have you thought of a way to deal with that? In the code you give, you will just get a segmentation fault.

Unable to have function properly populate array from text file, seems to skip first line/be one off

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.

How to store specific integers from a .txt file in an array of structures?

There are numbers ranging from 1-4 in a file called "data.txt" (ex. 2 1 2 4 1 3...). I need to read these numbers and create strings of 100 numbers each. After which I need to count how many 1s, 2s 3s, and 4s there are in each string. This is what I have so far:
//structure
struct DNAnt
{
int a, c, g, t;
string strand;
};
void data2DNA();
//main
int _tmain(int argc, _TCHAR* argv[])
{
data2DNA();
cin.get();
return 0;
}
//function
void data2DNA()
{
DNAnt DNAstrand[100];
ifstream inFile;
int numbers;
inFile.open("data.txt");
if(inFile.is_open())
{
while(!inFile.eof())
{
inFile >> numbers;
}
}
else
cout << "ERROR!";
inFile.close();
}
All this program does at the moment is read all the data from the file. I don't know how to continue from here.
Very often in C++ you need to use a loop to repeat an action some number of times. In your case I believe you could benefit from a for loop. Here is an example of a loop that will read 100 integers and store each one to a location in the array that you have near the start of your main:
int i;
for(i = 0; inFile && i < 100; ++i) { //i will range from 0 to 99
inFile >> DNAstrand[i];
}
//now use DNAstrand to do stuff
The reason I say inFile && is to make sure that inFile is not at eof.
Start with a very simple program that reads numbers from a file.
Just read them. Do not interpret them because there is no point to trying to do anything with these numbers until you can prove that they are being read correctly. All additional code will do is muddy the waters of ensuring you are reading correctly and hide the location of bugs from you.
vector<int> readFile()
{
vector<int> numbers;
Why vector? Because it is the easiest way to store an unknown number of entries. Don't play around with more complicated structures at this point and don't try to roll your own. If the instructor says, "No vector" oh well. But that's for what you hand in. What you use to prove the algorithm works is another story.
ifstream inFile("data.txt");
This also opens the file so you don't have to do it later
if(inFile.is_open())
{
int number;
while(inFile >> number)
This reads into an int. If it can't read an int for any reason, it stops and leaves the loop. If the file is poorly formatted and contains data that cannot be converted, we're outta here. If it hits the end of the file, we're outta here.
{
numbers.push_pack(number);
Otherwise, we put the number we read into the vector.
}
}
else
{
cout << "ERROR opening file";
)
Don't need to close the file. When we hit the end of the function inFiles destructor will fire and do it for us.
return numbers;
And send the vector back to the caller so they can use it however they see fit. There is a whole tot of interesting stuff that can happen here to keep the vector from being copied as it is returned, so don't worry about it.
}
All together:
void data2DNA()
{
vector<int> numbers;
ifstream inFile("data.txt");
if(inFile.is_open())
{
int number;
while(inFile >> number)
{
numbers.push_pack(number);
}
}
else
{
cout << "ERROR opening file";
)
return numbers;
}
Now that you have the data in, you can get on with the real job of turning it into a string of nucleic acids.
For this part I'm going to recommend an array
const char tags[] = {'-', 'A', 'C', 'G', 'T'};
Indexes 1 though 4 are A, C, G, and T, so tags[2] will provide 'C'. This makes translating from number to tag really, really easy.
Once you have a tag, you can append it to the DNA string.

C++ reading from file - last element gets read twice [duplicate]

This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 4 years ago.
The following C++ code uses a ifstream object to read integers from a text file (which has one number per line) until it hits EOF. Why does it read the integer on the last line twice? How to fix this?
Code:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream iFile("input.txt"); // input.txt has integers, one per line
while (!iFile.eof())
{
int x;
iFile >> x;
cerr << x << endl;
}
return 0;
}
input.txt:
10
20
30
Output:
10
20
30
30
Note: I've skipped all error checking code to keep the code snippet small. The above behaviour is seen on Windows (Visual C++), cygwin (gcc) and Linux (gcc).
Just follow closely the chain of events.
Grab 10
Grab 20
Grab 30
Grab EOF
Look at the second-to-last iteration. You grabbed 30, then carried on to check for EOF. You haven't reached EOF because the EOF mark hasn't been read yet ("binarically" speaking, its conceptual location is just after the 30 line). Therefore you carry on to the next iteration. x is still 30 from previous iteration. Now you read from the stream and you get EOF. x remains 30 and the ios::eofbit is raised. You output to stderr x (which is 30, just like in the previous iteration). Next you check for EOF in the loop condition, and this time you're out of the loop.
Try this:
while (true) {
int x;
iFile >> x;
if( iFile.eof() ) break;
cerr << x << endl;
}
By the way, there is another bug in your code. Did you ever try to run it on an empty file? The behaviour you get is for the exact same reason.
I like this example, which for now, leaves out the check which you could add inside the while block:
ifstream iFile("input.txt"); // input.txt has integers, one per line
int x;
while (iFile >> x)
{
cerr << x << endl;
}
Not sure how safe it is...
There's an alternative approach to this:
#include <iterator>
#include <algorithm>
// ...
copy(istream_iterator<int>(iFile), istream_iterator<int>(),
ostream_iterator<int>(cerr, "\n"));
Without to much modifications of the original code, it could become :
while (!iFile.eof())
{
int x;
iFile >> x;
if (!iFile.eof()) break;
cerr << x << endl;
}
but I prefer the two other solutions above in general.
The EOF pattern needs a prime read to 'bootstrap' the EOF checking process. Consider the empty file will not initially have its EOF set until the first read. The prime read will catch the EOF in this instance and properly skip the loop completely.
What you need to remember here is that you don't get the EOF until the first attempt to read past the available data of the file. Reading the exact amount of data will not flag the EOF.
I should point out if the file was empty your given code would have printed since the EOF will have prevented a value from being set to x on entry into the loop.
0
So add a prime read and move the loop's read to the end:
int x;
iFile >> x; // prime read here
while (!iFile.eof()) {
cerr << x << endl;
iFile >> x;
}
At the end of the last line, you have a new line character, which is not read by >> operator and it is not an end of file.
Please, make an experiment and delete the new line (thelast character in file) - you will not get the duplication.
To have a flexible code and avoid unwanted effects just apply any solution given by other users.
int x;
ifile >> x
while (!iFile.eof())
{
cerr << x << endl;
iFile >> x;
}

How to read integer value from file in C++

How can read integer value from file? For example, these value present in a file:
5 6 7
If I open the file using fstream then how I can get integer value?
How can read that number and avoid blank space?
ifstream file;
file.open("text.txt");
int i;
while (file >> i) {
cout << i << endl;
}
ifstream f(filename);
int x, y, z;
f >> x >> y >> z;
ifstream f;
f.open("text.txt");
if (!f.is_open())
return;
std::vector<int> numbers;
int i;
while (f >> i) {
numbers.push_back(i);
}
It's really rare that anyone reads a file Byte by Byte ! ( one char has the size of one Byte).
One of the reason is that I/O operation are slowest. So do your IO once (reading or writing on/to the disk), then parse your data in memory as often and fastly as you want.
ifstream inoutfile;
inoutfile.open(filename)
std::string strFileContent;
if(inoutfile)
{
inoutfile >> strFileContent; // only one I/O
}
std::cout << strFileContent; // this is also one I/O
and if you want to parse strFileContent you can access it as an array of chars this ways: strFileContent.c_str()