如何修复此教科书程序以在C++中添加多项式?

How can I fix this textbook program to add polynomials in C++?

本文关键字:C++ 添加 多项式 何修复 教科书 程序      更新时间:2023-10-16

我刚刚开始编码,这是我用来学习C++的一本书。它应该直接从书中工作,我不知道如何解决它。

我认为问题可能是因为它缺少常量运算符,但是如果您将其添加进来,这不会阻止您修改值吗?

这本书是由Drozdek撰写的,标题为C++中的数据结构和算法,如果你需要的话。感谢您的帮助!

#include <iostream>
#include <cctype>
#include <cstdlib>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
class Variable {
public:
char id;
int exp;
Variable() { // required by <vector>;
}
Variable(char c, int i) {
id = c; exp = i;
}
bool operator== (const Variable& v) const { 
return id  == v.id  && exp == v.exp;
}
bool operator< (const Variable& v) const { // used by sort();
return id < v.id;
}
};
class Term {
public:
Term() {
coeff = 0;
}
int coeff;
vector<Variable> vars;
bool operator== (const Term&) const;
bool operator!= (const Term& term) const { // required by <list>
return !(*this == term);
}
bool operator< (const Term&) const;
bool operator> (const Term& term) const {  // required by <list>
return *this != term && (*this < term);
}
int min(int n, int m) const {
return (n < m) ? n : m;
}
};
class Polynomial {
public:
Polynomial() {
}
Polynomial operator+ (Polynomial&);
void error(char *s) {
cerr << s << endl; exit(1);
}
private:
list<Term> terms;
friend istream& operator>> (istream& in, Polynomial& polyn) {
char ch, sign, coeffUsed, id;
int exp;
Term term;
in >> ch;
while (true) {
coeffUsed = 0;
if (!isalnum(ch) && ch != ';' && ch != '-' && ch != '+')
polyn.error("Wrong character entered2");
sign = 1;
while (ch == '-' || ch == '+') { // first get sign(s) of Term
if (ch == '-')
sign *= -1;
ch = in.get();
if (isspace(ch))
in >> ch;
}
if (isdigit(ch)) {              // and then its coefficient;
in.putback(ch);
in >> term.coeff;
ch = in.get();
term.coeff *= sign;
coeffUsed = 1;
}
else term.coeff = sign;
int i;
for (int i = 0; isalnum(ch); i++) { // process this term:
id = ch;                    // get a variable name
ch = in.get();
if (isdigit(ch)) {          // and an exponent (if any);
in.putback(ch);
in >> exp >> ch;
}
else exp = 1;
term.vars.push_back(Variable(id,exp));
}
polyn.terms.push_back(term);    // and include it in the linked list;
term.vars.resize(0);    
if (isspace(ch))
in >> ch;
if (ch == ';')                  // finish if a semicolon is entered;
if (coeffUsed || i > 0)
break;
else polyn.error("Term is missing");  // e.g., 2x - ; or just ';'
else if (ch != '-' && ch != '+')           // e.g., 2x  4y;
polyn.error("wrong character entered");
}
for (list<Term>::iterator it = polyn.terms.begin(); it != polyn.terms.end(); it++)
if (it->vars.size() > 1)
sort(it->vars.begin(),it->vars.end());
return in;
}
friend ostream& operator<< (ostream& out, const Polynomial& polyn) {
int afterFirstTerm = 0, i;
for (list<Term>::const_iterator pol = polyn.terms.begin(); pol != polyn.terms.end(); pol++) {
out.put(' ');
if (pol->coeff < 0)             // put '-' before polynomial
out.put('-');              // and between terms (if needed);
else if (afterFirstTerm)        // don't put '+' in front of
out.put('+');              // polynomial;
afterFirstTerm++;
if (abs(pol->coeff) != 1)       // print a coefficient
out << ' ' << abs(pol->coeff);// if it is not 1 nor -1, or
else if (pol->vars.size() == 0) // the term has only a coefficient
out << " 1";               
else out.put(' ');
for (i = 1; i <= pol->vars.size(); i++) {
out << pol->vars[i-1].id;       // print a variable name
if (pol->vars[i-1].exp != 1)    // and an exponent, only
out << pol->vars[i-1].exp; // if it is not 1;
}
}
out << endl;
return out;
}
};
// two terms are equal if all varibles are the same and
// corresponding variables are raised to the same powers;
// the first cell of the node containing a term is excluded
// from comparison, since it stores coefficient of the term;
bool Term::operator== (const Term& term) const {
int i;
for (i = 0; i < min(vars.size(),term.vars.size()) &&
vars[i] == term.vars[i]; i++);
return i == vars.size() && vars.size() == term.vars.size();
}
bool Term::operator< (const Term& term2) const { // used by sort();
if (vars.size() == 0)
return false;           // *this is just a coefficient;
else if (term2.vars.size() == 0)
return true;            // term2 is just a coefficient;
for (int i = 0; i < min(vars.size(),term2.vars.size()); i++)
if (vars[i].id < term2.vars[i].id)
return true;       // *this precedes term2;
else if (term2.vars[i].id < vars[i].id)
return false;      // term2 precedes *this;
else if (vars[i].exp < term2.vars[i].exp)
return true;       // *this precedes term2;
else if (term2.vars[i].exp < vars[i].exp)
return false;      // term2 precedes *this;
return ((int)vars.size() - (int)term2.vars.size() < 0) ? true : false;
}
Polynomial Polynomial::operator+ (Polynomial& polyn2) {
Polynomial result;
list<Term>::iterator p1, p2;
bool erased;
for (p1 = terms.begin(); p1 != terms.end(); p1++) // create a new polyn
result.terms.push_back(*p1);                  // from copies of *this
for (p1 = polyn2.terms.begin(); p1 != polyn2.terms.end(); p1++) // and
result.terms.push_back(*p1);                  // polyn2;
for (p1 = result.terms.begin(); p1 != result.terms.end(); ) {
for (p2 = p1, p2++, erased = false; p2 != result.terms.end(); p2++)
if (*p1 == *p2) {             // if two terms are equal (except
p1->coeff += p2->coeff;  // for the coefficient), add the
result.terms.erase(p2);  // two coefficients and erase
if (p1->coeff == 0)      // a redundant term; if the 
result.terms.erase(p1);// coefficient in retained term 
erased = true;             // is zero, erase the term as well;
break;
}
if (erased)        // restart processing from the beginning
p1 = result.terms.begin();  // if any node was erased;
else p1++;
}
result.terms.sort();
return result;
}
int main() {
Polynomial polyn1, polyn2;
cout << "Enter two polynomials, each ended with a semicolon:n";
cin  >> polyn1 >> polyn2;
cout << "The result is:n" << polyn1 + polyn2;
return 0;
}

