Write multiple lines to a text file and Read the file with all the characters reversed

Hi guys i'm trying to write a programme as follow:

Write a program that:
1) Prompt the user to enter a file name to save the inputs.
2) Prompt the user to enter information/statements.
3) Save the information/statements entered by user to the file name given early.
4) Close the file.
5) Reopen the input file
6) Read all info from the file.
7) Reverse all characters from the reading.
8) Prompt the user to enter a file name to save the outputs.
9) Write the reversed results to the file.
Do not use reverse function provided in the algorithm header file.

Suppose the user specifies input.txt and output.txt when prompted for the file names

Below is my current progress, I am able to transfer the user input to the text file but what if the user wants to input multiple lines, my programme can only transfer it in one line, also how can i stop the user input when a specific character is entered?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
	string input_file, output_file;
	char statement[100];

	do {
		cout << "Please enter a file name for input file : " << flush;
		cin >> input_file;

		if (input_file != "userinput") {
			cout << "File name unavailable!" << endl;
		}
	} while (input_file != "userinput");
	ofstream userinput("input.txt");

	cout <<"Please enter your information/statement (Enter a dot to stop) :"<< flush;
	
	do{
	cin.getline(statement,100);
	userinput << statement << " " << flush;
	}while(statement != ".");


}
Hello imyourjoy,

To start with line 8 should be a "std::string" not a character array.

Lines 11 and 12 should be done before the do/while loop and it should be an output file nor input.

The do/while loop should be getting user input from the keyboard and saving it to a file.


You need to follow your instructions better along with a bit of planning before you start to code.

Right now the code makes no sense because things are out of order.

Andy
Thank you for your respond Andy,

The reason why I did line 11 and 12 in the do while loop is because I want the user to keep on re-entering the file name until they get it correct.
Hello imyourjoy,

I understand your point, but you should be asking for the output file name not the input file name. The second problem is that you do not show what files are available, so how would a user know what to enter?

Lastly you open an "ofstream" using a constant string when you should be using the variable "output_file".

The name "userinput" for the "ofstream" is very misleading.

I was also wondering if you can use a vector yet?

I would start with step 1 first then steps 2 and 3 tend to go together. Finish with step 4 when 2 and 3 are finished.

Get that much of the program working first then the rest will be a lot easier.

Andy
Assuming that 7) means reverse all the contents of the file and without using std::reverse() consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <fstream>
#include <iostream>
#include <string>

int main()
{
	std::string savinp;

	std::cout << "Enter file name to save input to: ";
	std::getline(std::cin, savinp);

	std::ofstream ofs(savinp);

	if (!ofs)
		return (std::cout << "Cannot open file\n"), 1;

	for (std::string line; std::cout << "Please enter information line (CR to terminate): " && std::getline(std::cin, line) && !line.empty(); ofs << line << '\n');
	ofs.close();

	std::ifstream ifs(savinp);

	if (!ifs)
		return (std::cout << "Cannot open file\n"), 2;

	std::string data;

	for (std::string line; std::getline(ifs, line); data += line + '\n');

	const std::string reverse {data.rbegin() + 1, data.rend()};

	std::string revinp;

	std::cout << "Enter file name to save reverse to: ";
	std::getline(std::cin, revinp);

	std::ofstream rfs(revinp);

	if (!rfs)
		return (std::cout << "Cannot open file\n"), 3;

	rfs << reverse << '\n';
}



Enter file name to save input to: inputline.txt
Please enter information line (CR to terminate): qwe
Please enter information line (CR to terminate): asd
Please enter information line (CR to terminate): zxc
Please enter information line (CR to terminate):
Enter file name to save reverse to: inputrev.txt

c:\MyProgs>type inputrev.txt
cxz
dsa
ewq

Last edited on
Thank you seeplus,
is it possible to achieve something as below

user input:
qwe
asd
zxc

reversed:
ewq
dsa
cxz

only characters on each line are reversed but not the whole file
Of course. Consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <fstream>
#include <iostream>
#include <string>

