How to read and write to a text file in C++? - c++

Hey everyone, I have just started to learn C++ and I wanted to know how to read and write to a text file. I have seen many examples but they have all been hard to understand/follow and they have all varied. I was hoping that someone here could help. I am a total beginner so I need clear instructions. Here is an example of what i'm trying to do:
#include <iostream>
#include <fstream>
using namespace std;
string usreq, usr, yn, usrenter;
int start ()
{
cout << "Welcome..."
int main ()
{
cout << "Is this your first time using TEST" << endl;
cin >> yn;
if (yn == "y")
{
ofstream iusrfile;
ofstream ousrfile;
iusrfile.open("usrfile.txt", "w");
iusrfile >> usr;
cout << iusrfile;
iusrfile.close();
cout << "Please type your Username. \n";
cin >> usrenter;
if (usrenter == usr)
{
start ();
}
}
else
{
cout << "THAT IS NOT A REGISTERED USERNAME.";
}
return 0;
}

Header files needed:
#include <iostream>
#include <fstream>
declare input file stream:
ifstream in("in.txt");
declare output file stream:
ofstream out("out.txt");
if you want to use variable for a file name, instead of hardcoding it, use this:
string file_name = "my_file.txt";
ifstream in2(file_name.c_str());
reading from file into variables (assume file has 2 int variables in):
int num1,num2;
in >> num1 >> num2;
or, reading a line a time from file:
string line;
while(getline(in,line)){
//do something with the line
}
write variables back to the file:
out << num1 << num2;
close the files:
in.close();
out.close();

Default c++ mechanism for file IO is called streams.
Streams can be of three flavors: input, output and inputoutput.
Input streams act like sources of data. To read data from an input stream you use >> operator:
istream >> my_variable; //This code will read a value from stream into your variable.
Operator >> acts different for different types. If in the example above my_variable was an int, then a number will be read from the strem, if my_variable was a string, then a word would be read, etc.
You can read more then one value from the stream by writing istream >> a >> b >> c; where a, b and c would be your variables.
Output streams act like sink to which you can write your data. To write your data to a stream, use << operator.
ostream << my_variable; //This code will write a value from your variable into stream.
As with input streams, you can write several values to the stream by writing something like this:
ostream << a << b << c;
Obviously inputoutput streams can act as both.
In your code sample you use cout and cin stream objects.
cout stands for console-output and cin for console-input. Those are predefined streams for interacting with default console.
To interact with files, you need to use ifstream and ofstream types.
Similar to cin and cout, ifstream stands for input-file-stream and ofstream stands for output-file-stream.
Your code might look like this:
#include <iostream>
#include <fstream>
using namespace std;
int start()
{
cout << "Welcome...";
// do fancy stuff
return 0;
}
int main ()
{
string usreq, usr, yn, usrenter;
cout << "Is this your first time using TEST" << endl;
cin >> yn;
if (yn == "y")
{
ifstream iusrfile;
ofstream ousrfile;
iusrfile.open("usrfile.txt");
iusrfile >> usr;
cout << iusrfile; // I'm not sure what are you trying to do here, perhaps print iusrfile contents?
iusrfile.close();
cout << "Please type your Username. \n";
cin >> usrenter;
if (usrenter == usr)
{
start ();
}
}
else
{
cout << "THAT IS NOT A REGISTERED USERNAME.";
}
return 0;
}
For further reading you might want to look at c++ I/O reference

To read you should create an instance of ifsteam and not ofstream.
ifstream iusrfile;
You should open the file in read mode.
iusrfile.open("usrfile.txt", ifstream::in);
Also this statement is not correct.
cout<<iusrfile;
If you are trying to print the data you read from the file you should do:
cout<<usr;
You can read more about ifstream and its API here

Related

More appropriate way to loop input from a file?

I want to be able to loop this file opening and closing to continually search for names.
The first time is no problem and output is what is expected then, when choosing y for yes, an output loop occurs.
Any ideas as to why this would happen? The logic seems more than correct.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string boys, girls, name;
int rank;
char end = 'n';
while (end != 'y' || end != 'Y')
{
cout << "Enter a name to search";
cin >> name;
ifstream input;
input.open("Names2016");
if (input.fail())
cout << "Failed to open file.\n";
while (!input.eof())
{
input >> rank >> boys >> girls;
if (boys == name)
cout << name << " ranks " << rank << " among boys.\n";
if (girls == name)
cout << name << " ranks " << rank << " among girls.\n";
}
input.close();
cout << "Would you like to search another name?\n"
<< "Enter Y for yes or N for no.\n";
cin >> end;
}
return 0;
}
There are a some of things you can do to make this code better,
The first is to use ifstreams and do file input/output the proper idiomatic way in a loop, don't use .eof() to check for end of file in a loop condition (the answer linked in the comments is a good place to start if you want to know why),
The second thing you want to check for validity of the file with a simple if (!file) its much cleaner IMO.
The third thing is, when you have a local file handle like you do in your code, then you can just let it go out of scope and let the destructor cleanup the file and close() it, it's the C++ RAII way of doing things (notice that I have removed the open() method to the constructor call (which does the same thing)
Use cerr instead of cout to report errors
Use char instead of int to represent characters
Not a big change, but using std::toupper like advised in the other answer's comments is a good readable way to check for uppercase and lowercase values at the same time
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
string boys, girls, name;
int rank;
char end = 'n';
while (std::toupper(end) == 'Y')
{
cout << "Enter a name to search";
cin >> name;
ifstream input{"Names2016"};
// change here
if (!input) {
cerr << "Failed to open file.\n";
}
while (input >> rank >> boys >> girls)
{
if (boys == name)
cout << name << " ranks " << rank << " among boys.\n";
if (girls == name)
cout << name << " ranks " << rank << " among girls.\n";
}
// change below, just let the file handle go out of scope and close
// input.close();
cout << "Would you like to search another name?\n"
<< "Enter Y for yes or N for no.\n";
cin >> end;
}
return 0;
}
But you can do better on the I/O if your file isn't guaranteed to change over different iterations (in which case you probably need to make sure that there is no race anyway, so I am assuming the file does not change much). Read in the file once and save that information to be used later
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <unordered_map>
#include <vector>
using namespace std;
int main()
{
string boys_name, girls_name, name;
int rank;
char end = 'n';
ifstream input{"Names2016"};
if (!input) {
cerr << "Failed to open file" << endl;
}
// preprocess the information and store it in a map
// making a map from string to vector because it is unclear whether
// there is a 1-1 mapping from the name to the rank for each name
unordered_map<string, vector<int>> boys;
unordered_map<string, vector<int>> girls;
while (input >> rank >> boys_name >> girls_name) {
boys[boys_name].push_back(rank);
girls[girls_name].push_back(rank);
}
while (std::toupper(end) == 'Y')
{
cout << "Enter a name to search";
cin >> name;
// use the map to do the lookup, much faster than reading
// the entire file over and over again
}
return 0;
}
First of all, what is this supposed to mean int end = 'n'; Are you assigning an integer with a character value?!
And why are you opening the same file inside the loop. You should probably open it only once at the beginning of the program.
And the eof doesn't have what to check for, because you have to read from a file to reach its end.

