Read input from a file, capitalize first letter, m

2020-04-14 09:43发布

问题:

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?

回答1:

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 . . .



回答2:

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;
}