Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Тестовая программа для чтения файла с неприводимыми многочленами.
- */
- #include <cassert>
- #include <cstdio>
- #include <cstdlib>
- #include <exception>
- #include <fstream>
- #include <iostream>
- #include <locale> // for isspace, isdigit etc.
- #include <map>
- #include <string>
- #include <vector>
- using namespace std;
- const char * const FILENAME = "polys.txt";
- /* --- Misc ---------------------------------------------------------------- */
- /*
- * Skip spaces in string 's' starting from 'pos'.
- * Return the position of the first non-space char.
- * If no non-space char was found, return 's.size()'.
- */
- size_t skipspaces(const string & s, size_t pos = 0){
- assert(pos >= 0);
- size_t l = s.size();
- while (pos < l && isspace(s[pos])) ++pos;
- return pos;
- }
- /* --- Polynom classes ----------------------------------------------------- */
- class SyntaxError: public exception {
- public:
- SyntaxError(const string & message_): message(message_) { }
- virtual const char * what() const throw() { return message.c_str(); }
- virtual ~SyntaxError() throw() { }
- private:
- string message;
- };
- class Poly {
- friend ostream & operator <<(ostream & output, const Poly & poly);
- public:
- enum Stat {
- REDUCIBLE,
- IRREDUCIBLE,
- PRIMITIVE,
- };
- Poly(Stat stat_): stat(stat_) { }
- bool is_irreducible() const {
- return stat >= IRREDUCIBLE;
- }
- bool is_primitive() const {
- return stat >= PRIMITIVE;
- }
- /*
- * Распарсить строку, содержащую коэффициенты многочлена.
- * Символы считываются из 's', начиная с позиции 'pos'.
- *
- * Коэффициенты в строке должны разделяться запятыми.
- * Пробелы вокруг запятых допускаются.
- * Пробелы в позиции pos допускаются.
- * Однако пустая строка или строка из одних пробелов
- * будет считаться ошибкой.
- *
- * Представление шестнадцатеричными цифрами A-F не допускается, только 0-9.
- * Возвращаемое значение - место в строке, где закончился разбор.
- */
- size_t parse(int q, const string & s, size_t pos = 0){
- assert(pos >= 0);
- const size_t l = s.size();
- /*
- * Пропускаем начальные нули, чтобы не захламлять массив
- * лишней информацией.
- */
- bool skip_zeroes = true;
- vector<int> new_vec;
- pos = skipspaces(s, pos);
- if (pos == l)
- throw SyntaxError("Empty string is not a polynom, dude!");
- for (;;) {
- size_t pos2 = pos;
- while (pos2 < l && isdigit(s[pos2])) ++pos2;
- if (pos == pos2) {
- /* atoi doesn't consider empty string to mean 0 */
- if (!skip_zeroes)
- new_vec.push_back(0);
- }
- else {
- int v = atoi(s.substr(pos, pos2 - pos).c_str());
- if (v < 0) {
- /* Глупая проверка, так как использовали isdigit выше */
- throw SyntaxError("Polynom coeffs must't be negative.");
- }
- else if (v >= q) {
- throw SyntaxError("Polynom coeff must be less than 'q'.");
- }
- if (skip_zeroes) {
- if (v != 0){
- new_vec.push_back(v);
- skip_zeroes = false;
- }
- }
- else
- new_vec.push_back(v);
- }
- pos = skipspaces(s, pos2);
- if (pos == l)
- /* Конец строки - конец разбора */
- break;
- if (s[pos] != ',')
- /* Не запятая - конец разбора */
- break;
- /*
- * Иначе пропускаем запятую и последующие пробелы
- * и разбираем следующий коэффициент.
- */
- pos = skipspaces(s, pos+1);
- }
- vec.swap(new_vec);
- return pos;
- }
- private:
- Stat stat;
- vector<int> vec;
- };
- ostream & operator <<(ostream & output, const Poly & poly){
- vector<int>::const_iterator it = poly.vec.begin();
- const vector<int>::const_iterator end = poly.vec.end();
- if (it != end)
- output << *it++;
- for (; it != end; ++it)
- output << ',' << *it;
- return output;
- }
- /* --- main ---------------------------------------------------------------- */
- typedef map<int, vector<Poly> > Polys;
- bool read(Polys & all_polys){
- ifstream input(FILENAME);
- int lineno = 1;
- /*
- * То, что обозначалось буквой q не лекциях.
- * 0 - недействительное значение.
- */
- int q = 0;
- vector<Poly> * polys = 0;
- try {
- string line;
- for (; getline(input, line); ++lineno){
- const size_t l = line.size();
- if (l == 0)
- /* Проверяем заранее, чтобы не напороться на грабли, проверяя line[0]. */
- continue;
- if (line[0] == '#')
- /* comment */
- continue;
- if (line[0] == '>'){
- /* primitive poly */
- if (q == 0)
- throw SyntaxError("Field size (q) directive is missing");
- polys->push_back(Poly(Poly::PRIMITIVE));
- if (polys->back().parse(q, line, 1) != l){
- /* Строка разобрана не до конца */
- throw SyntaxError("");
- }
- continue;
- }
- if (line[0] == '['){
- if (l < 4 || line[1] != 'F')
- throw SyntaxError("");
- size_t i = 2;
- size_t i2 = i;
- while (i2 < l-1 && isdigit(line[i2])) ++i2;
- if (i == i2)
- throw SyntaxError("");
- q = atoi(line.substr(i, i2 - i).c_str());
- if (q <= 0)
- throw SyntaxError("q must be positive");
- if (line[i2] != ']')
- throw SyntaxError("");
- if (skipspaces(line, i2+1) != l)
- throw SyntaxError("");
- polys = &( all_polys[q] );
- continue;
- }
- /*
- * Проверяем здесь, не пустая ли это строка.
- * Poly.parse() в этом случае выдаст ошибку,
- * а мы пустые строки в файле допускаем (и пропускаем).
- */
- size_t i = skipspaces(line, 0);
- if (i == l)
- /* Skip empty string */
- continue;
- if (q == 0)
- throw SyntaxError("Field size (q) directive is missing");
- polys->push_back(Poly(Poly::IRREDUCIBLE));
- if (polys->back().parse(q, line, i) != l)
- /* Строка разобрана не до конца */
- throw SyntaxError("");
- }
- }
- catch(SyntaxError & e){
- cerr << "Syntax error at line " << lineno << ": " << e.what() << '\n';
- return false;
- }
- return true;
- }
- void write(const Polys & polys){
- Polys::const_iterator it = polys.begin();
- const Polys::const_iterator end = polys.end();
- for (; it != end; ++it){
- cout << "[F" << it->first << "]\n";
- vector<Poly>::const_iterator it2 = it->second.begin();
- const vector<Poly>::const_iterator end2 = it->second.end();
- for (; it2 != end2; ++it2){
- if (it2->is_primitive())
- cout << "> ";
- else
- cout << " ";
- cout << *it2 << '\n';
- }
- }
- }
- int main(int argc, char ** argv){
- Polys polys;
- if (!read(polys))
- return 1;
- write(polys);
- return 0;
- }
Add Comment
Please, Sign In to add comment