fstream and reading every line

I'm trying to get my program to read every line of my inFile but when I try using a getline() function within my while loop it would break my algorithm. What modifications do I need to make to get it to read every lines of input?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  #include <iostream>
#include <fstream>
#include <iomanip>
#include <string>

using namespace std;

int main()
{
	ifstream inFile;
	ofstream outFile;

	int a, b, t;
	int counter = 0;
	double sum = 0;
	string file_Dir;
	int ori_a;
	int ori_b;

	cout << "Enter the file directory: " << endl;
	cin >> file_Dir;

	inFile.open(file_Dir);
	outFile.open("output.txt");

	inFile >> a >> b >> t;
	ori_a = a;
	ori_b = b;

	a = a - b;

	while (sum < t) {
		
		a = a + b;
		sum += a;
		counter++;
	}

	outFile << ori_a << " " << ori_b << " " << t << " " << counter << endl;

	inFile.close();
	outFile.close();

	system("pause");
	return 0;
}


My inFile .txt file that contains the inputs

10 5 70
5 15 85
12 9 75
10 6 60
20 10 100
15 8 95
4 3 35
20 10 200
9 5 65
Last edited on
Hello Battlefire,

I have not actually tested this yet, but I believe this is what you are looking for.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
while (inFile >> a >> b >> t)
{
	ori_a = a;
	ori_b = b;

	a = a - b;

	while (sum < t)
	{

		a = a + b;
		sum += a;
		counter++;
	}

	outFile << ori_a << " " << ori_b << " " << t << " " << counter << endl;
}

The variable name "file_Dir" is a bit misleading. The first thing I thought of is that this should be a path not a file name. Over time I settled on using "inFileName" as there is no mistake to what it is used for.

While I am on the subject give your variables a proper name. This would be a noun or sometimes a verb that describes what it is or what it does. This is much better than "a", "b" and "t" which only you know what they are for.

Next I see that you have opened a file stream for input, but how do you know it is open? I like to use this code when opening a file for input:

1
2
3
4
5
6
7
8
9
10
const std::string inFileName{ "" }; // <--- Put file name here.

std::ifstream inFile(inFileName);

if (!inFile)
{
	std::cout << "\n File " << std::quoted(inFileName) << " did not open" << std::endl;
	//std::this_thread::sleep_for(std::chrono::seconds(3));  // <--- Needs header files chrono" and "thread". This is optional as is the header files.
	return 1;  //exit(1);  // If not in "main".
}

In your case remove the "const" from the "std::string" and put lines 3 - 10 after the "cin" statement. Otherwise it may not open the file stream, but the program will continue. It just will not be able to read anything from the file.

For an output file stream this is not as necessary because if the file name does not exist it will be created. Should you have a path of where to put the output file then it is useful as the path is usually where the problem lies. It is still a good idea to check if the output stream is open and usable.

One thing I would consider adding is to print out a list of the file names available for use. You could do this with a "std::string" array or a vector. Although you would have to keep this updated. Starting with C++14 there is the header file "experimental/filesystem" which I believe will print the files in a given directory. In C++17 this left the "experimental/" directory and became part of the standard include files. As I understand it.

In a little while I will load up the program and make the changes and give it a test. If I find anything else I will let you know.

Hope that helps,

Andy
here is working code of what you were trying to achieve:
see code comments on what has been edited.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>

using namespace std;

int main()
{
	ifstream inFile;
	ofstream outFile;

	int a, b, t;
	int counter = 0;
	double sum = 0;
	string file_Dir;
	int ori_a;
	int ori_b;

	cout << "Enter the file directory: " << endl;
	cin >> file_Dir;

	inFile.open(file_Dir);
	outFile.open("output.txt");

	auto pos = (inFile >> a >> b >> t).tellg(); // save end of line position
	ori_a = a;
	ori_b = b;

	a = a - b;

	while (sum < t)
	{
		pos += 1; // increment position to next line
		inFile.seekg(pos); // go to next line
		pos = (inFile >> a >> b >> t).tellg(); // get position of next line

		a = a + b;
		sum += a;
		counter++;

		ori_a = a;
		ori_b = b;
    
                // we want this inside the loop!
		outFile << ori_a << " " << ori_b << " " << t << " " << counter << endl;
	}


	inFile.close();
	outFile.close();

	system("pause");
	return 0;
}

Last edited on
@Handy Andy, Thanks for the reply, and it seems that my code finally has outputted all the correct values but for the exception for the counter.

