Reading data from file created from outside - c++

I'm trying to read from files created outside of the program, but am having some trouble. The program has the user create a file. Then it reads words from two .txt files created outside of the program, and then writes the words to the created file.
#include "std_lib_facilities.h"
int main()
{
string word;
cout << "Create file.\n";
char name[20];
cin >> name;
ofstream ost(name, ios::out);
cout << "Open first file.\n";
char filename[20];
cin >> filename;
ifstream ist(filename);
while(ist >> word) ost << word << " ";
ist.close();
cout << "Open second file.\n";
cin >> filename;
ifstream isttwo(filename);
while(isttwo >> word) ost << word << " ";
isttwo.close();
ost.close();
keep_window_open();
}
However, when I open the created file in notepad, it comes out blank. Is this because reading into a string is impossible because the files being read were created separately? I'm not really sure. Any help is appreciated.

The code is correct. Just make sure when you write the name of the first file and the second one you write their extensions as well.
For example :
first.txt
second.txt

A potential problem is your use of cin instead of getline.
Imagine this input:
Open second file.
>>file one.txt
This obviously won't open the file you want, since cin stops reading once you hit a space.
Try explicitly opening name, such as:
ost.open(name);
I also don't like your implicit use of the >> operator in the while loops. Try this:
while (!ist.eof())
{
getline(ist, word);
ost << word;
}

Maybe you should null terminate the filename[20] string . Like filename[20]={0}; before getting it from the standard input ; Then try printing out the filename on the console to check if the file name is OK .

Trikker,
The code compiled with insignificant changes and I came across the same problem you are having, though actually it works. Here's what happened with me. It has to do with how you are running the program. The exe file is saved in ../ProjectDir/Debug directory. If you save the two input files in Debug directory, you should run the program from the command prompt, NOT from the IDE (assuming Visual Studio 2008). However, if you run it from the IDE, save the two input files in ../ProjectDir/ProjectDir. Once I did that everything was ok with me.
Just to be sure about this directory thing, I have printed the directory from which the program is being run from the IDE. Though, the prompt shows that it is running the exe from the Debug directory, the working directory was actually ProjectDir/ProjectDir.
Anyway, please, give the following code a shot and do let us know?
//#include "std_lib_facilities.h"
#include <fstream>
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
system("cd");
//string word;
char word[80];
cout << "Create file.\n";
char name[20];
cin >> name;
ofstream ost(name, ios::out);
cout << "Open first file.\n";
char filename[20];
cin >> filename;
ifstream ist(filename);
while(ist >> word) ost << word << " ";
ist.close();
cout << "Open second file.\n";
cin >> filename;
cout << filename;
ifstream isttwo(filename);
while(isttwo >> word) ost << word << " ";
isttwo.close();
ost.close();
//keep_window_open();
}
This directory issue also probably explains why you didn't get anything, when tried to print out if it was reading anything at all. You probably should have checked if the input file creation was successful. To do that, just add ...
if ( ist.fail() ){
cout << "file open failed\n";
}
after
ifstream ist(filename)

What happens if you use absolute paths? e.g. on Windows try c:\file.txt and so on.

Related

Opening a C++ .txt file using user-input

