Lab 12: 整數指令列四則計算機

Lab 12-1: 整數指令列四則計算機顯示 (40%)

  • 輸入:包含整數 (符合 long 型態) 的四則計算運算式
    • 用空白字元分開整數數字及運算子,如:1 + 2 * 31 2 3 4 * + -
  • 輸出:顯示使用者輸入的整數數字及運算子。
    • 數字:1 2 31 2 3 4
    • 運算子:+ ** + -
  • 檔名:lab12_1_<學號>.cpp (e.g. lab12_1_106062802.cpp)

Notice:

  • 程式需提示使用者輸入運算式,程式需分析後顯示使用者輸入的整數數字及運算子。
  • 程式需檢查數字跟運算子的數量是否相符,若不相符則顯示錯誤訊息 Invalid expression. 並結束程式。
    • Example:使用者輸入 4 個數字,但運算子只有 2 個,並非 3 個,則顯示錯誤訊息 Invalid expression. 並結束程式。
  • 程式需檢查運算子是否為 '+'、'-'、'*'、'/',若不相符則顯示錯誤訊息 Invalid expression. 並結束程式。
  • 程式需使用 function 來處理整數指令列四則計算機的輸入與輸出。
  • 程式需在 30 秒之內執行完畢,所有測資皆不會超過 30 秒的執行時間。

Format

Please input the expression: <expression, space seprated>⏎
Operands: <numbers, space seprated>
Operators: <operators, space seprated>

Example

$ ./a.out⏎
Please input the expression: 1 2 3 4 * + -⏎
Operands: 1 2 3 4
Operators: * + -
$ ./a.out⏎
Please input the expression: -1 -2 -3 -4 * + -⏎
Operands: -1 -2 -3 -4
Operators: * + -
$ ./a.out⏎
Please input the expression: -1 -2 * -3 + -4 -⏎
Operands: -1 -2 -3 -4
Operators: * + -
$ ./a.out⏎
Please input the expression: -1 -2 -3 -4 * +⏎
Invalid expression.
$ ./a.out⏎
Please input the expression: -1 -2 -3 * + -⏎
Invalid expression.
$ ./a.out⏎
Please input the expression: -1 -2 -3 -4 * + %⏎
Invalid expression.

Pseudo Code

#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

void parse_expression(const string &expression, vector<string> &tokens);
bool check_expression(const vector<string> &tokens);
void print_ops(const vector<string> &tokens);
void print_nums(const vector<string> &tokens);

int main(int argc, char *argv[])
{
    string input_buffer;
    vector<string> tokens;

    cout << "Please input the expression: ";
    std::getline(cin, input_buffer);

    parse_expression(input_buffer, tokens);

    if (!check_expression(tokens))
    {
        cout << "Invalid expression." << endl;
        return EXIT_FAILURE;
    }

    print_ops(tokens);

    print_nums(tokens);

    return EXIT_SUCCESS;
}

Reference:

Reference Code:

2-passes parsing: Credit: 賴杰弘 (110021118)

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

void parse_expression(const string &expression, vector<string> &check);
void parse_expression(
    const vector<string> &check,
    vector<long> &operands,
    vector<string> &operators);
bool check_expression(const vector<string> &check);
void print_ops(const vector<long> &operands);
void print_nums(const vector<string> &operators);

int main(int argc, char *argv[])
{
    string input_buffer;
    vector<string> check;
    vector<long> operands;
    vector<string> operators;

    cout << "Please input the expression: ";
    getline(cin, input_buffer);

    parse_expression(input_buffer, check);

    if (!check_expression(check))
    {
        cout << "Invalid expression." << endl;
        return EXIT_FAILURE;
    }

    parse_expression(check, operands, operators);
    if ((operands.size() - 1) != operators.size())
    {
        cout << "Invalid expression." << endl;
        return EXIT_FAILURE;
    }

    print_ops(operands);

    print_nums(operators);

    return EXIT_SUCCESS;
}

