C++ text decoder only taking one line from a text file - c++

Im working on a two part program that uses an encoder do encode a text file then a decoder to decode the text file. However i cannot get my decoder to read the whole text file it just reads the first line. How do i fix this, ive played around with the loops but it is not helping me.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
ifstream fin;
ofstream fout;
string lineFromFile;
fin.open("secret.txt");
if (!fin.good()) throw "I/O error";
fout.open("secret.txt", ios::app);
if (!fout.good()) throw "I/O error";
while (fin.good())
{
getline(fin, lineFromFile);
for (int i = 0; i < lineFromFile.length(); i++) // for each char in the string...
lineFromFile[i]--; // bump the ASCII code by 1
fout << lineFromFile << endl;
}//while
fin.close();
fout.close();
return 0;
}

You are closing the stream in the first iteration (i.e., after reading the first line). Then you open the output stream to write the first line. Only then do you reach the end of the while-loop, at which time fin.good() cannot be true anymore since you closed fin.
The loop should contain only the reading and writing. Opening done before the loop, closing done after.
Additional suggestion: Use proper indenting, it helps understanding the control flow.

I think the problem might be that you are reading and writing from the same file: secret.txt. I do not know what the expected behaviour is but when I ran the code it was infinite, which makes some sense as you are appending.
Try changing the ouput stream, fout, to a different file name.
The while loop that currently processes the file will process a final invalid read as you do not check if getline() was successful until the loop condition. I would suggest changing to:
for (;;)
{
getline(fin, lineFromFile);
if (!fin.good())
{
break;
}
for (int i = 0; i < lineFromFile.length(); i++)
lineFromFile[i]--;
fout << lineFromFile << endl;
}

Perhaps that because another file handle,fout, accesses the file to which fin is tied, fin is closed as a side-effect. Either that, or because fout appends to the file, the file pointer is pointed to the end of the file, and so because there is no more input to read, the loop ends.
(These are hypotheses; I am not familiar enough with the specifics of C++ I.O. to conclusively say what is happening.)
If you are supposed to replace the original file with an encoded version, I recommend setting the file tied to fout to a temporary file for the duration of your code above, closing both fin and fout, and then copying the file associated with fout over the file associated with fin.
Otherwise, just tie fout to a different filename than fin, such as "encoded.txt".

Related

read a .dat file in c++

I am unable to read '.dat' file. I have tired all the possible ways and tired googling it but I could not find the solution. All it gives me is a null value for integer and a junk value for a string variable or char. This what I have written
ifstream file;
file.open("data1.dat"); // I have also tried this way too like file.open("data1.dat", ios::binary, ios::in);
int data=0;
file >> data;
cout << data << endl;
system("pause");
return 0;
I am using visual studio to compile this code. I am pretty sure that the pointer is entering into the data file but I don't know for what reason the data is not being read.
The .dat file consists of integer number per line ranging from 0, so I just need to read the file and get number from each line and should find the sum of all numbers in the file. The file contains number like
5,
468,
3200,
32, etc.,. Each number is in a new line. The file can contain any number of records. this how .dat file looks when opened using a notepad editor
Your code "works" on my system.
The following compiles (without "using namespace std;")
I changed the file name for my convenience.
I created the 't391.dat' file in the same working directory of the code, and put in 10 lines, with 1 value per line, 1..9,0.
#include <fstream>
#include <iostream>
int t391a(void)
{
std::ifstream file;
file.open("t391.dat");
int data=0;
file >> data;
std::cout << data << std::endl; // echo of input / proof it works
//system("pause");
file.close();
return 0;
}
This code outputs the first value (which is all it attempts to do), so it is working!
The echo of input is good idea.
As an experiment, I temporarily renamed the 't391.dat' file to something else. The code ran to completion and printed a single 0, which is not the first value in the file. Perhaps this suggests your file is not being found, I won't guess. To confirm, I restored the file, and the above 'works' again.
Missing items in your code:
error check - file.open()
a loop to read to end of file
error check - formatted extract (i.e. read from stream) of data item
file.close - possibly not needed
If you are still working this issue, I have a minimally extended version of your code that addresses these issues. Let me know.
class ValueGet {
public:
int data;
ValueGet() {
data = 0;
}
};
int main()
{
ValueGet vg;
ifstream file;
file.open("data1.dat", fstream::binary | fstream::out); // Opens a file in binary mode for input operations i.e., getting data from file.
if (!file)
cout << "File Not Found." << endl;
else {
file.seekg(0); // To make sure that the data is read from the starting position of the file.
while (file.read((char *)&vg, sizeof(vg))) // Iterates through the file till the pointer reads the last line of the file.
cout<<vg.data<<endl;
}
//system("pause");
return 0;
}
output of the data in the file
Here is one way which I just found
#include <bits/stdc++.h>
using namespace std;
int main(){
unsigned int a;
unsigned char c;
ifstream file;
file.open("ou.bin", ios::binary);
if(!file.is_open()){
cout<<"error";
return 0;
}
for(int i=0; i<8; i++){
file>>c;
a = c;
a = a<<8;
file>>c;
a = a+ c;
cout<<a<<endl;
}
file.close();
return 0;
}
This for storing two bytes in a number you can store as many bytes in a number or even one.
Hope this helps.
You will not be able to read .dat files and understand them in your context-- they are general formats used for storing data. Unless you know the contents of it or how they are specified, you will always get junk.

