Как отделить данные от файлового потока в c ++ - PullRequest
0 голосов
/ 15 февраля 2020

Я только начал изучать c ++ в колледже, и для нашего первого проекта нас попросили создать калькулятор из пяти функций (+, -, *, /,%), который считывает входные данные из файла, выполняет арифметическую операцию c над это и выводит его на экран. Мне дают входной файл, который, как и все числа, вот так:

/   100     10
109.5 +     1.0
25    /     2
25.5  /     2
0     /     0
8     *     8
10    -    10
ab    -    ab
100   -     1
10    *   -10
10.5  +  1000
1000  -  1.05
1000  *  1000
1000  /  1000
1000  /     0

Для моего кода это лучшее, что я смог придумать:

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>

using namespace std;
const string file_name = "input.txt";


float calculate_number (float first_number, char symbol, float last_number);

int main () {
    ifstream input_file;
    ofstream output_file;

    // Open file to get input_file from
    input_file.open(file_name, ios::in);

    // Error checking
    if (!input_file) {
        cout << "Error: file input.txt does not exists\n";
        exit(1);
    } else {

        string data_from_file;           // Declare string to store data from file
        input_file >> data_from_file;    // Pass file content to data

        while (getline(input_file, data_from_file)) {
            istringstream ss(data_from_file);

            char symbol;
            int first_number, last_number;

            ss >> first_number >> symbol >> last_number;
            cout << first_number << symbol << last_number << endl;
        }
    }

    return 0;
}

Приведенный выше код дает следующий вывод, который является беспорядком, но все же огромный шаг вперед:

10010
109.5
25/2
25.5
0/0
8*8
10-10
0-10
100-1
10*-10
10.5
1000-1
1000*1000
1000/1000
1000/0

Мой вопрос заключается в том, является ли способ отделить каждое число и арифметический оператор c от входного потока, сложите их вместе и отобразите вывод на экран. Заранее спасибо

Ответы [ 3 ]

0 голосов
/ 16 февраля 2020

Самый простой способ получить информацию из входного файла - извлечь ее, перебирая результаты, полученные из входного файла, и передавая ее в переменную для удобства обращения.


#include <iostream>
#include <string>
#include <fstream>

using namespace std;
const string INPUT_FILE = "input.txt";
const string OUTPUT_FILE = "result.txt";


// Global variables

float first_number, second_number, answer;
char arithemetic_op;
ifstream input_file;     // File to get input from
ofstream output_file;    // File to put result in

// function prototype

float calculate (float first_number, char arithemetic_op, float second_number);


int main () {

    // Open file to get input_file from
    input_file.open(INPUT_FILE, ios::in);

    // Error if file does not exists
    if (!input_file) {
        cout << "Error: file `input.txt` does not exists\n";
        exit(1);
    }


    while (input_file >> first_number >> arithemetic_op >> second_number) {
        answer = calculate(first_number, arithemetic_op, second_number);

        output_file.open(OUTPUT_FILE, ios::out);
        output_file << first_number << " " << arithemetic_op << " " << second_number << " = " << answer << endl;
        output_file.close();
    }
    return 0;
}

float calculate (float first_number, char arithemetic_op, float second_number) {
    switch (arithemetic_op) {
        case '-':
            answer = first_number - second_number;
            return answer;
        case '+':
            answer = first_number + second_number;
            return answer;
        case '*':
            answer = first_number * second_number;
            return answer;
        case '/':
            answer = first_number / second_number;
            return answer;
    }
}

Ура!

0 голосов
/ 16 февраля 2020

Ваш подход в принципе неплох. Тем не менее, вам нужно сделать немного больше проверки ошибок. И были также некоторые ошибки semanti c.

Это очень важное правило, что вы всегда проверяете там результат операций ввода / вывода.

Сначала я покажу вам исправленную версию, основанную на ваш первоначальный черновик:

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cmath>

using namespace std;
const string file_name = "r:\\input.txt";


float calculate_number(float first_number, char symbol, float last_number) {
    float result{ 0 };
    switch (symbol) {
    case '+':
        result = first_number + last_number;
        break;
    case '-':
        result = first_number - last_number;
        break;
    case '*':
        result = first_number * last_number;
        break;
    case '/':
        result = first_number / last_number;
        break;
    case '%':
        result = fmod(first_number, last_number);
        break;
    default:
        break;
    }
    return result;
}

int main() {
    ifstream input_file;
    ofstream output_file;

    // Open file to get input_file from
    input_file.open(file_name, ios::in);

    // Error checking
    if (!input_file) {
        cout << "Error: file input.txt does not exists\n";
        exit(1);
    }
    else {

        string data_from_file;           // Declare string to store data from file
        //input_file >> data_from_file;    // Pass file content to data

        while (getline(input_file, data_from_file)) {
            istringstream ss(data_from_file);

            char symbol;
            float first_number, last_number;
            // Rad data and check, if that worked
            if (ss >> first_number >> symbol >> last_number) {
                // Check for a valid symbol
                if ((symbol == '+') || (symbol == '-') || (symbol == '*') || (symbol == '/') || (symbol == '%')) {
                    cout << first_number << " " << symbol << " " << last_number << " = "
                        << calculate_number(first_number, symbol, last_number) << endl;
                }
            }
        }
    }

    return 0;
}

После изучения дополнительных языков C ++ вы могли бы воспользоваться приведенным ниже решением.

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <numeric>
#include <map>
#include <utility>
#include <functional>

int main() {

    // All possible operations, defined in one place
    std::map<char, std::function<double(double,double)>> operation {
        {'+', std::plus<double>()},
        {'-', std::minus<double>()},
        {'*', std::multiplies<double>()},
        {'/', std::divides<double>()},
        {'%', static_cast<double(*)(double,double)>(std::fmod) }
    };

    // The file with the source data
    const std::string fileName{ "r:\\input.txt" };

    // Open the source file and check if it could be opened
    if (std::ifstream sourceStream(fileName); sourceStream) {

        // Read all lines of the source file
        for (std::string line{}; std::getline(sourceStream, line); ) {

            // For easier processing, put the line in a std::stringstream
            std::istringstream iss(line);

            // The operands and the operator
            double lhs{ 0.0 }, rhs{ 0.0 };
            char operationSymbol{};

            // Read the parts of the line and check, if read was OK
            if (iss >> lhs >> operationSymbol >> rhs) {

                // Now check, if we have read a valid operator
                if (operation.find(operationSymbol) != operation.end()) {

                    // Show the result
                    std::cout << lhs << " " << operationSymbol << " " << rhs << " = " << operation[operationSymbol](lhs, rhs) << "\n";
                }
                else std::cerr << "\n*** Error: Invalid operator '" << operationSymbol << "'\n\n";
            }
            else std::cerr << "\n*** Error: Problem while reading line:\n'" << line << "'\n\n";
        }
    }
    else std::cerr << "\n*** Error: Source file '" << fileName << "' could not be opened\n\n";

    return 0;
}

Извините, но я не рекомендую ответы пользователя Onyrew и Тихана, которая использует даже глобальные переменные. Простите, ребята.

0 голосов
/ 16 февраля 2020

Я бы порекомендовал реализовать структуру , где вы храните свои номера и операции. Таким образом, вы можете отделить каждую строку.

struct calc {
    int a, b;
    char o;
};

int main() {
    std::ifstream input("input.txt");
    if (!input) {
        /* Handle error */
    } else {
        while (!input.eof()) {
            calc temp;
            input >> temp.a >> temp.o >> temp.b;
            /* Store it as you like */
        }
    }
}

Вы можете сохранить свои окончательные данные в вектор или список .

...