void parse_expression(const string &expression, vector<string> &check)
{
    stringstream terms_extractor(expression);

    for (string term; (terms_extractor >> term);)
    {
        check.push_back(term);
    }
}
void parse_expression(
    const vector<string> &check,
    vector<long> &operands,
    vector<string> &operators)
{
    for (int i = 0; i < check.size(); i++)
    {
        if (check[i] == "+" 
            || check[i] == "-" 
            || check[i] == "*" 
            || check[i] == "/")
        {
            operators.push_back(check[i]);
        }
        else
        {
            long operand = stol(check[i]);
            operands.push_back(operand);
        }
    }
}
bool check_expression(const vector<string> &check)
{
    if ((check.size() % 2) == 0)
    {
        return false;
    }
    for (int i = 0; i < check.size(); i++)
    {
        string s = check[i];
        if (s.size() == 1)
        {
            if (s[0] != '+' 
                && s[0] != '-' 
                && s[0] != '*' 
                && s[0] != '/')
            {
                if (!isdigit(s[0]))
                {
                    return false;
                }
            }
        }
        else
        {
            if (s[0] != '-')
            {
                if (!isdigit(s[0]))
                {
                    return false;
                }
            }
            for (int i = 1; i < check[i].size(); i++)
            {
                if (!isdigit(s[i]))
                {
                    return false;
                }
            }
        }
    }
    return true;
}
void print_ops(const vector<long> &operands)
{
    cout << "Operands: ";
    for (int i = 0; i < operands.size(); i++)
    {
        cout << operands[i] << " ";
    }
    cout << endl;
}
void print_nums(const vector<string> &operators)
{
    cout << "Operators: ";
    for (int i = 0; i < operators.size(); i++)
    {
        cout << operators[i] << " ";
    }
    cout << endl;
}

by character parsing: Credit: 吳咨萱 (110021132)

#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

void parse_expression(const string &expression, vector<string> &tokens)
{
    int n = 0;
    string stringtokens;
    while (n <= expression.size() - 1)
    {
        if (expression[n] != ' ')
        {
            do
            {
                stringtokens.push_back(expression[n]);
                n = n + 1;
            } while (expression[n] != ' ' && n <= expression.size() - 1);
            tokens.push_back(stringtokens);
            stringtokens.clear();
        }
        else
        {
            n = n + 1;
        }
    }
}
bool check_expression(const vector<string> &tokens)
{
    int operandsnum = 0;
    int operatorsnum = 0;
    for (int i = 0; i <= tokens.size() - 1; i++)
    {
        int j = 0;

        if (tokens[i][j] == '-' && tokens[i].size() != 1)
        {
            for (int j = 1; j <= tokens[i].size() - 1; j++)
            {
                if (!isdigit(tokens[i][j]))
                {
                    return false;
                }
            }
            operandsnum = operandsnum + 1;
        }
        else if (tokens[i][j] == '+' 
            || tokens[i][j] == '-' 
            || tokens[i][j] == '*' 
            || tokens[i][j] == '/')
        {
            if (tokens[i].size() != 1)
            {
                return false;
            }
            else
            {
                operatorsnum = operatorsnum + 1;
            }
        }
        else
        {
            for (int j = 0; j <= tokens[i].size() - 1; j++)
            {
                if (!isdigit(tokens[i][j]))
                {
                    return false;
                }
            }
            operandsnum = operandsnum + 1;
        }
    }
    if (operandsnum != operatorsnum + 1)
    {
        return false;
    }
    else
    {
        return true;
    }
}
void print_ops(const vector<string> &tokens)
{
    std::cout << "Operators: ";
    for (int i = 0; i <= tokens.size() - 1; i++)
    {
        if (tokens[i] == "+" 
            || tokens[i] == "-" 
            || tokens[i] == "*" 
            || tokens[i] == "/")
        {
            std::cout << tokens[i];
            if (i != tokens.size() - 1)
            {
                std::cout << " ";
            }
        }
    }
}
void print_nums(const vector<string> &tokens)
{
    std::cout << "Operands: ";
    for (int i = 0; i <= tokens.size() - 1; i++)
    {
        if (tokens[i] != "+" 
            && tokens[i] != "-" 
            && tokens[i] != "*" 
            && tokens[i] != "/")
        {
            std::cout << tokens[i];
            if (i != tokens.size() - 1)
            {
                std::cout << " ";
            }
        }
    }
    std::cout << "\n";
}
int main(int argc, char *argv[])
{
    string input_buffer;
    vector<string> tokens;

    cout << "Please input the expression: ";
    std::getline(cin, input_buffer);

    parse_expression(input_buffer, tokens);

    if (!check_expression(tokens))
    {
        cout << "Invalid expression." << endl;
        return EXIT_FAILURE;
    }
    print_nums(tokens);
    print_ops(tokens);

    return EXIT_SUCCESS;
}