find word in a text in C++ and print some next specific lines

I wrote a code in C++ that writes a .txt file.
Then I want to open the code again and give some information, so I can get a new text depending on what I gave as an input.
For example I want to give the name of a month, and print in another .txt file all the lines that came after the word "November".
I found some solutions, but none of them worked for me!
One solution that I found on stack overflow is the following:
void Keyword(ifstream & stream, string token) {
string line;
while (getline(stream, line)) {
if (line.find(token) != string::npos) {
cout << line << endl;
}
}
cout << token << " not found" << endl;
}
I can't print the next lines with the code above.
Any suggestion would be helpful!
Thanks!
If you want to perform operations on files such as 'Read' and/or 'Write',you might want to search on the net(or if you have a C++ book) on topics such as "File I/O operations using C++". Anyways moving on, C++ has 2 basic classes to handle files which are ifstream and ofstream. And to use them you have to include ethier the header fstream(i.e #include<fstream>) or include them separately as #include<ifstream> and #include<ofstream>. ifstream is basically used for all input operations such as reading files etc. Similarly ofstream is used for all output operations such as writing data to files.
You can open a file and write data to it by doing the following,
ofstream myFile("filename");// Create an instance of ofstream and open file for writing data
and to write data to the file use the << operator like below,
myFile<<data;
Similarly, You can open a file and read data as follows,
ifstream myFile("filename");//Create an instance of ifstream and open file to read data
and to read data from the file use the >> operator as shown below,
myFile>>data;
You can also open a file using the method void open(const char *filename, ios::openmode mode); as shown below,
//Writing only
ofstream outFile;
outFile.open("filename.txt",ios::out);
//Reading only
ifstream inFile;
inFile.open("filename.txt",ios::in);
//For reading and writing
fstream file;
file.open("filename.txt",ios::in|ios::out);
//For closing File
outFile.close();
//or
inFile.close();
//or
file.close();
Note the open() method takes various flags such as ios::in for reading mode, ios::out for writing mode, ios::app for adding data to the end etc.
All of these can also combined by using the bit OR operator | as shown below,
outFile.open("filename.txt",ios::out|ios::app);
There is a lot more in IO. I just covered the things required to start.
Here is the solution to your problem. Try to understand it.
#include<iostream>
#include<fstream>
#include<cstring>
using namespace std;
int main()
{
ofstream outFile;
ifstream inFile;
char fileName[10],data[50];
int noLines;
cout<<"Enter Month:"<<endl;
cin>>fileName;
cout<<"Enter Number of lines you want to enter:"<<endl;
cin>>noLines;
outFile.open(fileName,ios::out);
cout<<fileName<<"(Enter Data):";
for(int i=0;i<=noLines;i++)
{
cin.getline(data,50);
outFile<<data<<endl;
}
outFile.close();
cout<<"Openening "<<fileName<<" :"<<endl;
inFile.open(fileName,ios::in);
for(int i=0 ;i<=noLines ;i++)
{
inFile.getline(data,50);
cout<<data<<endl;
}
inFile.close();
return 0;
}
OP has found most of the solution already:
string line;
while (getline(stream, line)) {
if (line.find(token) != string::npos) {
cout << line << endl;
}
}
cout << token << " not found" << endl;
But this only prints the lines with the keyword. And always prints the "not found" message. Ooops.
Instead I pitch:
string line;
bool found = false;
while (!found && getline(stream, line))
{ // search for keyword
if (line.find(token) != string::npos)
{
found = true; // found keyword. Stop looking
}
}
if (found)
{ // print out all remaining lines in the file
while (getline(stream, line))
{
cout << line << endl;
}
}
else
{
cout << token << " not found" << endl;
}
The above splits the finding of the token and the printing of the remaining file into two stages for readability. It can be compressed into one loop, but two things make this a sucker bet:
this program will be IO bound. It will spend the vast majority of its time reading the file, so little tweaks that do not address getting the file into memory are wasted time.
combining the loops would require the addition of logic to the loop that would, over along run, dwarf the minuscule cost of switching loops.
Try this:
http://www.cplusplus.com/doc/tutorial/files/
and this:
http://www.cplusplus.com/forum/beginner/14975/
It's about reading and writing files in c++ and about searching in files.

C++ Trouble opening a file for output

So I am working on a program for class in which we have to open two different text files to retrieve the appropriate text to be displayed in the console. My code is not opening the file and keeps outputting the else statement ".txt file cannot be open". I've tried several different ways to open the file but with no luck. Any help here would be greatly appreciated.
//
// main.cpp
// PunchLine program
// Page 896 Problem 3
//
//
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
//File stream objects
fstream inFile;
string line;
//Open joke file to read lines to console
inFile.open("joke.txt", ios::in);
if (inFile.is_open())
{
//Read lines from file to console
while (getline(inFile, line))
{
cout << line << endl;
inFile.close();
}
}
else
cout << "joke.txt file cannot be open.\n";
//Open punchline file to read last line joke to console
inFile.open("punchline.txt", ios::in);
if (inFile.is_open())
{
//Read last line from file to console
inFile.seekp(-52L, ios::end);
getline(inFile, line);
}
else
cout << "punchline.txt file cannot be open.\n";
return 0;
}
When declaring an input file use
ifstream inFile;
Also make sure the input file is in the same folder as your .exe
Edit: http://www.cplusplus.com/doc/tutorial/files/ also, this link should help with working with files.
Edit 2: I already posted this in a comment, but I'll just add it to the official answer: "Change your while loop as well. Instead of the if test, use while(inFile.is_open()) and then use your getline statement inside the loop. Because right now your code reads like while get this line from the file is true cout line. So it might not even be doing the while loop."
I don't think you should close the file inside the while loop. Otherwise, your file gets closed after only the first line is read in. Move the close statement outside the loop. Same for the second block.
if (inFile.is_open())
{
//Read lines from file to console
while (getline(inFile, line))
{
cout << line << endl;
}
inFile.close();
}
else
cout << "joke.txt file cannot be open.\n";
Check that your file exist. If it does, check whether you have the correct path when you open it (check if your .txt files are in the same directory as your .exe file, or specify the full path in your code). If yes, check if the files are read-only.
use
if(!infile)
{
cout<<"cannot open file";
}
I think you need to flush the screen. Once you have flushed and closed the stream. The next time you run an application it should open the file.
e.g.
inFile.flush();
inFile.close();

