Something is definitely wrong with my loop because after reading and executing the first line the programs ends.
if (infile.is_open())
{
cout << "Input filename: ";
cin>>filename;
infile.open(filename.c_str());
cout<< "Output filename: ";
cin>>filename;
outfile.open(filename.c_str());
while(getline(infile,input))
{
string output = "";
for(int x = 0; x < input.length(); x++)
output += cipher(input[x]);
cout<<output<<endl;
outfile<<output;
}
}
Any suggestions on how to make this work?
EDIT
Followed the suggestions and got this:
if (infile.is_open()) {
cout << "Input filename: ";
cin>>filename;
infile.open(filename.c_str());
if (!infile.is_open())
{
std::cout << "Failed to open the input file." << std::endl;
return -1;
}
cout<< "Output filename: ";
cin>>filename;
outfile.open(ofilename.c_str());
if (!outfile.is_open())
{
std::cout << "Failed to open the output file." << std::endl;
return -1;
}
while(getline(infile,line)){
string output = "";
for(int x = 0; x < input.length(); x++) {
output += cipher(input[x]);
}
}
BUT it still reads only the first line...everything else is working perfectly fine....just can't read anything beyond the first line..
It seems that you misunderstood the point of the fstream's is_open() method, since this code:
if (infile.is_open())
{
cout << "Input filename: ";
cin>>filename;
infile.open(filename.c_str());
...
}
checks whether the infile has been successfully opened (i.e. if either a previous call to member open succeeded or if the object was successfully constructed using the parameterized constructor,
and close has not been called since) and in case it is open it retrieves the name of the input file from cin and opens the file.
Good start would be the program that reads from the input file line by line and writes these lines to the output file without processing them:
// retrieve the name of the input file and open it:
cout << "Input filename: ";
cin>>filename;
infile.open(filename.c_str());
if (!infile.is_open())
{
std::cout << "Failed to open the input file." << std::endl;
return -1;
}
// retrieve the name of the output file and open it:
cout << "Output filename: ";
cin >> filename;
outfile.open(filename.c_str());
if (!outfile.is_open())
{
std::cout << "Failed to open the output file." << std::endl;
return -1;
}
std::string line;
while(getline(infile,line))
{
std::cout << line << std::endl;
outfile << line;
}
So I suggest this.
Write char cipher(char ch) to return enciphered input for anything. if you don't want to encipher whitespace, then don't. But always return the enciphered character or unmodifed character.
Use std::transform , std::istream_iterator , and std::ostream_iterator to transform your input and output files.
Check your file states at the correct times.
An example appears below:
#include <iostream>
#include <fstream>
#include <iteraor>
#include <string>
using namespace std;
char cipher(char ch)
{
if (std::isalpha(ch))
{
// TODO: change ch to whatever you want here.
}
// but always return it, whether you changed it or not.
return ch;
}
int main()
{
int res = EXIT_SUCCESS;
string in_filename, out_filename;
cout << "Input filename: ";
cin >> in_filename;
cout << "Output filename: ";
cin >> out_filename;
// don't skip whitespace
ifstream infile(in_filename);
ofstream outfile(out_filename);
if ((infile >> noskipws) && outfile)
{
std::transform(istream_iterator<char>(infile),
istream_iterator<char>(),
ostream_iterator<char>(outfile),
cipher);
}
else
{
perror("Failed to open files.");
res = EXIT_FAILURE;
}
return res;
}
Related
I am supposed to ask the user for two file names (input and output files). The contents from the input file should be read and the first letter of each sentence should be made uppercase while every other letter should be made lowercase. The results should then be stored in the output file.
I am aware that there are ways of using the toupper and tolower functions that include pointers, arrays, or even ASCII values of chars but I am trying to get this code to work by using if/else and while statements, as well as boolean statements. I have had various results ranging from all the letters being capitalized to none of the letters being capitalized however, I think right now I am on the right track with the code and am just overlooking the way I am incrementing through the characters causing the code to not capitalize after a period and a space.
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
int main() {
string input_file; // To hold input file name
string output_File; // To hold output file name
char ch; // To hold character
fstream inputFile;
fstream outputFile;
bool new_sentence = true;
cout << "Enter input file name: " << endl;
cin >> input_file;
cout << "Enter output file name: " << endl;
cin >> output_File;
outputFile.open(output_File, ios::out);
inputFile.open(input_file, ios::in);
if (inputFile) {
while (inputFile.get(ch)) {
if (isprint(ch)) {
if (new_sentence) {
outputFile.put(toupper(ch));
}
else {
outputFile.put(tolower(ch));
}
new_sentence = false;
}
else {
if (ch == '.') {
new_sentence = true;
outputFile.put(ch);
}
}
}
inputFile.close();
outputFile.close();
}
else {
cout << "Cannot open file(s)." << endl;
}
cout << "\nFile conversion complete." << endl;
return 0;
}
With my current code I am able to capitalize the first letter of the first sentence and make every other letter lowercase. I am able to store and show the results in the output file. My issue is that the first letter of every other sentence after the first one won't change to uppercase. This makes me think the issue is in this part of the code:
if (new_sentence)
{
outputFile.put(toupper(ch));
}
else
{
outputFile.put(tolower(ch));
}
Am I missing something here?
You have a minor logical error.
You first need to check, if the character is a period. This state you need to remember. If then a next character isalpha, then we check, if recently the newsentence flag has been set. In this case, and only in this case, we reset the new sentence flag and convert the character to uppercase.
All other alpha characters will be converted to lowercase. Other charcaters will not be converted.
In your solution you always reset the newsentence flag. Even, if the next print character is a space (Which is most liekly the case).
Please see updated solution:
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
int main() {
string input_file; // To hold input file name
string output_File; // To hold output file name
char ch; // To hold character
fstream inputFile;
fstream outputFile;
bool new_sentence = true;
cout << "Enter input file name: " << endl;
cin >> input_file;
cout << "Enter output file name: " << endl;
cin >> output_File;
outputFile.open(output_File, ios::out);
inputFile.open(input_file, ios::in);
if (inputFile) {
while (inputFile.get(ch)) {
if (ch == '.') {
new_sentence = true;
}
if (isalpha(ch)) {
if (new_sentence) {
ch = toupper(ch);
new_sentence = false;
}
else {
ch = tolower(ch);
}
}
outputFile.put(ch);
}
inputFile.close();
outputFile.close();
}
else {
cout << "Cannot open file(s)." << endl;
}
cout << "\nFile conversion complete." << endl;
return 0;
}
And then, please see some further improvements:
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
int main() {
// Will hold the input and output filename
std::string filename;
// This is our flag to indicate that a new sentence will come
bool newSentence = true;
// Get input filename
std::cout << "Enter input file name: " << "\n";
std::cin >> filename;
// And try to open the file
std::ifstream inFile(filename);
std::cout << "Enter output file name: " << "\n";
std::cin >> filename;
// And try to open the file
std::ofstream outFile(filename);
// Only convert, if the input and output file could be opened
if (inFile && outFile) {
char ch;
while (inFile.get(ch)) {
if (ch == '.') {
newSentence = true;
}
if (isalpha(ch)) {
if (newSentence) {
ch = toupper(ch);
newSentence = false;
}
else {
ch = tolower(ch);
}
}
outFile.put(ch);
}
}
else {
std::cout << "Cannot open file(s)\n";
}
std::cout << "\nFile conversion program complete\n";
return 0;
}
And the full blown "C++ with algorithm" solution. Here the conversion, or transformation is done in one statement
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <algorithm>
#include <iterator>
int main() {
// Will hold the input and output filename
std::string filename;
// Get input filename
std::cout << "Enter input file name: " << "\n";
std::cin >> filename;
// And try to open the file
std::ifstream inFile(filename);
std::cout << "Enter output file name: " << "\n";
std::cin >> filename;
// And try to open the file
std::ofstream outFile(filename);
// Only convert, if the input and output file could be opened
if (inFile && outFile) {
// Do the conversion
std::transform(
std::istreambuf_iterator<char>(inFile),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(outFile),
[newSentence = true](char c) mutable {
if (c == '.') newSentence = true;
if (std::isalpha(c))
if (newSentence) {
newSentence = false;
c = std::toupper(c); }
else c = std::tolower(c);
return c;
}
);
}
else {
std::cout << "Cannot open file(s)\n";
}
std::cout << "\nFile conversion program complete\n";
return 0;
}
But if the last solution adds additional value? I am not sure . . .
This part of your code should be changed:
// if (isprint(ch)) {
if (ch != '.') {
if (new_sentence) {
outputFile.put(toupper(ch));
}
else {
outputFile.put(tolower(ch));
}
new_sentence = false;
}
else {
new_sentence = true;
outputFile.put(ch);
}
std::isprint() only checks if the character is printable.
Full code:
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
int main() {
string input_file; // To hold input file name
string output_File; // To hold output file name
char ch; // To hold character
fstream inputFile;
fstream outputFile;
bool new_sentence = true;
cout << "Enter input file name: " << endl;
cin >> input_file;
cout << "Enter output file name: " << endl;
cin >> output_File;
outputFile.open(output_File, ios::out);
inputFile.open(input_file, ios::in);
if (inputFile) {
while (inputFile.get(ch)) {
if (ch != '.') {
if (new_sentence) {
outputFile.put(toupper(ch));
}
else {
outputFile.put(tolower(ch));
}
new_sentence = false;
}
else {
new_sentence = true;
outputFile.put(ch);
}
}
inputFile.close();
outputFile.close();
}
else {
cout << "Cannot open file(s)." << endl;
}
cout << "\nFile conversion complete." << endl;
return 0;
}
I need to delete all the occurencies of a string in a file.
I receive the text as a string and erase every occurencies.
After I deleted all the occurencies i don't know how to save the string back to the file.
I've tried to close the file and wit ofstream to write in it but it didn't work.
#include <iostream>
#include <fstream>
#include <string>
int main () {
std::string file_contents = "";
std::ifstream myfile ("text.txt");
char ch;
if (myfile.is_open())
{
// READ FILE CONTENTS AS STRING
while ( myfile >> std::noskipws >> ch)
{
file_contents += ch;
}
// DISPLAY STRING
std::cout << file_contents << '\n';
// GET WORD TO BE DELETED
std::string word;
std::cout << "Please enter word to be deleted: ";
std::cin >> word;
std::string::size_type found;
std::string new_text;
//DELETE WORD FROM STRING
bool ok=0;
do{
found = file_contents.find(word);
ok=1;
if (found!=std::string::npos)
{
std::cout << word << " found at: " << found << '\n';
file_contents.erase(found, word.length());
std::cout << file_contents << '\n';
}
else
ok==0;
new_text=file_contents;
}while(ok==1);
myfile.close();
}
else std::cout << "Unable to open file";
return 0;
}
Okay so you must close ifstream instance before proceeding to write to the file again.
After closing the file, modify the content and then open the same file for write using ofstream and simply write the content.
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::string file_contents = "";
std::ifstream myfile("text.txt");
char ch;
if (myfile.is_open())
{
// READ FILE CONTENTS AS STRING
while (myfile >> std::noskipws >> ch)
{
file_contents += ch;
}
myfile.close();
}
else {
std::cout << "Unable to open file";
return -1; // no need to continue if can't read it
}
// DISPLAY STRING
std::cout << file_contents << '\n';
// GET WORD TO BE DELETED
std::string word;
std::cout << "Please enter word to be deleted: ";
std::cin >> word;
//DELETE WORD FROM STRING
size_t found;
while ((found = file_contents.find(word)) != file_contents.npos)
{
std::cout << word << " found at: " << found << '\n';
file_contents.erase(found, word.length());
std::cout << file_contents << '\n';
}
// this will open in text mode and will replace all existing content
std::ofstream out("text.txt");
if (out.is_open()) {
out << file_contents;
out.close();
}
else {
std::cout << "Unable to open file for writing.\n";
return -2; // for failure to open for write
}
return 0;
}
Note: the loop you had went infinitely when I tried to execute it, I had to change it to the code shown above. Also, new_text is completely unnecessary, why have it?
The simpliest way is first to open as input stream. When finish open as output stream to write. It is not the only way you can do that.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
std::string file_contents = "";
{
std::ifstream myfile ("text.txt");
if (! myfile.is_open())
{
else std::cout << "Unable to open file";
return 1;
}
// READ FILE CONTENTS AS STRING
char ch;
while ( myfile >> std::noskipws >> ch) file_contents += ch;
myfile.close();
}
{
std::string word;
std::cin >> word; // GET WORD TO BE DELETED
std::string::size_type found;
while((found = file_contents.find(word))!=std::string::npos)
file_contents.erase(found, word.length());
std::ofstream myfile ("text.txt");
myfile << file_contents<< std::flush;
myfile.close();
}
return 0;
}
I'm working on the following problem:
I need to write a prgoram that reads an ASCII text file from the hard drive and allows the user to display and edit the contents of the file line-by-line.
It must have the following features:
It reads the file name from the standard output and opens the text file using a file stream.
When the file is loaded, the user enters the text line number.
If the line exists, it is displayed in the standard output.
If the line does not exist (the user has entered a line number
that is greater than the number of lines in the file), an error message is displayed,
for example: The line 82 does not exist. When the line is displayed the user is given
an option to enter a new string in the standard input that will become the contents of
the line. The string can contain blank spaces. Then the user is asked to enter another line number.
Finally, the user is asked whether he wants to save the changes in the file or not.
Technical requirements: The program must be composed by more than one function
This is my code so far:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
void printErrorMessage(int lineNumber)
{
cout << endl << " ERROR: The line " << lineNumber << " does not exist"
<< endl;
}
int main()
{
int line_number;
vector<string> TextVector;
int loop = 1;
fstream myfile;
myfile.open("test.txt", std::fstream::in | std::fstream::out);
while(loop == 1)
{
if (myfile.is_open())
{
// get end line of file.
cout << "File has opened successfully." << endl;
}
else
{
cout << "File hasn't opened successfully.";
return 0;
}
cout << "Enter the text line number:" << endl;
cin >> line_number;
size_t lines_count = 0;
string line;
while(getline(myfile, line))
{
TextVector.push_back(line); // push to text file
}
if(line_number > TextVector.size() + 1)
{
printErrorMessage(line_number);
return 0;
}
cout << TextVector[line_number] << endl;
cout << "If you'd like to change the line, please enter it, otherwise enter n to exit" << endl;
string changeLine;
getline(cin, changeLine);
if (changeLine == "n")
{
myfile.close();
return 0;
}
TextVector[line_number] = changeLine; // changes the line with the new string
cout << "Would you like to enter a new line to edit? (Y/n)" << endl;
string newLine;
cin >> newLine;
if (newLine != "y" && newLine != "Y")
{
cout << "Would you like to save all your changes to the file? (Y/n)" << endl;
string saveChanges;
cin >> saveChanges;
if (saveChanges != "y" && saveChanges != "Y")
{
myfile.close();
return 0;
}
for (int i = 0; i < TextVector.size() + 1; i++)
{
cout << TextVector[i] << endl;
myfile << TextVector[i] << endl;
myfile.flush();
}
myfile.close();
return 0;
}
}
return 0;
}
Technically I do save the changes to the vector, but for some reason I cannot get to overwrite the vector into the text file that already is full.
Also, any idea why the
getline(cin, changeLine);
Still acts as if it's a normal string? shouldn't it get the whole line entered togethe with the spaces?
Some guidance would really be appreciated!
string line;
string filename;
cout << "Please enter filename :" << endl;
cin >> filename;
ifstream myfile(filename);
/*cout << "Please enter the name of file that you write results : "<< endl;
cin >> wfile; */
if(myfile.is_open())
{
while(getline(myfile,line))
{
convert(line);
}
//getline(myfile,line);
//pushintoVector(line,buffer);
}
else
{
cout << "Error : File could not be opened" << endl;
}
try{
myfile.close();
myFile.close();
}catch(exception &e1)
{
cout << endl;
}
//system("PAUSE");
return 0;
After that i want to send current line to another function like:
void convert(string lines)
{
myFile.open("yazici.txt");
string buf;
string convertingnum;
istringstream ss(lines);
while(ss >> buf)
{
So how can i read word from a line and change it according to if-else structure and write it another file.Edit: Also is there a function or method to determine line length ?
Open the output file at the same time you open the input file.
Pass the output stream as an argument to convert instead of opening the file every time in the function.
Use better names than myfile and myFile.
ifstream inputFile(filename);
ofstream outputFile("yazici.txt");
if(inputFile.is_open())
{
while(getline(inputFile,line))
{
convert(outputFile, line);
}
}
and ...
void convert(std::ostream& outputFile,
string lines)
{
string buf;
string convertingnum;
istringstream ss(lines);
while(ss >> buf)
{
outputFile << buf << std::endl; //???
}
}
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// Main Routine
void main() {
char in;
string s,m;
fstream f;
// Open file
cout << "Positive Filter Program\n"<< endl;
cout << "Input file name: ";
cin >> s;
cout << "Output file name: ";
cin >> m;
f.open(s.data(),ios::in);
f.open(m.data(),ios::out);
// Loop through file
if(f.is_open())
{
while(f.good())
{
f.get(in);
f<<in;
cout << "\nFinished!"<< endl;
}
}
else cout << "Could not open file";
// Close file
f.close();
}
I am not sure what I am doing wrong here. In this program I am trying to cin the file name that would input, and then would output onto what file name that you typed in.
The same fstream object is being reused:
f.open(s.data(),ios::in);
f.open(m.data(),ios::out);
it will never read the input file. Change to:
std::ifstream in(s.data());
std::ofstream out(m.data());
The while loop is incorrect, the result of a read attempt should be checked immediately after the read:
char ch;
while(in.get(ch))
{
out << ch;
}
cout << "\nFinished!"<< endl; // Moved this to outside the while