How to read from a file [duplicate] - c++

This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 9 years ago.
* For those having this problem, it was the problem with my command. Make sure your command to compile and run the program is correct!
I was watching a tutorial on youtube.
I did exactly the same as the op did, and I get a different output.
I am new to c++, and I am using Xcode to run the code.
here is the code: (again, it's not mine, but from a youtube tutorial video)
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int input[100];
int x = 0;
int fail = 0;
int pass = 0;
fstream textfile;
textfile.open("exam.txt");
while(! textfile.eof()) {
textfile >> input[x];
cout << input[x] << endl;
if(input[x] < 50) {
fail++;
}
else {
pass++;
}
x++;
}
textfile.close();
cout << fail << "students out of " << (fail + pass) << "did not pass the exam." << endl;
return 0;}
It's supposed to print grades.
But this is what I get when I run it on Xcode.
0
0
0
0
0
0
0
0
1606415288
32767
1606415720
32767
1606415720
32767
2003953588
1294056514
104
1
1606415312
32767
25240
1
1606415288
32767
1606415312
32767
25248
1
1606415288
32767
1606415312
32767
1606415720
32767
25264
1
1606415304
32767
1606415720
32767
1606415720
32767
6144
1
1910210376
32767
1606416728
32767
0
0
0
0
0
0
0
0
0
0
1606416544
32767
2003953588
1294056514
1606416544
32767
-1988827167
32767
0
0
1
0
1606416904
32767
0
0
It's only part of the output. It doesn't terminate.
Also, when I try to run it on linux (sshed into school linux machine),
I get this following error:
##?!#8 # #####?88#8###?? ??`?`?? ``?TT#T#DDP?tdPP#P#DDQ?tR?td??`?` /lib64/ld-linux-x86-64.so.2GNUGNU?Yd?`˫sP???*??"b!!?? (E?L?
CyIk? ^Q#y??K#??'?[?
#3P
# `??
#libstdc++.so.6__gmon_start___Jv_RegisterClasses_ZNSt8ios_base4InitD1Ev_ZNSt13basic_fstreamIcSt11char_traitsIcEEC1Ev_ZNSt13basic_fstreamIcSt11char_traitsIcEE5closeEv_ZNSirsERi_ZNSt13basic_fstreamIcSt11char_traitsIcEE4openEPKcSt13_Ios_Openmode__gxx_personality_v0_ZSt4cout_ZNSolsEi_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6__ZNSt13basic_fstreamIcSt11char_traitsIcEED1Ev_ZNSolsEPFRSoS_E_ZNKSt9basic_iosIcSt11char_traitsIcEE3eofEv_ZNSt8ios_base4InitC1Evlibgcc_s.so.1_Unwind_Resumelibc.so.6__stack_chk_fail__cxa_atexit__libc_start_mainGCC_3.0GLIBC_2.4GLIBC_2.2.5CXXABI_1.3GLIBCXX_3.4 P&y
xui ?ӯk?t)??`? ` ` ` ` `( `0 8 ` # ` p60ii
H `
P `
` `h `p `x `? `H??c????H???5? ?%? #?%? h??????%? h??????%? h??????%? h?????%? h?????%? h?????%? h?????%? h?p????%? ?`????%? h ?P????%? h
?#????%? h
?0????%? h
?????%z h?????%r h??????%j h?????1?I??^H??H???PTI???#H??0#H??
#????????H?H?? H??t??H?Ð????????????UH??SH??=0 uK?`H?* H???`H??H??H9?s$fDH??H? ???`H?? H9?r??? H?[]?fff.?H?= UH??t?H??]`??]Ð?UH??SH???dH?%(H?E?1?Dž????Dž????Dž????H??????H???T???????H???????#H???????|H??0?????????Hc?H??H?H??????H??H???$?????????H????0????ƿ? `?Y?????
#H???
?????????H????0?????1 ???????????????????H??????H???????????d???H??????H???R???????????????????????ƿ? `??????%#H????????H???????6#H?????????
#H???`????H??????H?????????H?U?dH3%(t$?H??H??????H???????H??H???L????????H???[]?UH??H???}??u??}?u*?}???u!??!`?6????P
#?? `??!`H?????????UH?????????]?UH??}??u??U??E? ?]Ð???H?l$?L?d$?H?-? L?%? L?l$?L?t$?L?|$?H?\$?H??8L)?A??I??H??I???k???H??t1?#L??L??D??A??H??H9?u?H?\H?l$L?d$L?l$ L?t$(L?|$0H??8???Ð?????????????UH??SH?H H???t??`DH???H?H???u?H?[]Ð?H??_???H??exam.txtstudents out of did not pass the exam.D????`?????s?????????????????0p???XzRx
$H??? FJ
O ??;*3$"D8???A?C
I used this command: g++ main.cpp -o output.out
Is there something wrong with my command?
Thank you so much!!!

You're doing some dodgey things. As mentioned already, don't test eof. You actually need to test whether your input was successful and/or whether the stream is good. You can have a catch-all when you're reading streams:
while( infile )
{
//...
}
I mentioned also that you need to check that the value was read. It could be that an integer cannot be read because the input stream does not contain something that looks like an integer, or perhaps some other error occurred. Since you're only reading one integer at a time, you can test that operation by itself. If the stream was bad to begin with (eg the file could not be opened) it will fail straight away:
while( infile >> input[x] )
{
//...
}
I wouldn't generally use the above approach if reading more than one value each time, because the loop condition gets cluttered. Here's an alternative:
while( infile )
{
if( !(infile >> input[x]) ) {
cout << "Failed to read value " << x+1 << endl;
break;
}
//...
}
Let's roll with that, because it's more useful when you wanna find out what's going on. The next thing is that you have a fixed-size array with 100 values. If you read too many values, you are going to overflow. So you need to make sure this won't happen:
while( infile && x < 100 )
{
if( !(infile >> input[x]) ) {
cout << "Failed to read value " << x+1 << endl;
break;
}
cout << input[x] << endl;
if( input[x] < 50 ) {
fail++;
} else {
pass++;
}
x++;
}
Now, it seems to me that you're not even using the array, so why keep it at all? You could just read into a temporary value:
int grade;
if( !(infile >> grade) ) break;
// ...
But if you wanted to keep the array and didn't know how many grades you might end up reading, use a vector<int> instead of an int array. I'll show this with the simpler loop style:
std::vector<int> grades;
int grade;
while( infile >> grade )
{
grades.push_back(grade);
//...
}
Notice how I've used more descriptive variable names. Something like input doesn't tell you much about what it contains. That is the kind of variable name you'd get from an inexperienced programmer whose YouTube videos you should immediately boycott.
The last thing I'll suggest is using ifstream instead of fstream, because by default you don't need to open the file in read/write mode. You could supply flags to fstream::open, but why do that when you can just construct ifstream like this:
ifstream infile("exam.txt");
You also don't need to explicitly close it, because that will happen when infile's destructor is called.

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void main ()
{
string STRING;
ifstream infile;
infile.open ("names.txt");
while(!infile.eof) // To get you all the lines.
{
getline(infile,STRING); // Saves the line in STRING.
cout<<STRING; // Prints our STRING.
}
infile.close();
system ("pause");
}
I hope, this code can help you.

Related

Why splitting a line separated by spaces with stream in C++ runs infinitely?

Before, when I was writing C++, I often used getch() for validation. However, now I am turning into competitive programming, I cannot use getch(); I had to use cin or getline. Thus, today, I replicated an instance of splitting a string using stringstream:
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
int main() {
string line;
getline(cin, line);
cout << line << endl;
stringstream reader;
reader.clear();
reader.str(line);
vector<long long int> list;
while (true) {
reader.clear();
if (reader.str().size() == 0) {
break;
}
long long int value;
reader >> value;
list.push_back(value);
}
}
Then, I ran the program, typed 1 2 3 4 5 6 7 8 9 and pressed enter. The program successfully displayed line, 1 2 3 4 5 6 7 8 9, but the program just didn't terminate. It never approached the end of the main() function. I tried to print reader.str(), but it just print 1 2 3 4 5 6 7 8 9 continually. I was confused. Why reader >> value didn't run and did not read any value? Why was the program running an infinite loop? How can I fix the issue? I appreciate any solution.
The reading operator >> does not change the underlying string. It uses an inner position of a next char to read.
int main() {
int n;
std::istringstream in; // could also use in("1 2")
in.str("1 2");
in >> n;
std::cout << "after reading the first int from \"1 2\", the int is "
<< n << ", str() = \"" << in.str() << "\"\n";
}
Outputs
after reading the first int from "1 2", the int is 1, str() = "1 2"
The loop may be terminated by replacing reader >> value; with
if (!(reader >> value))
break;
... but the program just didn't terminate.
This means that ...
while (true)
true is never false, or ...
reader.str().size() == 0
is never true.
true, in fact, is never false, and you never change the size of the reader's string object. Why would you expect this loop to break?
Please edit your question to make it more clear what you are trying to accomplish.

File Handling - Value is being added two times instead of one [duplicate]

This question already has answers here:
Reading from text file until EOF repeats last line [duplicate]
(7 answers)
Closed 2 years ago.
When I run my code it is adding the value of 81 two times. Why ???
Write a program to read the contents of file Squares.txt and display the
sum of all the numbers, the average of all the numbers, the largest
number and the smallest number in a file named Analysis.txt.
Content in Squares.txt :
Number Square
3 9
5 25
1 1
7 49
9 81
#include <iostream>
using namespace std ;
#include <fstream>
int main() {
ifstream file ;
char arra[100];
int num1,num2,avg;
int sum=0 ;
int smallest = 9999 ;
int highest = -999 ;
int count= 0 ;
cout<<"Open file square.txt..."<<endl ;
file.open("/Users/kchumun/Documents/Xcode/Labsheet 8(3)/square2.txt") ;
if(!file){
cout<<"File cannot be opened !"<<endl ;
}else {
cout<<"File opened !"<<endl;
file.get(arra,100) ;
while(!file.eof()){
file>>num1;
file>>num2 ;
sum+=num2;
count++ ;
if(num2<smallest){
smallest = num2 ;
}
if (num2>highest) {
highest = num2 ;
}
}
}
file.close() ;
avg= sum / count ;
cout<<"Sum= "<<sum<<endl ;
cout<<"Average= "<<avg<<endl;
cout<<"Highest= "<<highest<<endl ;
cout<<"Smallest= "<<smallest<<endl;
ofstream File ;
cout<<"Open file Analysis "<<endl ;
if(!File){
cout<<"Error !" ;
}else{
File.open("/Users/kchumun/Documents/Xcode/Labsheet 8(3)/Analysis.txt");
File<<"Sum= "<<sum<<endl ;
File<<"Averagem= "<<avg<<endl;
File<<"Highest= "<<highest<<endl ;
File<<"Smallest= "<<smallest<<endl ;
}
File.close();
cout<<"Operation completed !";
return 0;
}
This style of code is incredibly common but also incredibly wrong
while(!file.eof()){
file>>num1;
file>>num2;
Like this instead please
while (file >> num1 >> num2) {
The problem with your code is a misunderstanding of how eof works. Eof tests if you are at the end of the file right? No, wrong. In reality eof tests if your last read failed because you were at the end of file. A subtly different thing, and this difference explains why your loop seems to read the last item twice.
If you do use eof you should use it after reading to test if the last read failed. Not before reading to predict if the next read will fail.

std::cin only runs once in while loop? [duplicate]

This question already has answers here:
How to handle wrong data type input
(4 answers)
Closed 2 years ago.
I'm sorry if this question is stupid, but it's been kind of bugging me. I have written a program that is supposed to accept user input 5 times and then print out the result each time (i am using a while loop.) Here is the code I wrote:
#include <iostream>
int main()
{
int x = 1;
int number;
while (x <= 5)
{
std::cin >> number;
std::cout << number << std::endl;
x++;
}
return 0;
}
However, after compiling and running (i'm using clang) the program only lets me insert user input once and then it just prints a bunch of 0's:
jakdfjaksdfjk
0
0
0
0
0
I am really confused why this behavior happens. Shouldn't you be able to pass in user input 5 times? Why does this behavior happen? Help would really be appreciated.
You are trying to read an integer and "jakdfjaksdfjk" would be a string, that's why that happens. Type something like 1 4 8 35 42 and it'll work as you expect
You should consider checking the validation of std::cin:
#include <iostream>
int main(void) {
int x = 1;
int number;
while (x++ <= 5) {
std::cin >> number;
// If the input isn't an integer, the breaks the loop and quit
if (!std::cin.good()) {
std::cout << "Numbers only please.\n";
break;
}
// Otherwise, simply print...
std::cout << number << std::endl;
}
return 0;
}

Output from array is wrong

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <fstream>
using namespace std;
void make_array(ifstream &num, int (&array)[50]);
int main(){
ifstream file; // variable controlling the file
char filename[100]; /// to handle calling the file name;
int array[50];
cout << "Please enter the name of the file you wish to process:";
cin >> filename;
cout << "\n";
file.open(filename);
if(file.fail()){
cout << "The file failed to open.\n";
exit(1);
}
else{
cout << "File Opened Successfully.\n";
}
make_array(file, array);
file.close();
return(0);
}
void make_array(ifstream &num, int (&array)[50]){
int i = 0; // counter variable
while(!num.eof() && i < 50){
num >> array[i];
i = i + 1;
}
for(i; i>=0; i--){
cout << array[i] << "\n";
}
}
Alright, so this it my code so far. When I output the contents of the array, I get two really large negative numbers before the expected output. For example, if the file had 1 2 3 4 in it, my program is outputting -6438230 -293948 1 2 3 4.
Can somebody please tell me why I am getting these ridiculous values?
Your code outputs the array backwards, and also it increments i twice after it has finished reading all the values. This is why you see two garbage values at the start. I suspect you are misreporting your output and you actually saw -6438230 -293948 4 3 2 1.
You end up with the extra increments because your use of eof() is wrong. This is an amazingly common error for some reason. See here for further info. Write your loop like this instead:
while ( i < 50 && num >> array[i] )
++i;
Now i holds the number of valid items in the list. Assuming you do actually want to output them backwards:
while ( i-- > 0 )
cout << array[i] << "\n";
To output them forwards you'll need two variables (one to store the total number of items in the array, and one to do the iteration)
The check !num.eof() only tells you that the last thing you read was not eof. So, if your file was 1 2 3 4, the check will only kick in after the 5th num>>array[i] call. However, for that i, array[i] will be populated with a meaningless value. The only correct way to deal with eofs is to check for validity on every call to operator>>. In other words, the right condition is simply num>>array[i]. This works by exploiting this conversion to bool since C++11 and to void* pre-C++11.

Assign last number of a text file to a variable C++

I am doing a program that outputs a list of prime numbers with fstream.
I have this so far:
int export_list (int lim = 50)
{
int x;
last_in_txt = ????????????; // assigns last number on txt
ofstream file ("Primes.txt" , ios::app);
if (file.is_open()) // if it opens correctly
{
for (x = last_in_txt ; x < lim ; x++)
{
if (check_prime (x)) // returns 1 when x is prime, returns 0 when not
{
file<< x << " ";
}
}
cout << "Done!" << endl << pressenter;
cin.get();
}
else
{
cout << "Unable to open file" << endl << pressenter;
cin.get();
}
return(0);
}
So, as you can see, this should append a list of prime numbers to Primes.txt, starting with the prime 1234547.
Primes.txt looks like this:
2 3 5 7 11 13 17 19 23 29 31 37 (...) 1234543 1234547
My question is how do I assign 1234547 (which is the last number of the txt) to the variable last_in_txt?
Other (not so important) question:
Should I save the numbers the way I'm currently doing, or should I store each number in a separate line?
One simple way: keep reading and assign until the whole file is read.
For example,
int last_in_txt = 0;
{
ifstream infile("Prime.txt");
int k;
while(infile >> k) {
last_in_txt = k;
}
}
// Now last_in_txt is assigned properly, and Prime.txt is closed
This works well no matter the numbers in Prime.txt are separated by space characters (' ') or by newline characters ('\n').
My suggestion is that you write using binary format into the text file(using wb in C). In this case you will know how many bytes does the last number occupy and you will be able to use seekg and tellg to get it. If you use plain text format you will have to read char by char from the end and this is more error-prone and also slower.