2
\$\begingroup\$

I recently made a little program that shouldparse a logic formula (given in conjunctive normal form). I do the parsing with reloaded operator>> but I am not very satisfied with the workaround I used to get those operators recognized from a file different from the file they are implemented in.

When I need those operators I have to write the following at the top of the file:

extern std::istream& operator>>(std::istream&, class-name&);
extern std::ostream& operator<<(std::ostream&, const class-name&);

Here are the part I would be glad to have a review of:

#include "formula.hh"
#include "clause.hh"

#include <cstdio>
#include <sstream>

extern std::istream& operator>>(std::istream&, Clause& lhs);
extern std::ostream& operator>>(std::ostream&, const Clause& lhs);

[...]

std::istream&
operator>>(std::istream& stream, Formula& lhs) {
    std::string cur_line("");
    unsigned int var_max_expected = 0;
    unsigned int nb_clauses_expected = 0;
    bool clause_read = false;
    bool intro_read = false;

    while (getline(stream, cur_line)) {
        Clause c;
        if (cur_line[0] == 'c') {} /* Comment skip */
        else if ((sscanf(cur_line.c_str(), "p cnf %d %d", &var_max_expected, &nb_clauses_expected)) == 2) {
            if (!intro_read)
                intro_read = true;
            else
                std::cerr << "Warning : Intro already read and overwritten!" << std::endl;
            if (clause_read)
                std::cerr << "Warning : Intro was not the first command of the file!" << std::endl;
        } else {
            std::istringstream is(cur_line);
            is >> c;
            lhs.insert(c);
        }
        c.clear();
    }

    if (!intro_read)
        std::cerr << "Warning: Intro missing" << std::endl;
    else {
        if (var_max_expected != Var::max_index())
            std::cerr << "Warning: Bad number of variables. Found: " << Var::max_index() << ". Expected: " << var_max_expected << "." << std::endl;
        if (nb_clauses_expected != lhs.size() + 1)
            std::cerr << "Warning: Bad number of found. Found: " << lhs.size() << ".     Expected: " << nb_clauses_expected << "." << std::endl;
    }

    return stream;
}

#ifdef FORMULA_DEBUG


int
main (void) {
    Formula f;

    std::cin >> f;
    std::cout << f << std::endl;

    return EXIT_SUCCESS;
}

#endif /* FORMULA_DEBUG */

The relevant part in clause.hh, clause.cc and formula.hh are listed below:

formula.hh

#ifndef FORMULA_HH
#define FORMULA_HH

#include <iostream>
#include <set>

#include "clause.hh"

class Formula : public std::set<Clause> {
    public:
    [...]
        /**
         * @brief Allow a Formula to be used with output streams.
         */
        friend std::ostream& operator<<(std::ostream& stream, const Formula& rhs);

        /**
         * @brief Allow a Formula to be used with input streams.
         */
        friend std::istream& operator>>(std::istream& stream, Formula& lhs);

};
#endif

clause.hh

#ifndef CLAUSE_HH
#define CLAUSE_HH

#include <iostream>
#include <set>

#include "truthvalue.hh"
#include "var.hh"

class Clause : public std::set<std::pair<Var *, bool>> {
    public:
    [...]

       /**
         * @brief Allow a Clause to be used with output streams.
         */
        friend std::ostream& operator<<(std::ostream& stream, const Clause& rhs);

        /**
         * @brief Allow a Clause to be used with output streams.
         */
        friend std::istream& operator<<(std::istream& stream, Clause& lhs);

};
#endif

clause.cc

#include <cstdlib>

#include "clause.hh"

[...]

std::ostream&
operator<<(std::ostream& os, const Clause& rhs) {
    os << rhs.to_str();
    return os;
}

std::istream&
operator>>(std::istream& is, Clause& lhs) {
    int nb;
    bool first_item = true;

    while(is >> nb) {
        if (nb == 0) break;

        int var = std::abs(nb);
        Var& v = Var::declare(var);
        bool polarity = (nb / var == 1)
                      ? true
                      : false
                      ;

        lhs.insert(std::make_pair(&v, polarity));
    }

    return is;
}

Do you have any ideas to get them recognized everywhere? If you need additional information I can provide them.

Samples test cases for parsing can be found here and the whole code which is doing the parsing is here.

The compile line is the following:

g++/clang++ truthvalue.cc var.cc clause.cc formula.cc -DFORMULA_DEBUG -o test
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Simplify the boolean ternary

You write:

    bool polarity = (nb / var == 1)
                  ? true
                  : false
                  ;

But nb / var == 1 already is a boolean, so the ternary is completely superfluous and may be deleted:

    bool polarity = (nb / var == 1);
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.