Visual C++ - Cannot open text file

Simple program to open up a file and read it's contents. Then a test at the end to see if I did in fact get the information. Every time I run it it tells me that it cannot open the file. I will post the contents of SaleSlips below. Why isn't it opening the file? It is also attempting to delete the file every run as well.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
struct SaleSlip{
char name[20];
int prodID;
double value;
};
void main(){
fstream slips;
SaleSlip sales[17];
slips.open("SaleSlips.txt", ios::in);
if(slips.eof()){
cout << "Cannot open file - SaleSlips.txt"<< endl;
system("pause");
exit(2);
}
int i = 0;
while(!slips.eof()){
slips.getline(sales[i].name, ' ');
slips >> sales[i].prodID;
slips.ignore(5, ' ');
slips >> sales[i].value;
slips.ignore(80, ' ');
i++;
}
cout << sales[1].value;
slips.close();
system("pause");
}
Eric 1 200000.00
Sookie 2 200.00
Sookie 4 200.50
You're opening the stream in output mode by using ios::out. Use ios::in to read from it.
You've got a lot of other issues, too. IE:
-The if(!slips.eof()) after the file open will always cause an exit unless the file is empty.
-In your while loop, you are (probably accidentally) attempting to write the prodID and value into the slips file using <<. Use >> to read from a stream and << to write to it.
You have two problems:
You're opening the file for output (writing)
slips.open("SaleSlips.txt", ios::out);
Useios::in instead for input (reading)
slips.open("SaleSlips.txt", ios::in);
Next, you're immediately testing for !eof(), which is the wrong logic.
if(!slips.eof())
You don't want to be at eof() when opening the file for input. eof() is end of file. When first opening the file for input you want to be at the beginning of the file; being at eof() is a bad thing. Your code should error out if eof() is true, not if it's false:
if(slips.eof()) {
// It's an error if we're starting at eof()
}