function of function: Credit: 陶威綸 (110021121)

#include <cstdlib>
#include <sstream>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

void parse_expression(const string &expression, vector<string> &tokens);
bool check_expression(const vector<string> &tokens);
void print_ops(const vector<string> &tokens);
void print_nums(const vector<string> &tokens);
bool is_number(string num);
bool is_oper(string token);

int main(int argc, char *argv[])
{
    string input_buffer;
    vector<string> tokens;

    cout << "Please input the expression: ";
    std::getline(cin, input_buffer);

    parse_expression(input_buffer, tokens);

    if (!check_expression(tokens))
    {
        cout << "Invalid expression." << endl;
        return EXIT_FAILURE;
    }

    print_nums(tokens);
    print_ops(tokens);

    return EXIT_SUCCESS;
}

void print_ops(const vector<string> &tokens)
{
    cout << "Operators: ";
    for (int i = 0; i < tokens.size(); i++)
    {
        if (is_oper(tokens[i]))
            cout << tokens[i] << " ";
    }
    cout << endl;
}
void print_nums(const vector<string> &tokens)
{
    cout << "Operands: ";
    for (int i = 0; i < tokens.size(); i++)
    {
        if (is_number(tokens[i]))
            cout << tokens[i] << " ";
    }
    cout << endl;
}

void parse_expression(const string &expression, vector<string> &tokens)
{
    stringstream buffer(expression);
    for (string tmp; (buffer >> tmp);)
    {
        tokens.push_back(tmp);
    }
}

bool is_number(string num)
{
    int suc_case = 0;
    if (num[0] == '-' && num.size() != 1)
        suc_case = 1;
    for (int i = 0; i < num.size(); i++)
    {
        for (int tmp = 0; tmp < 10; tmp++)
        {
            if (num[i] - '0' == tmp)
            {
                suc_case += 1;
            }
        }
    }
    return suc_case == num.size();
}

bool is_oper(string token)
{
    if (token.size() != 1)
        return false;
    string valid = "+-*/";
    for (int i = 0; i < valid.size(); i++)
    {
        if (token[0] == valid[i])
            return true;
    }
    return false;
}

bool check_expression(const vector<string> &tokens)
{
    int numC = 0, operC = 0;
    for (int i = 0; i < tokens.size(); i++)
    {
        if (is_number(tokens[i]))
            numC += 1;
        else if (is_oper(tokens[i]))
            operC += 1;
        else
            return false;
    }
    return (numC - operC == 1);
}

try ... catch ...: Credit: 陳柏志 (107021128)

#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <sstream>

using namespace std;

void parse_expression(const string &expression, vector<string> &tokens);
bool check_expression(const vector<string> &tokens);
void print_ops(const vector<string> &tokens);
void print_nums(const vector<string> &tokens);

int main(int argc, char *argv[])
{
	string input_buffer;
	vector<string> tokens;

	cout << "Please input the expression: ";
	getline(cin, input_buffer);

	parse_expression(input_buffer, tokens);

	if (!check_expression(tokens))
	{
		cout << "Invalid expression." << endl;
		return EXIT_FAILURE;
	}

	print_nums(tokens);
	print_ops(tokens);

	return EXIT_SUCCESS;
}