int main()
{
	std::string savinp;

	std::cout << "Enter file name to save input to: ";
	std::getline(std::cin, savinp);

	std::ofstream ofs(savinp);

	if (!ofs)
		return (std::cout << "Cannot open file\n"), 1;

	for (std::string line; std::cout << "Please enter information line (CR to terminate): " && std::getline(std::cin, line) && !line.empty(); ofs << line << '\n');
	ofs.close();

	std::ifstream ifs(savinp);

	if (!ifs)
		return (std::cout << "Cannot open file\n"), 2;

	std::string revinp;

	std::cout << "Enter file name to save reverse to: ";
	std::getline(std::cin, revinp);

	std::ofstream rfs(revinp);

	if (!rfs)
		return (std::cout << "Cannot open file\n"), 3;

	for (std::string line; std::getline(ifs, line); )
		rfs << std::string {line.rbegin(), line.rend()} << '\n';
}

Thank you see plus and Andy for your help, this is my final solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <fstream>
#include <iostream>
#include <string>

using namespace std;

int main() {
	string inputfile_name;
	cout << "Please enter a file name for input file: ";
	cin >> inputfile_name;
	ofstream ofs(inputfile_name);

	string statement;
	cout << "Please enter your information/statements (Enter a dot to stop) : ";

	while (getline(cin, statement)) {
		if (statement.empty()) {
			continue;
		} else {
			ofs << statement << endl;
		}
		if (statement[statement.length() - 1] == '.') {
			break;
		}
	}

	ofs.close();

	ifstream ifs(inputfile_name);

	string outputfile_name;
	cout << "Please enter a file name for output file: ";

	cin >> outputfile_name;

	ofstream rfs(outputfile_name);

	for (string line; getline(ifs, line);) {
		string reverse { line.rbegin(), line.rend() };
		rfs << reverse << '\n';
	}

	rfs.close();
	ifstream dfs(outputfile_name);

	cout << "\nThe reversed information/statements is : " << endl;
	string reversed_line;
	while (getline(dfs, reversed_line)) {
		cout << reversed_line << "\n";

	}
}
Hello imyourjoy,

Your while loop may not work the way that you want. There is a good chance it will only accept 1 line of input.

Put your-self in the users point of view. Entering a line of type and ending it with a period is normal for most people, so checking for a period on each pass of the while loop is more likely to end the loop before its time. As you will see in the following code it would be better to check for an empty string.

This is a suggestion of what you could do and in some what you need to do:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <fstream>
#include <iostream>
#include <limits>  // <--- Added.
#include <string>

using namespace std;

int main()
{
    string io_file_name{ "Work.txt" }; // <--- "{ "Work.txt" }" Used for testing. Comment or remove when finished. OK if you leave.

    // <--- Next 2 lines commented for testing. Uncomment when finished.
    //cout << "\n Please enter a file name for output of your work: ";
    //std::getline(std::cin, io_file_name);  // <--- Should use "std::getline" here. Not formatted input of "cin >> io_file_name;"

    // <--- Use after formatted input. Not needed if "std::getline" is used.
    //std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.

    ofstream outFileWork(io_file_name);

    if (!outFileWork)
    {
        std::cerr << "\n     File \"" << io_file_name << "\" did not open\n";

        return 1;
    }

    string statement;

    cout << "\n Please enter your information/statements (Enter a blank line to stop):\n> ";

    while (getline(cin, statement))
    {
        if (statement.empty())
        {
            break;
        }

        outFileWork << statement << '\n';

        std::cout << "> ";
    }

    outFileWork.close();

    ifstream inFile(io_file_name);

    if(!inFile)
    {
        std::cerr << "\n     File \"" << io_file_name << "\" did not open\n";

        return 2;
    }

    string outputfile_name;

    cout << "\n Please enter a file name for output file: ";
    cin >> outputfile_name;

    ofstream outFileRev(outputfile_name);

    if (!outFileRev)
    {
        std::cerr << "\n     File \"" << outputfile_name << "\" did not open\n";

        return 3;
    }

    cout << "\nThe reversed information/statements is:\n";

    for (string line; getline(inFile, line);)
    {
        string reverse{ line.rbegin(), line.rend() };

        outFileRev << reverse << '\n';

        cout << reverse << "\n";  // <--- Done here you do not need the next input file stream and the for loop.
    }

    outFileRev.close();

    return 0;
}

I changed some of the variable names to give you an idea of how the program is easier to read and follow. What you have works, so changing is not really necessary.

Notice the revised while loop. This allows for multiple lines to be entered even if they end with a period.

In you above code lines 44 - 48 are not needed if you move line 49 to after line 40. What you write to the file can easily be written to the screen with out having to read the file just created.

See what you think.

Andy
Topic archived. No new replies allowed.