Why using while(!input.eof()) loop twice not working? [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 9 years ago.
On the following lines of code is intended to put every words in the input text file(words are separated by new lines) to a vector of strings, then to turn each word inside out, and to see if this turned word is contained in the list of words in the input file.
I believe my binary search function and wordTurn function works fine.
I did several simple tests on my code, and I found out using while(!myFile.eof()) loop twice might be the cause for my code not working. By not working I mean I get the output file("pairs.txt") as an empty document(it is supposed to be a list of pairs of words).
That is, when I put some simple print code in the second while(!myFile.eof()) loop body, it did not get printed out, from which I concluded this loop is not reached. This is more likely, since it printed when I commented out the first while(!myFile.eof()) loop. I originally placed the first while loop at the else body, but this made no difference.
What do you think is the problem?
I tried combining those two loop body into the second loop, and it produces something in the output file, but this was not what this code was supposed to do, and this was logically not correct.
Any words of advice would be greatly appreciated.
int main(int argc, char* argv[]) {
vector<string> words;
ifstream myFile(argv[1]);
ofstream outputFile("pairs.txt");
string vocab;
string s;
int count;
while(!myFile.eof()) { //first while(!myFile.eof()) loop
getline(myFile, s);
words.push_back(s);
}
if(argc != 2) {
cout << "Usage: provide the name of one input file after the dictlookupHN executable file." << endl;
return (1);
}
else {
if(!myFile.is_open()) {
cerr << "Error: unable to open file " << argv[1] << endl;
return (1);
}
else {
while(!myFile.eof()) { //second while(!myFile.eof()) loop
getline(myFile, vocab);
string turnedWord = wordTurn(vocab);
if(binsearch(words, turnedWord) != "") {
outputFile << vocab << ":" << turnedWord << endl;
count++;
}
}
}
}
myFile.close();
outputFile.close();
return 0;
}
The ifstream class maintains an internal offset into the stream data, keeping track where it has to read from, for the next operation.
When this offset reaches the end, it stops the first loop, (eof() returns false). You need to reset this internal position back to the beginning of the file, before reading again.
You do that by saying:
myFile.clear(); // clear stream flags and error state
myFile.seekg(0, ios::beg); // reset read position
before the second loop.
Edit: Added call to clear().
What is happening is that the seek pointer for the file is at the end of the file when you complete the first run through the file. If you want to seek through the file again, you will need to reset the file pointer using myFile.seekg(0, ios::beg); before the second while loop. Something like this:
...
else {
myFile.seekg(0, ios::beg);
while(!myFile.eof()) { //second while(!myFile.eof()) loop
...
That should fix the problem.
If you want to read the file again [once you have read the entire file to the end] you will need to reset the bad/fail bits, and also seek to the start. End of file is a permanent state unless something is done to reset it.
So, you need myFile.clear(); and myFile.seekg(0, ios_base::beg);
Although I have a feeling you actually want to open a different file in this particular case, in which case, I would recommend closing the current one, and using a different variable - they aren't very expensive, and it makes the code clearer [particularly if you call it something sensible, e.g. vocabFile instead of myFile]
To read from the beginning of your file again, use:
myFile.seekg(0, ios::beg);
But note, that this is not a good way of reading from a file:
string vocab;
while(!myFile.eof()) {
getline(myFile, vocab);
...
}
This is how it should look like:
string vocab;
while(getline(myFile, vocab)) {
if (vocab.empty())
continue; // empty line might be read
...
}
Have a look at: Why does my input seem to process past the end of file?
The first loop reaches the end of file, and you're not resetting before the second read. You need to seek to the start of the file after the first loop: myFile.seekg (0, ios::beg); will do this for you.
the first loop reached EOF, thats the position of "read marker", so the second EOF is readed as first in the second loop.
As simple, try to close and open file between loop.
Better idea is to use seekg to read from top again.
Thank you everyone for all of these words of good advice.
They really helped me understand how the ifstream and eof work.
My TA's advice was to use for loop instead of the second while(!myFile.eof()) loop. I might be using this option, but your answers will be of great help when I have to use eof twice.
Thank you!
while(!myFile.eof()) {
string s;
getline(myFile, s);
words.push_back(s);
}
for(int i=0; i<words.size(); i++) {
//LOOP INV:
string vocab = words.at(i);
string turnedWord = wordTurn(vocab);
if(binsearch(words, turnedWord) == 1 && turnedWord.length() > 3) {
outputFile << vocab << ":" << turnedWord << endl;
count++;
}