void parse_expression(string const &expression, vector<string> &tokens)
{
	stringstream tokens_extractor(expression);

	for (string new_token; (tokens_extractor >> new_token);)
	{
		tokens.push_back(new_token);
	}
}

bool check_expression(const vector<string> &tokens)
{
	int op_cnt = 0, num_cnt = 0;

	for (int i = 0; i < tokens.size(); ++i)
	{
		if (tokens[i] == "+" 
			|| tokens[i] == "-" 
			|| tokens[i] == "*" 
			|| tokens[i] == "/")
		{
			++op_cnt;
		}
		else
		{
			try
			{
				stol(tokens[i]);
				++num_cnt;
			}
			catch (const std::exception &e)
			{
				return false;
			}
		}
	}
	return num_cnt == op_cnt + 1;
}

void print_ops(const vector<string> &tokens)
{
	cout << "Operators:";
	for (int i = 0; i < tokens.size(); ++i)
	{
		if (tokens[i] == "+" 
			|| tokens[i] == "-" 
			|| tokens[i] == "*" 
			|| tokens[i] == "/")
		{
			cout << " " << tokens[i];
		}
	}
	cout << endl;
}

void print_nums(const vector<string> &tokens)
{
	cout << "Operands:";
	for (int i = 0; i < tokens.size(); ++i)
	{
		try
		{
			long number = stol(tokens[i]);
			cout << " " << number;
		}
		catch (const std::exception &e)
		{
		}
	}
	cout << endl;
}

TA version:

#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void parse_expression(const string &expression, vector<string> &tokens);
bool check_expression(const vector<string> &tokens);
void print_ops(const vector<string> &tokens);
void print_nums(const vector<string> &tokens);
int main(int argc, char *argv[])
{
    string input_buffer;
    vector<string> tokens;
    cout << "Please input the expression: ";
    std::getline(cin, input_buffer);
    parse_expression(input_buffer, tokens);
    if (!check_expression(tokens))
    {
        cout << "Invalid expression." << endl;
        return EXIT_FAILURE;
    }
    print_nums(tokens);
    print_ops(tokens);
    return EXIT_SUCCESS;
}

void parse_expression(const string &expression, vector<string> &tokens)
{
    string temp;
    for (int i = 0; i < expression.size(); i++)
    {
        if (expression[i] == ' ')
        {
            tokens.push_back(temp);
            temp.clear();
        }
        else if (i == expression.size() - 1) // End of Input_Buffer
        {
            temp += expression.substr(i, 1);
            tokens.push_back(temp);
        }
        else
            temp += expression.substr(i, 1);
    }
}

bool check_expression(const vector<string> &tokens)
{
    int oper_counts = 0, num_counts = 0;
    for (int i = 0; i < tokens.size(); i++)
    {
        if (tokens[i].length() == 1)
        {
            if (isdigit(tokens[i][0]))
            {
                num_counts++;
                continue;
            }
            else
            {
                if (tokens[i][0] == '+' 
                    || tokens[i][0] == '-' 
                    || tokens[i][0] == '*' 
                    || tokens[i][0] == '/')
                {
                    oper_counts++;
                    continue;
                }
                else
                    return false;
            }
        }
        for (int j = 0; j < tokens[i].length(); j++)
        {
            if (!isdigit(tokens[i][j]))
            {
                if (j == 0 && tokens[i][j] == '-') 
                // Check if Negative Sign
                    continue;
                return false;
            }
        }
        num_counts++;
    }

    if (num_counts != oper_counts + 1)
        return false;
    return true;
}

void print_nums(const vector<string> &tokens)
{
    cout << "Operands:";
    for (int i = 0; i < tokens.size(); i++)
    {
        if (tokens[i].length() != 1 || isdigit(tokens[i][0]))
            cout << ' ' << tokens[i];
    }
    cout << endl;
}

void print_ops(const vector<string> &tokens)
{
    cout << "Operators:";
    for (int i = 0; i < tokens.size(); i++)
    {
        if (tokens[i].length() == 1 && !isdigit(tokens[i][0]))
            cout << ' ' << tokens[i];
    }
    cout << endl;
}