I'll use the these inputs from the inFile .txt as an example: 5 15 85

The algorithm should be 5 + 20 + 35 = 80. The value of b which is 15 is added to a. And after each loop, a is added to sum. The loop stops at the sum of 80 because anything more would be more than t=85. So the counter should be 3 but instead my output for that is 6.
Last edited on
@Battlefire
isn't my correction to your code do exactly what you are asking for?
@malibor
Unfortunately no.
Here is the output I get:

20 15 85 1
21 9 75 2
16 6 60 3
30 10 100 4
23 8 95 5


Not all of inFile a >> b >> c is being outputted and is mistakenly getting the values of a, b, and t wrong. Those variables in the end should be the same. The only difference is counter is added. And the counter for each line input is incorrect. But the counter error is due to of my own algorithm. But I can't seem to figure out why my counter is being inconsistent base from my algorithm.
Last edited on
First worry about reading the data in your file. When you have that correct, then worry about manipulating the data:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <fstream>

int main()
{
   std::ifstream fin("input.txt");
   std::ofstream fout("output.txt");

   int a { }, b { }, c { };

   // input three values from the file
   // will fail when there are no more values to read (end of file)
   while (fin >> a >> b >> c)
   {
      std::cout << a << '\t' << b << '\t' << c << '\n';

      // your data manipulation goes here

      fout << a << ' ' << b << ' ' << c << ' ' << '\n';
   }

   fin.close();
   fout.close();
}

10      5       70
5       15      85
12      9       75
10      6       60
20      10      100
15      8       95
4       3       35
20      10      200
9       5       65
Last edited on
Hello Battlefire,

Sorry for the delay I was away from the computer for a while.

I always did have a question of what counter was for and if it should be reset after the inner while loop. After the output line I reset the counter and it produced this:

 10   5  70  4
  5  15  85  2
 12   9  75  0
 10   6  60  0
 20  10 100  1
 15   8  95  0
  4   3  35  0
 20  10 200  3
  9   5  65  0


I also changed the line to
1
2
3
4
5
6
outFile << std::setw(3) << orgNum1 << " "
	<< std::setw(3) << orgNum2 << " "
	<< std::setw(3) << t << "  "
	<< counter << std::endl;

counter = 0;

As you can see I changed the variable names along with "a" and"b" to "num1" and "num2". Still not sure what to call "t".

I was also wondering about "sum" and if it should be reset along with "counter"?

As an example this is what I did:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <iomanip>
#include <iostream>
#include <limits>
#include <string>
#include <vector>
#include <fstream>

#include <chrono>
#include <thread>

//using namespace std;  // <--- Best not to use.
// A recent post that is worth reading. http://www.cplusplus.com/forum/beginner/258335/

int main()
{
	int num1{}, num2{}, t{};
	int orgNum1{};
	int orgNum2{};
	int counter = 0;
	double sum = 0;
	std::vector<std::string> fileNames
	{
		"inFile.txt",
		"Test File.txt"
	};

	std::string inFileName{ "inFile.txt" };
	const std::string outFileName{ "output.txt" };

	for (size_t index = 0; index < fileNames.size(); index++)
	{
		std::cout << "\n " << fileNames[index];
	}

	std::cout << "\n\n Enter the file directory: " << inFileName << '\n';
	//std::cout << "\n\n Enter the file directory: ";
	//std::cin >> inFileName;

	std::ifstream inFile(inFileName);

	if (!inFile)
	{
		std::cout << "\n File " << std::quoted(inFileName) << " did not open" << std::endl;
		std::this_thread::sleep_for(std::chrono::seconds(3));  // <--- Needs header files chrono" and "thread". Optional as is the header files.
		return 1;  //exit(1);  // If not in "main".
	}

	std::ofstream outFile(outFileName);

	if (!outFile)
	{
		std::cout << "\n File " << std::quoted(outFileName) << " did not open" << std::endl;
		std::this_thread::sleep_for(std::chrono::seconds(3));  // <--- Needs header files chrono" and "thread". Optional as is the header files.
		return 2;  //exit(2);  // If not in "main".
	}

	while (inFile >> num1 >> num2 >> t)
	{
		orgNum1 = num1;
		orgNum2 = num2;

		num1 = num1 - num2; // <--- Can be written as num1 -= num2;

		while (sum < t)
		{
			num1 = num1 + num2; // <--- Can be written as num1 += num2;

			sum += num1;

			counter++;
		}

		outFile << std::setw(3) << orgNum1 << " "
			<< std::setw(3) << orgNum2 << " "
			<< std::setw(3) << t << "  "
			<< counter << std::endl;

		counter = 0;
	}

	inFile.close();
	outFile.close();

	//system("pause");

	// A fair C++ replacement for "system("pause")".
	// The next line may not be needed. If you have to press enter to see the prompt it is not needed.
	//std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
	std::cout << "\n\n Press Enter to continue: ";
	std::cin.get();

	return 0;	
}