C++ Reading a txt file containing multiple kinds of variables

My skills are very basic. I'm trying to make save and load functions for a text game. This is my code:
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <string>
#include <sstream>
#include "variables.h"
// CORE FUNCTIONS
void save_game()
{
std::ofstream file((savefile_path + "/" + player_name + ".txt").c_str());
if (file.is_open())
{
file << engine_switch << std::endl; //int
file << map_switch << std::endl; // int
file << sub_map_switch << std::endl; // int
file << player_name << std::endl; //string
file << player_class << std::endl; // string
//file << << endl;
file.close();
}
else
{
std::cout << "A PROBLEM OCCURED";
system("pause");
}
return;
}
void load_game()
{
system("cls");
std::cout << "ENTER THE SAVE FILE NAME (SAME AS YOUR CHARACTER NAME)\nOR PRESS ENTER TO GO BACK TO MAIN MENU: ";
fflush(stdin);
getline(std::cin, player_name);
std::string name=player_name;
std::ifstream file((savefile_path + "/" + player_name + ".txt").c_str());
if(file)
{
file >> engine_switch; // this is int
file >> map_switch; // this is int
file >> sub_map_switch; /this is int
file >> player_name; //string
file >> player_class; //string
//file >> ;
return;
}
else
{
if(player_name=="\0")
{
engine_switch=1;
return;
}
else
{
system("cls");
std::cout << "COULDN'T OPEN THE SAVE FILE" << std::endl;
system("pause");
load_game();
}
}
engine_switch=1;
return;
}
The problem happens when I enter a player_name compound of multiple words separated with a space. For example when I enter "name name" the player_name becomes name and the player_class becomes name and the actual player_class is not put into any variable.
I tried the rdbuf() function, but didn't work and I don't even understand it yet. I tried it with stream, string, c.str(), everything I found on the web and could comprehend, but it always comes out wrong.
When you extract a string from a stream, spaces are considered as separators.
It's even worse: in your code, the player_name is followed by player_class which is also a string. How should your program interpret this :
10 15 20 John William Doe hero B
How would your program guess that John William Doe is a composed name and hero B the category ?
The simplest solution is to write all your strings on a separate line in the file. When you load it you can then read it with getline():
file >> engine_switch; // this is int
file >> map_switch; // this is int
file >> sub_map_switch; /this is int
getline (file, player_name); //string
getline (file, player_class; //string
You need to use getline instead of the >> operator in your load-game function.
Instead of doing file >> player_name do getline(file, player_name)
This should be used in replacement of every occurrence of file >> someVar
EDIT: I didn't realize the others were integer values. For those you should still be using the >> operator.

Writing files with fstream

I'm trying to create a simple program that accepts user input and writes it to a text file.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main(){
string name; int score; fstream scoreSheet;
scoreSheet.open("score_sheet.txt");
string stayOpen = "y";
while(stayOpen == "y"){
scoreSheet >> name >> score;
cout << "Do you want to add another entry? (y/n) ";
cin >> stayOpen;}
scoreSheet.close();
return 0;}
When this is run no file is created in the directory except for a gmon.out. Why isn't the file created and how do I write user input to the file?
For creating file and write into that file, you have to specify mode in open function.
And also you have to scan data every time when you give Yes for write data into file.
Below is updated code.Hope this will solve your problem.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string name ; int score; fstream scoreSheet;
scoreSheet.open("path to ur file", fstream::out | fstream::app );
string stayOpen = "y";
while(stayOpen == "y")
{
cout<<"Enter new entry for name and score"<<endl;
cin >> name >> score;
scoreSheet << name << score;
cout << "Do you want to add another entry? (y/n) ";
cin >> stayOpen;}
scoreSheet.close();
return 0;
}
You need to do >> with cin or some file that exists. And the >> operator when used with scoreSheet should be a << since you are trying to write to a stream not reading from it. Also you should consider changing fstream to ofstream since you want to write to a file
Files are created when you open them as output, and not as input.
When you are going to read data from a file into your variables, the file should already be there (otherwise, where should the data come from?).
On the other hand, if you want to write data into your file, and therefore open it in the write mode, then the file will be created if it does not already exist.
You should use ofstream if you want the file stream to be written to. Also as others have commented, to write to the file, you need to get the content from somewhere else, like from console input or another file for input. Try the following code as a guide. Also you can take a look at fstream or any decent book on this topic (e.g., C++ Primer Chapter 8)
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main(){
string name; int score;
fstream scoreSheet("score_sheet.txt", fstream::out);
// Only proceed if file opened successfully
if (scoreSheet) {
string stayOpen = "y";
while(stayOpen == "y"){
cin >> name >> score;
fstream << name << score << "\n";
cout << "Do you want to add another entry? (y/n) ";
cin >> stayOpen;
}
scoreSheet.close();
}
return 0;
}