在第 52 行,error 函数应该取一个const char*,而不是一个char*

void error(char* s) { // WRONG
void error(const char *s) { // RIGHT
cerr << s << endl; exit(1);
}

这是因为像"Hello"这样的字符串是const char数组,因为你不能修改文字。如果进行此更改,代码应该可以工作。编译器不会将指针转换为const类型到常规指针,因为这会破坏const

此外,在第 82 行和 83 行,教科书写道:

int i; // Error: i never initialized
for (int i = 0; isalnum(ch); i++) { // process this term:

看起来它试图在 for 循环内外使用i,但作者在循环开始时不小心第二次声明了i。我们可以通过这样做来修复它:

int i = 0; // This is probably what was intended
for(; isalnum(ch); i++) { // process this term:

为什么我不能修改字符串文本?

想象一下,如果你能做到

5 = 10; // This is complete and utter nonsense. 

这没有任何意义!不能将 5 分配给 10。同样,这也是无稽之谈:

"hello" = "blarg"; // This is also nonsense

"hello"总是"hello",从不做别的。如果编译器允许您编写

"hello"[0] = 'H'; // This is also nonsense

这将修改"hello",这可能只是...中断你的程序。这是错误的;这是邪恶的。事实上,字符串文字"hello"甚至可以放在操作系统本身标记为const的内存部分中。

为什么编译器会给你错误(或警告(

如果你有char*,那就是指向字符的指针。如果你有const char*,那就是指向常量字符的指针。如果你可以从const char*转到char*,这将允许您修改const内存,这可能会破坏程序:

// If you could do this, you could modify "hello"
// Modifying "hello" is nonsense, so this should be nonsense too:
char* s = "hello"; 
s[0] = 'H'; // How you'd modify "hello"

因此,字符串文字只能分配给const char*

// Because s contains const chars, elements of s can't be modified so this is fine
const char* s = "hello"; // This is OK

为什么教科书包含错误?

这种语言用于让人们做真正不安全的事情,比如修改字符串文字。这是非常糟糕的做法,它破坏了编译器用于使程序更小、更快的优化。

这本教科书可能是由习惯于编写旧的、不安全的代码的人编写的。