I'm trying to open a C++ .txt file as shown in my code below. This is part of a larger program that I'm working on where I write the contents of one file into another so that it contains the same information as the original but I am required to provide user-input. If the user-provides a .txt file that is not the one we are using, I have to produce an error message and prompt them to re-enter an input until they input the correct one (test.txt):
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
/* Refers to test.txt */
ofstream mainfile;
std::string filename;
std::cout << "Please enter the name of your data file: ";
std::cin >> filename;
mainfile.open(filename.c_str());
mainfile << "test.txt";
if(!mainfile) {
std::cout << "I'm sorry, I could not open '" << filename << "'." << std::endl;
std::cout << "Please enter another name: " <<
std::endl;
std::cin >> filename;
} else {
std::cout << "File '" << filename << "' opened successfully!" << std::endl;
}
return 0;
}
My current issue is that the program is terminating too early, even when I input incorrect inputs such as jaguar.txt or flowers.txt, anything that isn't "test.txt". In fact, when I input just about any .txt file name it will output saying that it opened successfully.
It seems that what you want to do is open up 2 different files, where one is used as the file to copy from (test.txt), and the other is the file to copy to (jaguar.txt). Instead of checking if test.txt exists with std::ofstream, you should instead use std::ifstream.
Using ifstream, if the file does not exist, your code will work properly. Instead, because you are currently using ofstream, the file will open correctly, because you're essentially telling it to make the file for you.
So basically, where you have used ofstream mainfile, instead it should be:
ifstream mainfile;
Later in the code, you can prompt the user for the file to copy to (i.e. jaguar.txt), and this will be the one where you output data using ofstream.
Use ifstream to read from a file, and ofstream to write to a file.
To check whether the source file exists, test the corresponding ifstream after trying to open it:
ifstream mainfile; // ifstream stands for "input file stream"
std::cout << "Please enter the name of your data file: ";
std::cin >> filename;
mainfile.open(filename);
while (!mainfile) { // asking endlessly, until the user inputs a good file
std::cout << "I'm sorry, I could not open '" << filename << "'." << std::endl;
std::cout << "Please enter another name: " <<
std::endl;
std::cin >> filename;
mainfile.open(filename);
}
std::cout << "File '" << filename << "' opened successfully!" << std::endl;
By the way, in the error message "open" is programmer's jargon. It's a general word which includes both reading and writing. If your application copies stuff from one file to the other, the user may get confused: is there a problem with input or output? You might want to say "read" instead of "open", even though technically you didn't read anything yet. That would make a clearer error message.
If you want to copy one file to another, use one of the methods described in a dedicated question.

Evaluating expression statements from a text file in C++