Writing to a file with fstream and cstring

#include <fstream>
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char filename[20] = "filename";
char userInput;
ofstream myFile;
cout << "Enter filename: ";
cin.getline(filename, sizeof(filename));
myFile.open(filename);
if(myFile.fail())
{
cout << "Error opening file: "
<< filename << "\n";
return 1;
}
cout << "Add text to the file: ";
cin.get(userInput);
while(cin.good() && userInput)
{
myFile.put(userInput);
cin.get(userInput);
}
myFile.close();
return 0;
}
Im having trouble terminating the input without force quiting it(It still writes to the file).
This is what I am supposed to do
Receives a line of input from the user, then outputs that
line to the given file. This will continue until the line input
by the user is “-1” which indicates, the end of input.
however I cannot work out the -1 part. Any help would be greatly appreciated everything else seems to work.
You're making things a bit more complicated than they need to be. Why C strings instead of std::string, for example? Using the right (standard-provided) classes generally leads to shorter, simpler and easier-to-understand code. Try something like this for starters:
int main()
{
std::string filename;
std::cout << "Enter filename" << std::endl;
std::cin >> filename;
std::ofstream file{filename};
std::string line;
while (std::cin >> line) {
if (line == "-1") {
break;
}
file << line;
}
}
First of all, the assignment asks to read a line from the user, character-wise input by get() shouldn't be the function to use. Use the member function getline() as you did to recieve the file name and use a comparison function to check against -1:
for (char line[20]; std::cin.getline(line, sizeof line) && std::cin.gcount(); )
{
if (strncmp(line, "-1", std::cin.gcount()) == 0)
break;
myFile.write(line, std::cin.gcount());
}