I had a little trouble with using an array of strings for the file names and gave up on trying to make it work for now in favor of using the vector. If you are not ready for the vector I work on using the string array.

Hope that helps,

Andy
Hello Battlefire,

Should have mentioned this: by writing the line std::string inFileName{ "inFile.txt" }; and changing the lines 35 - 37 you avoid having to enter a file name each time you run the program. This allows you to concentrate on the rest of the program until you get it working right.

When you are ready change std::string inFileName{ "inFile.txt" }; to std::string inFileName;. and change the comments on lines 35 - 37. Also uncomment line 88.

Hope that helps,

Andy
Hello Battlefire,

I think you should check your math 5 + 20 + 35 != 80, but 5 + 20 + 35 = 60.

For testing add this line after "counter++"
1
2
std::cout << "\n num1 = " << std::setw(2) << num1 << "   " << "sum = "
	<< std::setw(3) << sum << "   counter = " << counter << '\n'; // <--- Used for testing. 
and after writing to the file I put
1
2
3
std::cout << '\n' << std::string(36, '-') << '\n'; // <--- Used for testing.

counter = sum = 0;

This will give you an idea of what is happening in the inner while loop. You can comment out or delete these lines later.

I still think it is a good idea to reset "sum" at the same time you reset "counter" or "sum" will become larger the "t" and the while loop will not be entered.

Given the input file you have posted do you have an example of what the output should be?

Hope that helps,

Andy
@Handy Andy

I apologize if I took so long to reply. Also, I should have actually given what the outputs should be in the "output.txt". That is stupid of me to not give you that information.

The output should be:

1
2
3
4
5
6
7
8
9
10 5 70 4
5 15 85 3
12 9 75 3
10 6 60 3 
20 10 100 3
15 8 95 3
4 3 35 3 
20 10 200 5
9 5 65 3



As you can see, The original a >> b >> t values are the same for both from the inFile .txt file and should output into "output.txt" with the same values. The only difference is that there is a forth number for each line that is displayed into "output.txt" and that is the counter. As I mentioned before, the counter is counting the number of times 'b' is added to 'a' and 'a' is added to sum. And once sum is at a value where if the the next rotation goes over t. Then it stops right there and the number of loops is what the counter value is.

As for vectors, yeah I'm not ready for those yet. As you can see I'm still a beginner but my professor did go over string arrays. Still a bit rusty but thanks to you I can see the implication of it for my code.

I was also wondering about "sum" and if it should be reset along with "counter"?


I'm facepalming myself for not thinking of that. It should be a no brainer for both counter and sum to reset after a loop. It should be simple by just declaring sum as 0 at the end of the loop just like what you did with counter, am I correct?
Last edited on
@Handy Andy

I decided to remove num1 = num1 - num2; and got this for the output:


1
2
3
4
5
6
7
8
9
10 5 70 4
5 15 85 3
12 9 75 3
10 6 60 3
20 10 100 3
15 8 95 4
4 3 35 4
20 10 200 5
9 5 65 4


The only problem is that line 6, 7, and 9 have incorrect counter value which should be 3 and not 4. The reason why I put num1 = num1 - num2; in there was because 'a' after the first operation of a = a + b, would start the output with that so I have to get the difference of 'b' to get the output values correct. But it seems after these changes that equation is obsolete.

And based from the the test code you gave me, my calculations are still doing the sum right. Can you check this?
Last edited on
Hello Battlefire,

I always felt that the line num1 = num1 - num2; was kind of pointless to subtract before the while then add it back together in the while loop. When I put a comment on that line the program produced the correct output.

Based on the code I showed you put a comment on line 62 and see if that gives you what you want.

For line 78 I wrote it as counter = sum = 0;. This does the same as setting each variable separate.

Hope that helps,

Andy
Ok, I see what direction to take. I reseted my sum and counter after each loop and have my string arrays. I'll use other input values in my inFile to see if everything is consistent. And I'll be sure to modify it using vectors once I learn about them.

I appreciate your time helping me on this.
Topic archived. No new replies allowed.