I am altering a (well, my first) C++ program that evaluates expressions. For example, by inputting this:
(x + (y * 3)), x = 2, y = 6;
It should output the following:
Value = 20
The program works when the user types the expression into the console, but I want it to read and evaluate expressions from a text file (each on a separate line). I have successfully read the file in, and can even print its contents in the console, but I'm having trouble parsing and evaluating each line. There are many more header and source files that accompany this project, but I think all of the relevant information is in the main function:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
#include "expression.h"
#include "subexpression.h"
#include "symboltable.h"
#include "parse.h"
SymbolTable symbolTable;
void parseAssignments();
int main()
{
Expression* expression;
char paren, comma;
string program;
ifstream myfile("expressions.txt");
if (myfile.is_open())
{
while (getline(myfile, program))
{
cout << program << '\n'; //confirms that file was read properly
//code to parse expressions and print results
}
myfile.close();
}
else cout << "Unable to open file";
//original code that parses expression the user inputs
/*cout << "Enter expression: ";
cin >> paren;
expression = SubExpression::parse();
cin >> comma;
parseAssignments();
cout << "Value = " << expression->evaluate() << end1;*/
cin.get(); //added this so the window doesn't close automatically
return 0;
}
I have tried numerous approaches over the last couple days, and I think it comes down to my C++ ignorance of what exactly is happening on these two lines. My theory is that it parses everything to the right of the parenthesis in the first line, and everything to the right of the comma in the second line (ignoring the fact that the scopes would overlap).
cin >> paren;
cin >> comma;
Therefore, among other approaches, I tried including the following in the while loop. I am using MS Visual Studio, and when I click "> Local Windows Debugger" it will open up a console window with the first expression printed and a blinking line like it's waiting for me to input something. I close out of the window, and instead of a "> Continue" in place of "> Local Windows Debugger" it will just end the program. It is entirely possible that I'm just using Visual Studio incorrectly.
myfile >> paren;
expression = SubExpression::parse();
myfile >> comma;
parseAssignments();
cout << "Value = " << expression->evaluate();
And this:
std::istringstream iss(program);
iss >> paren;
expression = SubExpression::parse();
iss >> comma;
parseAssignments();
cout << "Value = " << expression->evaluate();
And of course this:
getline(myfile, program) >> paren;
expression = SubExpression::parse();
getline(myfile, program) >> comma;
parseAssignments();
cout << "Value = " << expression->evaluate();
Am I taking the completely wrong approach here, or worse should I be focusing on changing other functions as well? Thank you!!
EDIT: It appears that cin >> was being called in parse() and a few other .cpp files, which prevented my three attempts above from having much of an effect. Right now I'm looking into including the line as an argument in functions like below. I will report any errors if it doesn't work.
string parseName()
{
char alnum;
string name = "";
cin >> ws;
while (isalnum(cin.peek()))
{
cin >> alnum;
name += alnum;
}
return name;
}
EDIT 2: IT WORKS!!! Since cin >> was being used throughout the program, I had to create a new variable std::stringstream in(program); and then use that as arguments in functions as seen below:
void parseAssignments(stringstream& in);
int main()
{
Expression* expression;
char paren, comma;
string program;
ifstream myfile("expressions.txt");
if (myfile.is_open())
{
while (getline(myfile, program))
{
cout << program << '\n'; //confirms that file was read properly
std::stringstream in(program);
in >> paren;
expression = SubExpression::parse(in);
in >> comma;
parseAssignments(in);
cout << "Value = " << expression->evaluate() << '\n\;
}
myfile.close();
}
else cout << "Unable to open file";
cin.get(); //added this so the window doesn't close automatically
return 0;
}
Thanks for your help guys! I think I'm going to go back to something a bit simpler with C++ and build up from there...
Lets start with this
cin >> paren;
expression = SubExpression::parse();
cin >> comma;
This code reads a single character from cin (the terminal), then calls parse, then reads another single character. It never reads your expression. It also never does anything with the two single characters, it just throws them away.
This says to me that the code that reads the expression from the terminal is in SubExpression::parse() -- that code (which you don't show) apparently reads directly from cin.
This indicates immediately why all your attempts have failed -- you have your expression in a file or a string, but your parse routine is still stubbornly reading from cin. You need to change that routine to read from somewhere else.

Open a file with C++ and output the text that is in the file

I am trying to open a file with C++ and output the text that is in the file. I cannot seem to figure out what I am doing wrong. Here is what I have so far.
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
int main()
{
char fileName[50];
ifstream infile;
cout << "Enter the name of the file you would like to open: ";
cin.getline(fileName, 50);
infile.open(fileName);
if(!infile.is_open())
{
exit(EXIT_FAILURE);
}
char line[75];
infile >> line;
while (infile.good())
{
cout << line << " ";
infile >> line;
}
system("pause");
return 0;
}
After I input the file name and press enter the CMD prompt just closes. I know that the file exist, but I cannot figure out why it is exiting. Obviously it is because of the exit command, but it should be open. What am I doing wrong?
You don't need to read/write the file line by line; C++ already supports to copy the file in one step. You also should use string instead of char[] for your strings; on one hand it means that you don't need to restrict the maximal length of your strings to some arbitrary length (what if your file's pathname has more than 50 characters, or the file has lines with more than 75 characters?
Note also that your file copying code is erroneous: It will remove all whitespace from the file, as infile >> line does not read a line (use readline for that), but a word, discarding whitespace.
Also, your code should give an error message if it couldn't open the file, instead of just silently returning (you do provide an error return, which is very good, but unless you call it from something that actually gives you feedback on the error return, you'll never learn about it.
Finally, the system("pause") should probably be done in an RAII class, so it is guaranteed to be exited on return (however, exit will not call destructors, so unless you want to use atexit, you should use return in `main`` instead). A better idea would, however, be to not put this into the code, but instead run it in a terminal that doesn't immediately close after the program finishes.
Here's a program that implements those suggestions:
#include <iostream>
#include <fstream>
#include <cstdlib>
int main()
{
// make sure that system("pause") is called on all exit paths
struct cleanup
{
~cleanup() { std::system("pause"); }
} do_cleanup;
// get the file name
std::string filename;
std::cout << "Enter the name of the file you would like to open: ";
std::getline(std::cin,filename);
if (!std::cin)
{
std::cerr << "Failed to read the file name.\n";
return EXIT_FAILURE;
}
// open the file
std::ifstream infile(filename.c_str());
if (!infile)
{
std::cerr << "Could not open file: " << filename << "\n";
return EXIT_FAILURE;
}
// print the file
std::cout << infile.rdbuf();
// close the file
infile.close();
if (!infile)
{
std::cerr << "Could not properly close file: " << filename << "\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
There is no need to use a char[]. You've even #included string so just use that.
string fileName;
cout << "Enter the name of the file you would like to open: ";
cin >> fileName;
// or
// getline(cin, fileName);
ifstream infile(fileName);
if (infile.fail()) {
exit(EXIT_FAILURE);
}
string line;
while (infile >> line) {
cout << line << " ";
}
system("pause");
return 0;
I also modified a few things to make it a bit cleaner.
Thanks for the help. Yes the file was in the wrong folder. It was a newb oversight!

C++: How can I switch between input and output from file?

I'm trying to write up a program that will display the contents of a text file to the screen for a user. Specifically, the text file will be a list of names that the program will read and display each name to the user individually. The user will then either like the name and keep it or dislike the name and remove it.
My dilemma is: if the user elects to keep the name, the program will need to go from reading the file to "writing" (deleting the name) the file and then back to reading the file again! I found the following relevant code on http://www.tutorialspoint.com/cplusplus/cpp_files_streams.htm. It shows that one must use .close() to switch from reading to writing, but this seems funky to a newbie like me. Is there a better way to do it or is the code below just fine?
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
char data[100];
// open a file in write mode.
ofstream outfile;
outfile.open("afile.dat");
cout << "Writing to the file" << endl;
cout << "Enter your name: ";
cin.getline(data, 100);
// write inputted data into the file.
outfile << data << endl;
cout << "Enter your age: ";
cin >> data;
cin.ignore();
// again write inputted data into the file.
outfile << data << endl;
// close the opened file.
outfile.close();
This is where the file goes from write mode to read mode.
// open a file in read mode.
ifstream infile;
infile.open("afile.dat");
cout << "Reading from the file" << endl;
infile >> data;
// write the data at the screen.
cout << data << endl;
// again read the data from the file and display it.
infile >> data;
cout << data << endl;
// close the opened file.
infile.close();
return 0;
}
Also, I'm having a hard time finding how to read and modify individual characters in the file. I need to do this too, as the file needs to follow a specific pattern, with five names per line and one space between each name (newline at end of fifth name, obviously). Help with this would be appreciated.
Changing things mid-file is complicated.
What I would do is either create a temporary file, write the kept names to that file and replace the original file with this temporary file, (or just store the kept names in a vector and rewrite the file)
try
std::fstream ff("io.txt", std::fstream::in | std::fstream::out);
and fstream::read, fstream::write, fstream::seekg
If the file is small then load it into memory.
Otherwise use fopen with "a+" or "r+" mode and fseek.

File Handling not working in while loop

Code:
#include<iostream.h>
#include<fstream.h>
#include<string.h>
int n = 0, flag = 0,i;
struct bac
{
char name[10];
char amt[5];
} s;
void main()
{
ofstream f("C:\\TC\\1.dat");
for(i=0;i<10;i++)
{
cout << "\nenter the details ";
cin >> s.name >> s.amt;
f.write((char *)&s, sizeof(bac));
}
}
sometimes the code works fine
but at the other times , when i look at the output file,it is empty , the problem has come up many times , and i ant to know whether there is a precaution regarding loops with file handling
for eg. in other program
.....
while(ch!=4)
{
cout << "\nBANK MANAGEMENT SYSTEM \n";
cout << "enter choice ";
cout << "\n1.add\n2.search\n3.delete and overwrite ";
cin >> ch;
if (ch == 1)
{
cout << "\nenter the details ";
cin >> s.name >> s.amt;
f.write((char *)&s, sizeof(bac));
}
.....
the file is empty
I guess you may have used a very old compiler older than gcc 4.5.3.
I tried your code and it has no problem.
#include <iostream> //use header file without using deprecated iostream.h
#include <fstream> //same reason as above
#include <string>
using namespace std;
int n = 0, flag = 0,i;
struct bac
{
char name[10];
char amt[5];
} s;
int main() //usually main returns int. void was kind of old now
{
ofstream f("test.txt");
for(i=0;i<10;i++)
{
cout << "\nenter the details ";
cin >> s.name >> s.amt;
f.write((char *)&s, sizeof(bac));
}
f.flush();
f.close();
return 0;
}
I compiled the code in gcc 4.5.3 and ran it. the file has all the stuff I entered.
However, it will be better to use the << operator when you use file i/o stream to write to file.
You can find more information about and from top of this link:
http://members.gamedev.net/sicrane/articles/iostream.html
Another point, wen you have done writing to a file, remember to flush and close the file handle, otherwise, sometimes it will cause some annoying problems.
The code doesn't seem very C++-like to me...
To answer the last question, there aren't any gotchas about fstreams in loops specifically, no.
I suggest first trying to do f.write with the members name and amt themselves—compilers might add padding between name and amt, creating unwanted garbage output.
Are you sure you have write permission to the filepath all the time? Try opening a local file, as in the path being simply "1.dat".
Also try opening the file as f("/* file name */", ofstream::out | ofstream::app). "out" sets it as an output stream, and "app" makes it add to the end of the file. www.cplusplus.com/ofstream details more flags.
since you are using c++, I suggest you use a formal way to use ofstream, in your code, it should be f << s.name << s.amt.
remember, you are using c++, so keep using i/o stream.