0

beginner in c++ here... im making a multiple txt file to being read, it is testAnswers and CorrectAnswers

inside testAnswers is:

S1234 A B D C C C D A D D
S2345 A C D A A B D C A A
S3456 C A A A C C D D B B
S4567 A B B B B A B C C D
S5678 B C C B A A B C C D
S6789 A B B C C A B A C C
S7890 C B A A D A C A A C
S8912 A D A D A C C B A C
S9123 B C C A A C D B B A
S1928 B C C A A B A D B B
S2938 A B D C B D B D A A
S3847 C B D C C C B D A B 

inside CorrectAnswers is: A C D A A B B D C D

here the code i do

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main(int argc, char** argv) {
    ifstream inputStream1, inputStream2;
    ofstream outputStream;
    
    inputStream1.open("testAnswers.txt");
    inputStream2.open("CorrectAnswers.txt");
    outputStream.open("outputAnswers.txt");
    string name, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1;
    string a2, b2, c2, d2, e2, f2, g2, h2, i2, j2;
    string id;
    
    while(inputStream1 >> name >> a1 >> b1 >> c1 >> d1 >> e1 >> f1 >> g1 >> h1 >> i1 >> j1){
    }
    
    while(inputStream2 >> a2 >> b2 >> c2 >> d2 >> e2 >> f2 >> g2 >> h2 >> i2 >> j2){
    }
        
    cout << "id: ";
    cin >> id;
    
    if(id == name){
        
            if(a1==a2){
                num+=1;
            }
            if(b1==b2){
                num+=1;
            }
            if(c1==c2){
                num+=1;
            }
            if(d1==d2){
                num+=1;
            }
            if(e1==e2){
                num+=1;
            }
            if(f1==f2){
                num+=1;
            }
            if(g1==g2){
                num+=1;
            }
            if(h1==h2){
                num+=1;
            }
            if(i1==i2){
                num+=1;
            }
            if(j1==j2){
                num+=1;
            }
    }
    cout << num << endl;
    outputStream << num << endl;


    inputStream1.close();
    inputStream2.close();
    outputStream.close();
    
    return 0;
} 

ABCD is an answer. example, User S1234 is answers A B D C C C D A D D. if we compared CorrectAnswers, he got 3 correct

thats what it should be happen. but the code only can read the last User only, S3847. im using while(input) because im assume it will read line by line but it not.

how can i make the code read each line from above first?

