pansoh pansoh - 1 month ago 31
C++ Question

A program that will correct a C++ program that has errors in the operator

Write a program that will correct a C++ program that has errors in which operator,

<<
or
>>
, it uses with
cin
and
cout
. The program replaces each (incorrect) occurrence of

cin <<

with the corrected version
cin >>


and each (incorrect) occurrence of
cout >>

with the corrected version
cout <<


Allow for the possibility that there may be any number of whitespace characters (one or more) between
cin
and
<<
and between
cout
and
>>
. The replacement corrected version has only one blank between the
cin
or
cout
and the following operator.

Your program should get the source filename as an input from the user. The corrected version should be output to a file with name
corrected.txt
and it should also be displayed on the terminal. That means output of your program (after getting the filename) should be exactly same as the contents of the file
corrected.txt
. Your program should define a function that is called with the input- and output-file streams as arguments.

There are no compile errors for the code. However, the code output's nothing (The file exists). Also the words in the file will disappear after I compile the program. Can anyone give me some advice? Thanks!

#include <stdio.h>
#include <iostream>
#include <iomanip>
#include <cctype>
#include <fstream>
#include <string>
using namespace std;

void print(ifstream& input,ofstream& output, char next)
{

input.get(next);
cout << next;
output.put(next);

while(input >> next)
{
if(next=='c')
{
output.put(next);
cout << next;
input.get(next);

if(next=='i')
{ output.put(next);
cout << next;
input.get(next);


if(next=='n')
{
output.put(next);
cout << next;
while(next==' ')
{
input.get(next);
}
output.put(' ');
if(next=='<')
{

input.get(next);

if(next == '<')

{
cout << ">>";
input.get(next);

}
else
{
output.put(next);
cout << next;
}
}
else
{
output.put(next);
cout << next;
}
}

else
{
output.put(next);
cout << next;
}
}

else if (next=='o')
{
output.put(next);
cout << next;
input.get(next);

if(next=='u')
{
output.put(next);
cout << next;
input.get(next);


if(next=='t')
{
output.put(next);
cout << next;
while(next==' ')
{
input.get(next);
}
output.put(' ');
if(next=='>')
{

input.get(next);

if(next == '>')

{
cout << "<<";
input.get(next);

}
else
{
output.put(next);
cout << next;
}

}
else
{
output.put(next);
cout << next;
}

}
else
{
output.put(next);
cout << next;
}
}

else
{
output.put(next);
cout << next;
}
input.get(next);
}

}

}
}

int main()
{
ifstream input;
ofstream output;
char next;
char filename[16];
cout << "Enter filename:" << endl;
cin >> filename;
input.open(filename);
if(input.fail()) {
cout << "Could not open the file " << endl;
exit(0);
}
output.open("original.txt");

if (output.fail()) {
cout << "Could not open the file " << filename << endl;
exit(1);
}
print(input, output, next);

input.close();
output.close();

return 0;
}

Answer

I can't explain this in a comment. Please don't judge this too harshly:

void print(ifstream& input,ofstream& output)
{
    bool first = true;
    std::string command;
    while(std::getline(input, command, ';'))
    { // loop until no more input to read or input fails to be read
        if (command.find("cin")!= std::string::npos)
        { // found cin somewhere in command. This is too crude to work. See below
            size_t pos = command.find("<<"); // look for the first <<
            while (pos != std::string::npos)
            { // keep replacing and looking until end of string
                command.replace(pos, 2, ">>"); // replace with >>
                pos = command.find("<<", pos); // look for another 
            }
        }
        else if (command.find("cout")!= std::string::npos)
        { // same as above, but other way around
            size_t pos = command.find(">>"); 
            while (pos != std::string::npos)
            {
                command.replace(pos, 2, "<<");
                pos = command.find(">>", pos);
            }
        }
        if (! first)
        {
            output << ';' << command; // write string to output
        }
        else
        {
            first = false;
            output << command; // write string to output
        }
    }
}

This will catch and correctly handle MOST cases. What it can't deal with is:

Stuff like

cout << Cincinnati; // find is just too dumb. Regex is not
           ^ finds a cin right here and starts reversing <<

Comments

/* cout >> hah ha ha Sucker!!!; */

String literals

std::string fail = "cout >> Got you again!!!";

[expletive deleted] macros

#define evil cout >\
> "Gotcha!!!";

And really odd stuff like

cout << vector<vector<int>>(42)[0];
                         ^ Muhuhahahahahaha!!!

To do this right, you need a non-trivial state machine that can detect and eliminate the above failure cases.