C++ read text file from command line ... send create .txt with responding info

sorry im real new to c++ and can't seem to understand the basic concept of reading a txt file and writing one. i have a program that currently just prompts the users and then delivers the output on the command line after reading the data. but i want to have it read a file, and the create a file with its output
heres it so far
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Enter number of names \n";
int a;
cin >> a;
string * namesArray = new string[a];
for( int i=0; i<a; i++) {
string temp;
cin >> temp;
namesArray[i] = temp;
}
for( int j=0; j<a; j++) {
cout << "hello " << namesArray[j] << "\n";
}
return 0;
}
Thanks to all..
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
int main(){
string fileName = "test.txt";
//declare a file object
//options are:
//ofstream for output
//ifstream for input
//fstream for both
fstream myFile;
//cannot pass a c++ string as filename so we convert it to a "c string"
//... by calling strings c_str member function (aka method)
//the fstream::out part opens the file for writing
myFile.open(fileName.c_str(), fstream::out);
//add the text to the file end the line (optional)
myFile << "Some text" << endl;
myFile.close();//always close your files (bad things happen otherwise)
//open the file for reading with fstream::in
myFile.open(fileName.c_str(), fstream::in);
string myString;
//get a line from a file (must be open for reading)
getline(myFile,myString);
myFile.close();//always close your file
//demonstrates that it works
cout << myString;
}
This a sample of reading a file or This example to write to a file to do what you are asking, if you want to know what are you doing, the << and >> operators, are like water valve that let you move the stream of information from side to side, "cin" is a "data generator", from keyboard, in the example in the page, "myReadFile.open" make a "data generator" from an input file, and you move that data using >> to save it to a string and << to move it to cout, dont know if it help you understand a little more of C++ streams...
ifstream input;
input.open("inputfile.txt");
input >> var; //stores the text in the file to an int or string
input.close();
ofstream output;
output.open("outputfile.txt"); //creates this output file
output << var; //writes var to the output file
output.close();
hope that helps