zxc
  • 11
  • 1
    Does this answer your question? [Read file line by line using ifstream in C++](https://stackoverflow.com/questions/7868936/read-file-line-by-line-using-ifstream-in-c) – atin Dec 26 '20 at 08:48
  • What end-of-line characters does your file-format use? `\r\n`, `\n`, `\r` (if you're using old-school MacOS 9 or earlier) or something else (e.g. `U+0085`)? If you use C++'s built-in line-handling it will only match the end-of-line characters used by your platform, which won't necessarily match those in the file. – Dai Dec 26 '20 at 08:48
  • 3
    You read from `inputStream1` and `inputStream2`, but you never save the data you read from the streams. Only the last successful read from those streams will be stored in the variables. Perhaps you should take some time to read about *structures* and *arrays* as a possible way to solve the problem? – Some programmer dude Dec 26 '20 at 08:49
  • You also never check for `name` in the loop, so it will not find the correct "line" unless the `id` is the same as the last record in the file. You need to rethink your design. – Some programmer dude Dec 26 '20 at 08:51

1 Answers1

0

Let me try to help you.

First we will look at your program and comment on it.

using namespace std;

you should not open the complete standard namespace. You will find many many comments here on SO recommending that. So, please omit that line an use qualified names everywhere (like std::string)


ifstream inputStream1;
inputStream1.open("testAnswers.txt");

You can and should do this in one line. The iostreams have a constructor, taking the filename. Additionally, you should always check the result of any IO operation. This you can simply do with an if (inputStream1), because the bool and the !-operator for iostreams are overloaded and return the state of stream. And, you should not use hardcoded string literals, please use const std::strings instead and store the file name. Last, but not least, we will use the if-statement with initializer to prevent the pollution of the outer name space. You should always try to narrow the scopy of your variable as much as possible. The resulting statement for opening a file will be:

if (std::ifstream correctAnswersStream{ fileNameCorrectAnswers }; correctAnswersStream) {

Another big advantage is that the iostreams destructor will close the file automatically for you, when they "fall" out of scope. So, no need for a close-statement.


Then you define tons of string variables. First strong recommendation: Please always initialize all variables. Use the {} for default initialization. Ant, if you have many variables with the same meaning, you should put them in a ```std::vector. If you have variables that logically belong together, the put them in a struct(class````). for example like:

std::vector<std::string> answer{};

of for a struct something like that:

struct Test {
    std::string name{};
    std::vector<std::string> answer{};
};

And then you would define methods to operate on your data. At least you could overwrite the inserter (<<) and the extractor (>>) operator for simple io operations. Only the class (struc) should know, how to read write data, not the outer world.

So you could for example add a simple inserter like the belo:

struct Correct {
    std::vector<std::string> answer{};

    // Overwrite inserter. Show all data
    friend std::ostream& operator << (std::ostream& os, const Correct& c) {
        std::copy(c.answer.begin(), c.answer.end(), std::ostream_iterator<std::string>(os, " "));
        return os;
    }
};

Now let's look at you next statement and the main source of your problems:

while(inputStream1 >> name >> a1 >> b1 >> c1 >> d1 >> e1 >> f1 >> g1 >> h1 >> i1 >> j1){
    }

You use a while-loop to read you variables, but, the problem is that you do nothing in the loop body. YOu read the variables, but not store their value in a std::vector or somehwere else. And then, during the next loop run, all preiviously read values will be overwritten with the new vales and their old content will be lost. And when the loop finishes, you will have the values of the last line in your varaibles, because you have overwritten and discarded all previously read values. That needs to changed.

Store the contents of the variables somewhere.

This you need to do for both input files. Then you can compare verything with everything else.

You will find out that you need somehow a 2 dimensional container. Or, a std::vector for your own struct which again contains another std::vector.

Because I want to help you, but not do your homework, I will add an example program using a little bit more sophisticated coding style. With that you can understand the logic, but most certainly not some of the more advanced stuff.

However, of course the following will work:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>

struct Correct {
    std::vector<std::string> answer{};

    friend std::istream& operator >> (std::istream& is, Correct& c) {
        // Read a complete line and check, if that worked
        if (std::string line{}; std::getline(is, line)) {

            // Put line into an istringstream for easier extraction
            std::istringstream iss(line);

            // CLear all old data from vector
            c.answer.clear();

            // Copy all  answers from file into internal vector
            std::copy(std::istream_iterator<std::string>(iss), {}, std::back_inserter(c.answer));

        }
        return is;
    }
    // Overwrite inserter. Show all data
    friend std::ostream& operator << (std::ostream& os, const Correct& c) {
        std::copy(c.answer.begin(), c.answer.end(), std::ostream_iterator<std::string>(os, " "));
        return os;
    }

};
struct Test {
    std::string name{};
    std::vector<std::string> answer{};

    friend std::istream& operator >> (std::istream& is, Test& t) {

        // Read a complete line and check, if that worked
        if (std::string line{}; std::getline(is, line)) {

            // Put line into an istringstream for easier extraction
            std::istringstream iss(line);

            // Try to extract the name
            if (iss >> t.name) {

                // Clear all old data from vector
                t.answer.clear();
                // Copy all  answers from file into internal vector
                std::copy(std::istream_iterator<std::string>(iss), {}, std::back_inserter(t.answer));
            }
        }
        return is;
    }
    // Overwrite inserter. Show all data
    friend std::ostream& operator << (std::ostream& os, const Test& t) {
        std::copy(t.answer.begin(), t.answer.end(), std::ostream_iterator<std::string>(os, " "));
        return os;
    }
};

const std::string fileNameTestAnswers{ "r:\\testAnswers.txt" };
const std::string fileNameCorrectAnswers{ "r:\\CorrectAnswers.txt" };
const std::string fileNameResult{ "r:\\outputAnswers.txt" };

int main() {

    // Open file with test answers and check, if it could be opened
    if (std::ifstream testAnswersStream{ fileNameTestAnswers }; testAnswersStream) {

        // Open file with correct answers and check, if it could be opened
        if (std::ifstream correctAnswersStream{ fileNameCorrectAnswers }; correctAnswersStream) {

            // Open file for the resulting output
            if (std::ifstream resultAnswersStream{ fileNameCorrectAnswers }; resultAnswersStream) {

                // Now all the files are open and we can start. Try to read all files
                std::vector<Correct> correct{};
                std::vector<Test> test{};
                
                // Read files
                std::copy(std::istream_iterator<Correct>(correctAnswersStream), {}, std::back_inserter(correct));
                std::copy(std::istream_iterator<Test>(testAnswersStream), {}, std::back_inserter(test));

                // Inform user that he has to enter a name
                std::cout << "\nPlease enter a name for checking the results:\n";

                // Read the name
                if (std::string searchName{}; std::getline(std::cin, searchName)) {

                    // Search the input search name in our test vector
                    // Goto all tests, because maybe the name is in the file several times
                    for (auto record{ std::find_if(test.begin(), test.end(), [&searchName](const Test& t) { return t.name == searchName; }) };
                        record != test.end();
                        record = std::find_if(std::next(record), test.end(), [&searchName](const Test& t) { return t.name == searchName; })) {

                        // So go through all the records that contain the search names and compare with all answers
                        for (const auto& co : correct) {
                            size_t okCounter{};
                            for (size_t r{}, c{}; r < record->answer.size() && c < co.answer.size(); ++r, ++c) {
                                if (record->answer[r] == co.answer[c]) ++okCounter;
                            }
                            // Incase there was a match, show result
                            if (okCounter > 0U)
                                std::cout << "\nName:\t\t " << searchName << "\nGiven answer:\t " << *record << "\nCorrect answer:\t "
                                << co << "\nNumber matches:\t " << okCounter;
                            std::cout << "\n\n";
                        }
                    }
                }
                else std::cerr << "\n\nError while reading search name files\n\n";
            }
            else std::cerr << "\n\nError: Could not open file '" << fileNameResult << "'\n\n";
        }
        else std::cerr << "\n\nError: Could not open file '" << fileNameCorrectAnswers << "'\n\n";
    }
    else std::cerr << "\n\nError: Could not open file '" << fileNameTestAnswers << "'\n\n";
    return 0;
}

A M
  • 14,694
  • 5
  • 19
  • 44