I am just kind of starting to code and this was in a book that I am using to learn C++. It should be working straight from the book and I can't figure out how to fix it.
I think the problem might be because it lacks the constant operator but if you add it in doesn't that prevent you from modifying the value?
The book is by Drozdek titles Data Structures and Algorithms in C++ if you need that. Thanks for the help!
#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;
}
On line 52, the error function should take a const char*, rather than a char*:
void error(char* s) { // WRONG
void error(const char *s) { // RIGHT
cerr << s << endl; exit(1);
}
This is because strings like "Hello" are arrays of const char, because you can't modify literals. If you make this change, the code should work. The compiler won't convert pointers to const types to regular pointers, because that would break the constness.
Also, on line 82 ad 83, the textbook writes:
int i; // Error: i never initialized
for (int i = 0; isalnum(ch); i++) { // process this term:
It looks like it was trying to use i both inside and outside the for loop, but the author accidentally declared i a second time at the start of the loop. We can fix it by doing this:
int i = 0; // This is probably what was intended
for(; isalnum(ch); i++) { // process this term:
Why can't I modify string literals?
Imagine if you could do
5 = 10; // This is complete and utter nonsense.
This doesn't make any sense! You can't assign 5 to 10. In the same way, this is also nonsense:
"hello" = "blarg"; // This is also nonsense
"hello" is always "hello", and never anything else. If the compiler allowed you to write
"hello"[0] = 'H'; // This is also nonsense
This would be modifying "hello", which could just... break your program. It's wrong; it's evil. In fact, the string literal "hello" might even be placed in a section of memory that's flagged as const by the Operating System itself.
Why does the compiler give you the error (or warning)
If you have char*, that is a pointer to a char. If you have const char*, that is a pointer to a const char. If you could go from const char* to char*, this would allow you to modify const memory, which could break the program:
// 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"
As a result, string literals can only be assigned to 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
Why did the textbook contain the error?
The language used to let people do really unsafe stuff, like modifying string literals. This is extremely bad practice and it breaks optimizations the compiler uses to make programs smaller and faster.
The textbook is probably written by someone who's used to writing old, unsafe code.
Related
I tried to write a calulator which allows for chaining.
So my firstSet() function handles division an multiplication and the. modifies the vector, until the secondSet() function handle addition and subtraction.I had some bugs with the part where I am erasing vector elements, which is where I suspect the segmentation fault is occurring from.
#include <vector>
#include <iostream>
//Structure:
//Vector 'stream' of data objects , where each element is either a num or operator
//Heirarchy:
//1.* & /
//2.+ & -
//expected input : Spaced integers with operators and a semicolon to end the input statement.
//for ex:
//3+2;
//5/6;
struct Data
{
char type;
int val;
char op;
Data(char x , char y)
: type(x) , op(y){}
Data(char x , int y) : type(x) , val(y){}
};
void firstSet(std::vector<Data> & v) // / & *
{
int temp;
for (auto i = v.begin(); i != v.end()-1 ; ++i)
{
if ((*i).type == 'o' && ((*i).op == '/' || (*i).op == '*'))
{
if ((*i).op == '/')
{
temp = (*(i-1)).val / (*(i+1)).val;
}
if ((*i).op == '*')
{
temp = (*(i-1)).val * (*(i+1)).val;
}
(*(i-1)).val = temp; // change lhs
v.erase(i); //delete operator
v.erase(i); //delete rhs
}
}
}
void secondSet(std::vector<Data> & v) // + & -
{
int temp;
for (auto i = v.begin(); i != v.end() ; ++i)
{
if ((*i).type == 'o' && ((*i).op == '+' || (*i).op == '-') )
{
if ((*i).op == '+')
{
temp = (*(i-1)).val + (*(i+1)).val;
}
if ((*i).op == '-')
{
temp = (*(i-1)).val - (*(i+1)).val;
}
(*(i-1)).val = temp;
v.erase(i);
v.erase(i);
}
}
}
int main()
{
std::vector<Data> v;
char T;
std::cin >>T;
while (T != ';')
{
if (T == '/' || T == '*' || T == '+' || T == '-')
{
v.push_back(Data{'o' , T});
}
if (T >= '0' && T <= '9')
{
std::cin.putback(T);
int x;
std::cin >> x;
v.push_back(Data{'n' , x});
}
std::cin >> T;
}
firstSet(v);
secondSet(v);
std::cout << v[0].val;
}
p.s any comments on code readability and neatness in general would be helpful as I want the code to be 'clean'.
Using i after v.erase(i) is invalid, because calling erase [...]invalidates iterators and references at or after the point of the erase, including the end() iterator.[...]
So the second v.erase(i) is wrong, but also continuing the loop using ++i is invalid, and would result in undefined behavior.
You need to replace i with a valid iterator after your erase called. E.g. using:
i = v.erase(i);
But doing so will result in skipping each element after the erased one, so you need to change the logic of your loop.
But there are other parts that are invalid:
(*(i-1)).val = temp; will be invalid if i==v.begin()
(*(i+1)).val will be invalid if (i+1)==v.end()
So you need to think over the complete logic of your code in general.
I have this code which is about polynomials multiplication.
I meet no error, just what I want is to sort the terms based on degrees (from lower degree to higher).
If I add condition in operator* in //commented part, it will be printed too many of times. I would like to know if I can use m_Polynomial.sort()? If yes how? If not, what other methods can I use?
As it is both for printing polynomials and their multiplication result it would be nice if it could be added in print function.
Also if it is possible to change the printing style of Polynomials to desired format (to add coefficients of same degree terms)
Minimal code:
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <vector>
using namespace std;
typedef struct Node
{
double cof; // coefficient
int deg; // degree
} Node;
class CPolynomial
{
public:
CPolynomial();
CPolynomial(const string& file);
~CPolynomial();
CPolynomial operator*(const CPolynomial &right);
CPolynomial& operator=(const CPolynomial &right);
void Print() const;
private:
void ReadFromFile(string file);
private:
list<Node> m_Polynomial;
};
int main()
{
CPolynomial p1("P3.txt");
CPolynomial p2("P4.txt");
CPolynomial p3;
p1.Print();
p2.Print();
p3 = p1*p2;
p3.Print();
system("pause");
return 0;
}
CPolynomial::CPolynomial()
{
Node term;
term.cof = 0;
term.deg = 0;
m_Polynomial.push_back(term);
}
CPolynomial::~CPolynomial()
{
m_Polynomial.clear();
}
CPolynomial::CPolynomial(const string& file)
{
ReadFromFile(file);
}
CPolynomial CPolynomial:: operator*(const CPolynomial &right)
{
CPolynomial result;
result.m_Polynomial = m_Polynomial;
for (list<Node>::iterator itr = result.m_Polynomial.begin(); itr != result.m_Polynomial.end(); ++itr)
{
itr->cof = 0;
itr->deg = 0;
}
Node term;
Node termR;
Node temp;
for (list<Node>::const_iterator it = m_Polynomial.begin(); it != m_Polynomial.end(); ++it)
{
for (list<Node>::const_iterator itR = right.m_Polynomial.begin(); itR != right.m_Polynomial.end(); ++itR)
{
term = *it;
termR = *itR;
temp.cof = termR.cof* term.cof;
temp.deg = termR.deg + term.deg;
for (list<Node>::iterator itr = result.m_Polynomial.begin(); itr != result.m_Polynomial.end(); ++itr)
{
if (temp.deg == itr->deg)
{
temp.cof += itr->cof;
itr->cof = 0;
}
// if(temp.deg < it->deg)
//result.m_Polynomial.insert(it, temp);
}
result.m_Polynomial.push_back(temp);
}
}
return result;
}
CPolynomial& CPolynomial:: operator=(const CPolynomial &right)
{
this->m_Polynomial = right.m_Polynomial;
return *this;
}
void CPolynomial::Print() const
{
list<Node>::const_iterator it;
for (it = m_Polynomial.begin(); it != m_Polynomial.end(); it++)
{
if (it->cof == 0)
{
;
}
else
{
if (it->cof > 0)
{
if (it != m_Polynomial.begin()) // if 'it' is not the first term, '+' is not necessary
cout << "+";
}
cout << it->cof;
if (it->deg != 0)
cout << "x^" << it->deg;
}
}
cout << endl;
}
void CPolynomial::ReadFromFile(string file)
{
Node term;
fstream MyFile;
string p;
int num;
MyFile.open(file);
if (!MyFile.is_open())
{
cerr << "Unable to open input file" << endl;
exit(EXIT_FAILURE);
}
else
{
MyFile >> p >> num;
std::list<Node>::iterator it = m_Polynomial.begin();
for (int i = 0; i < num; i++)
{
MyFile >> term.deg >> term.cof;
m_Polynomial.push_back(term);
}
MyFile.close();
}
}
P1.txt
P 8
0 2
5 -3
12 5
2 6
5 7
3 -4
2 9
2 2
P4.txt
P 2
1 4
4 -3
Output
2-3^5+5x^12+6x^2+7x^5-4x^3+9x^2+2x^2 (P1)
4x^1-3x^4 (P2)
8x^1+20x^13-15x^16_12x^9-22x^4+12x^7+68x^3 (P1*P2)
desired output:
2+17x^2-4x^3+4x^5+5x^12
4x^1-3x^4
8x^1+68x^3-22x^4+12x^7_12x^9+20x^13-15x^16
Your operator modifies its left operand, why?
If you say p3 = p1 * p2; then it is wrong to modify p1, you should return a new object with a new value, and not alter the operands.
One solution is to provide operator*= as a member function that alters its left operand, then define operator* as a non-member function:
CPolynomial operator*(const CPolynomial& lhs, const CPolynomial& rhs)
{
CPolynomial result = lhs;
result *= rhs;
return result;
}
The bug appears to be in AddOneTerm where you do the comparisons wrong. Your loop will insert the new term at the first position where (term.deg >= it->deg) but it should be the last position where that is true.
Also you should use AddOneTerm(term) instead of m_Polynomial.push_back(term) in ReadFromFile to ensure the terms are kept in the correct order.
You also have very confusing use of iterators:
std::list<Node>::iterator next_it;
next_it = ++it;
Now both next_it and it have been incremented, so they are both the next term. Why?
I suggest something much simpler:
void CPolynomial::AddOneTerm(Node term)
{
auto it = m_Polynomial.begin();
while (it != m_Polynomial.end() && it->deg < term.deg)
{
++it;
}
if (it != m_Polynomial.end() && term.deg == it->deg)
{
it->cof += term.cof;
}
else
{
m_Polynomial.insert(it, term);
}
}
You could also define a comparison operator for Node objects:
bool operator<(const Node& l, const Node& r)
{
return l.deg < r.deg;
}
Now you can easily sort your list<Node> structure, and you can use lower_bound to find the right position in AddOneTerm:
void CPolynomial::AddOneTerm(Node term)
{
auto it = std::lower_bound(m_Polynomial.begin(), m_Polynomial.end(), term);
if (it != m_Polynomial.end() && term.deg == it->deg)
{
it->cof += term.cof;
}
else
{
m_Polynomial.insert(it, term);
}
}
I'm trying to create a program that takes a polynomial function from the user, counts the number of terms it has, creates an array large enough to store all of the terms, and then stores the terms there. The problem is that I'm not quite sure how to add a private class variable (or more specifically, a string array) AFTER the program determines how the large the function is. I need this string array to be a private class variable because I want to be able to access its contents through other class methods to do things like, for example, cout each of the function terms.
main.cpp:
#include <iostream>
#include <string>
#include "Function.h"
using namespace std;
int main()
{
Function func1;
func1.coutFuncTerms();
func1.coutFunc();
return 0;
}
Function.h:
#ifndef FUNCTION_H
#define FUNCTION_H
#include <iostream>
#include <string>
#include "Function.h"
using namespace std;
class Function
{
public:
Function();
~Function();
void removePlus(string*);
void removeWhitespace(string*);
void setFuncTerms();
void splitTerms();
void coutFuncTerms();
void coutFunc();
void coutTerms(string);
protected:
private:
string func;
int funcTerms;
};
#endif
Function.cpp:
#include <iostream>
#include <string>
#include "Function.h"
using namespace std;
// Function Constructor
//
// Stores a function inputted by the user
// Adds a null character ('\0') to the end of a string
// Erases a redundant '+' sign at the beginning of a string if there's one there
// Erases any whitespace characters in a string
// Stores the number of terms in the function
Function::Function()
{
getline(cin, func);
setFuncTerms();
//splitTerms();
}
Function::~Function()
{
}
// removePlus Function
//
// Erases a redundant '+' sign at the beginning of a string if there's one there
void Function::removePlus(string* func)
{
if(func->at(0) == '+')
{
func->erase(0, 1);
}
}
// removeWhitespace Function
//
// Erases any whitespace characters in a string
void Function::removeWhitespace(string* func)
{
for(int x = 0; unsigned(x) < func->length() - 1; x++)
{
while(func->at(x) == ' ' || func->at(x) == '\t')
{
func->erase(x, 1);
}
}
}
// setFuncLength Function
//
// Finds the number of terms in a Function object's 'func' variable
// Assigns this number to the object's 'funcLength' variable
void Function::setFuncTerms()
{
funcTerms = 0;
for(int funcTerm = 0; unsigned(funcTerm) < func.length(); funcTerm += 1)
{
bool isAPotentialTerm = false;
bool isATrueTerm = false;
if(func.at(funcTerm) == '+' || func.at(funcTerm) == '-')
{
isAPotentialTerm = true;
}
if(isAPotentialTerm == true)
{
for(int newFuncTerm = funcTerm + 1; unsigned(newFuncTerm) < func.length(); newFuncTerm += 1)
{
if(func.at(newFuncTerm) == '+' || func.at(newFuncTerm) == '-')
{
break;
}
if(func.at(newFuncTerm) != ' ' && func.at(newFuncTerm) != '\t')
{
isATrueTerm = true;
break;
}
}
}
if(isATrueTerm)
{
funcTerms++;
}
}
}
// splitTerms Function
//
// Calls the splitTerm function for each term in 'func' according to the function array 'funcArray'
void Function::splitTerms()
{
string funcArray[funcTerms];
int tempFuncLength = 0;
for(int funcTerm = 0; unsigned(funcTerm) < func.length(); funcTerm += 1)
{
bool isAPotentialTerm = false;
bool isATrueTerm = false;
if(func.at(funcTerm) == '+' || func.at(funcTerm) == '-')
{
isAPotentialTerm = true;
}
if(isAPotentialTerm == true)
{
for(int newFuncTerm = funcTerm + 1; unsigned(newFuncTerm) < func.length(); newFuncTerm += 1)
{
if(func.at(newFuncTerm) == '+' || func.at(newFuncTerm) == '-')
{
break;
}
if(func.at(newFuncTerm) != ' ' && func.at(newFuncTerm) != '\t')
{
isATrueTerm = true;
break;
}
}
}
if(isATrueTerm)
{
string temp;
for(; unsigned(funcTerm) < func.length() && func.at(funcTerm) != '+' && func.at(funcTerm) != '-'; funcTerm += 1)
{
funcArray[tempFuncLength].append(1, func.at(funcTerm));
}
tempFuncLength++;
}
}
for(int x = 0; x < funcTerms; x++)
{
cout << "Term " << x + 1 << " is: " << funcArray[x] << endl;
}
}
void Function::coutFuncTerms()
{
cout << "Terms: " << funcTerms << endl;
}
void Function::coutFunc()
{
cout << "Function: " << func << endl;
}
void Function::coutTerms(string funcArrayTerm)
{
/*for(int x = 0; x < funcLength; x++)
{
cout << "Term " << x << " is: " << funcArray[x] << endl;
}*/
//cout << funcArray[0] << endl;
}
I highly recommend you change your design.
A function is a container of terms. So let's define a term:
A term minimally has a coefficient and an exponent:
struct Fundamental_Term
{
double coefficient;
int exponent;
};
If your function is only in terms of one variable, all you need is the Fundamental_Term. Otherwise, you need to have the base variable name:
struct Term_With_Base
: public Fundamental_Term
{
std::string variable_name;
};
Note: if you can't use inheritance, copy the member variables of Fundamental_Term into Term_With_Base.
Remember a function is a collection or container of terms. Assuming a function with multiple bases, we can declare:
struct Function
{
std::vector<Term_With_Base> terms;
};
Evaluation of Terms
To evaluate a function, f(x), all terms must be evaluated and their results summed.
This decomposes into two requirements: 1) Terms must have an evaluation method; 2) The function class must have an evaluation method that sums the terms.
So, we add an evaluation function to the base class:
struct Fundamental_Term
{
double coefficient;
int exponent;
double evaluate(double value)
{
return coefficient * pow(value, exponent);
}
};
struct Function
{
std::vector<Term_With_Base> terms;
double evauate(double value)
{
const unsigned int quantity = terms.size();
double result = 0.0;
for (unsigned int i = 0; i < quantity; ++i)
{
result = result + terms[i].evaluate(value);
}
return result;
}
};
When creating a function from a string, a preference is to create a constructor of Fundamental_Term that takes a string parameter. The term object should read its coefficient, variable name and exponent, not the Function container.
For more examples, search StackOverflow for "c++ parse term evaluation".
Edit 1: Inserting terms
One method to insert terms, is to have a method in the term data structure that loads a term from a string:
bool
Fundamental_Term ::
load_from string(const std::string& input,
unsigned int & start_position)
{
bool term_is_valid = false;
// Parse the string and load appropriate fields.
// Set the start position to the first position after the valid term.
// Set term_is_valid to true if the term has valid syntax.
return term_is_valid;
}
The Function object would have a member to load terms from a string.
bool
Function ::
load_terms_from_string(const std::string& input)
{
Term_With_Base term;
unsigned int position_in_string = 0;
bool term_is_valid = true;
while (term_is_valid && (position_in_string < input.size()))
{
term_is_valid = term.load_from_string(input, position_in_string);
if (term_is_valid)
{
terms.push_back(term);
}
}
}
The std::vector used to contain the terms will expand as necessary with each additional term that is parsed. The loop will terminate when the string is parsed or there is an invalid term.
I'm new at programming so I'm not really sure what the problem is. The errors I keep getting are in the AddTopping(string toppings). One is illegal reference to non-static member PizzaOrder::toppings . The other one is 'initializing' can not convert for " to std::string.
This is what I've got at the moment:
#include <iostream>
#include <string>
using namespace std;
class PizzaOrder
{
private:
static const int MAX_SIZE=1000;
int size;
string toppings[MAX_SIZE];
int num_toppings;
public:
static const string toppings_offered [4];
static const int DEFAULT_SIZE= 0;
static const int DEFAULT_TOPPINGS=0;
static const double topping_base_cost;
static const double base_price;
PizzaOrder ();
PizzaOrder (int size);
bool SetSize (int size);
int GetSize () {return size;}
static string AddTopping (string topping);
static int AddTopping (int n);
static double GetPrice ();
static string StringizeSize ();
static string GetToppings ();
static void DisplayPizza();
};
const double PizzaOrder :: topping_base_cost= .5;
const double PizzaOrder :: base_price= 5;
const string PizzaOrder ::toppings_offered[4]={"olives","bell peppers","onions","pepperoni"};
int main ()
{
PizzaOrder order;
char pizza_size;
int topping_choice;
short array_size = sizeof(order.toppings_offered)/sizeof(order.toppings_offered[0]);
cout << "Would you like a size [S]small , [M]medium, [L]large pizza or [Q]quit?" <<endl;
while ( pizza_size != 'Q' || pizza_size != 'q')
{
cin >> pizza_size;
if( pizza_size == 'S' || pizza_size == 's')
order.SetSize(0);
if(pizza_size == 'M' || pizza_size == 'm')
order.SetSize(1);
if(pizza_size == 'L' || pizza_size == 'l')
order.SetSize(2);
while (topping_choice !=0)
{
cout << "Current Pizza : " << order.StringizeSize () << order.GetToppings ();
cout <<"Select an item by number. (Enter 0 when done)" << endl;
for (int i=0; i< array_size-1; i++)
{
cout << (i+1) << ". " << order.toppings_offered[i]<< endl;
}
cout << "Selection?";
cin >>topping_choice;
order.AddTopping(topping_choice);
}
}
return 0;
}
PizzaOrder::PizzaOrder()
{
size=DEFAULT_SIZE;
num_toppings=DEFAULT_TOPPINGS;
}
PizzaOrder::PizzaOrder(int size)
{
if(!SetSize(size))
size=DEFAULT_SIZE;
}
bool PizzaOrder::SetSize(int size)
{
if (size != 0 || size !=1 || size !=2)
return false;
this -> size=size;
return true;
}
string PizzaOrder::AddTopping(string topping)
{
string temp_toppings[]={toppings};
short array_size = sizeof(temp_toppings)/sizeof(temp_toppings[0]);
num_toppings+1;
toppings[num_toppings];
for(int k=0; k<array_size-1; k++)
{
toppings[k]= num_toppings[k];
}
toppings[num_toppings]= topping;
}
int PizzaOrder::AddTopping(int n)
{
string temp_toppings[]={toppings};
short array_size = sizeof(temp_toppings)/sizeof(temp_toppings[0]);
num_toppings+1;
toppings[num_toppings];
for(int k=0; k<array_size-1; k++)
{
toppings[k]= num_toppings[k];
}
toppings[num_toppings]=toppings_offered[n];
}
double PizzaOrder ::GetPrice()
{
double price;
double multiplier;
if(size==0)
multiplier=1;
if(size==1)
multiplier=1.15;
if (size==2)
multiplier=1.25;
price= (base_price*multiplier)+(num_toppings*topping_base_cost);
return price;
}
string PizzaOrder::StringizeSize()
{
if(size==0)
return "small";
if(size==1)
return "medium";
if (size==2)
return "large";
}
string PizzaOrder::GetToppings()
{
string temp= "";
for(int x=0,x<num_toppings-1, x++)
temp+= "+ " + toppings[x];
return temp;
}
void PizzaOrder::DisplayPizza()
{
cout << StringizeSize ()<< GetTopping () << GetPrice ();
}
You have a bunch of static functions that shouldn't be static, including AddTopping. Read up on static.
I'm not absolutely sure which line you're getting the "initializing cannot convert from" error on (please provide complete error information, including line numbers, in future questions), but I'd wager it's that first line in the integer overload of AddTopping. I gather that you're trying to copy the contents of the current "toppings" array member (inaccessible to you because you've declared the function static -- which is probably the reason that the type information is missing in the error message) into a temp_toppings array. The line, as you've written it, is not valid C++. I suggest you Google "C++ copy array" and read the first link, which is a nice array tutorial on the augustcouncil.com Web site.
Even if you get rid of all mistakes, you have a infinite loop running with the very beginning condition in the while loop -
The intention of this loop is to break from the loop, I assume. But it never does so -
while ( pizza_size != 'Q' || pizza_size != 'q')
{
// .....
}
When pizza_size is equal to Q, with the || condition, the condition turns out to be true and an infinite loop. It should be -
pizza_size = 'Q' => false || true => true -> while loop continues
pizza_size = 'q' => true || false => true -> while loop continues
while ( (pizza_size != 'Q') && (pizza_size != 'q'))
{
// .....
}
Hope it helps at later stages.
class string
{
public:
friend istream& operator >> ( istream& is, string& str);
private:
char *m_data;
};
int main()
{
string str;
freopen("in.txt","r",stdin);
while( cin >> str)
{
cout < < str < < endl;
}
return 0;
}
the content of in.txt are:
asdfsfgfdgdfg
in the overload function, i use is.get() to read those charaters one by one,but program jump out the circle when cin finish,that means cout will not run. on the other way,i try getchar() instead, but it can not jump out the circle.
question: is there any wrong in my idea towards this function? or there is another better way to fulfill. thx :)
=========================================================================================
new edit:
here my code:
#Artem Barger
code detail
#include <iostream>
namespace Str
{
class string
{
public:
string():k(0){}
friend bool operator >> ( std::istream& is, string& str)
{
int size = 100;
char m;
if( (m = getchar()) && m == -1)
return false;
str.m_data = new char[size];
do
{
if( str.k == size)
{
size *= 2;
char *temp = new char[size];
for( int j = 0; j < str.k; ++j)
{
char *del = str.m_data;
temp[j] = *str.m_data++;
delete del;
}
str.m_data = temp;
temp = NULL;
}
str.m_data[str.k++] = m;
}while( (m = getchar()) && m != -1);
return true;
}
friend void operator << ( std::ostream& os, string& str)
{
os << str.m_data;
str.k = 0;
delete []str.m_data;
}
private:
char *m_data;
int k;
};
}
using namespace Str;
int main()
{
string str;
while( std::cin >> str)
{
std::cout << str;
}
return 0;
}
still have some problem in the content of
do
{
}while();
Perhaps you could rewrite your code like this, which should fix your problem:
bool success = true;
while (sucess) {
success = cin >> str;
cout << str;
}
However, I don't understand why you still want the cout to go ahead - if the cin call didn't succeed, you will only be printing the old contents of the string - you do not clear it anywhere (unless you do so in other code which you haven't posted here).