Redefinition and previous definition error - c++

hpp file :
#pragma once
#include <string>
using namespace std;
class LiczbaException: public exception{
private:
string s;
public:
LiczbaException(string ss) :
s(ss){
};
virtual ~ LiczbaException() throw () {
};
virtual const char * erorrr() const throw () {
return s.c_str();
}
};
class RzymArab {
private:
static string liczby[13];
static int arabliczby[13];
public:
static int rzym2arab (string rzym);
static string arab2rzym (int arab) throw(LiczbaException);
};
string RzymArab::liczby[13] = {"I","IV","V","IX","X","XL","L","XC","C","CD","D","CM","M"};
int RzymArab::arabliczby[13] = {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000};
test cpp :
#include <iostream>
#include <cstdlib>
#include <cstring>
#include "RzymArab.hpp"
using namespace std;
int main(int argc, char * argv[]) {
bool sprawdz = true;
int t = 0;
string pom;
for (int l = 1; l < argc; l++) {
try {
t = atoi(argv[l]);
if (t == 0)
throw pom;
else
sprawdz = true;
} catch (string pom){
sprawdz = false;
}
if (sprawdz == false){
try{
int wynikk = RzymArab::rzym2arab(argv[l]);
if (argv[l] != RzymArab::arab2rzym(wynikk))
cout << "Nieistniejaca liczba" << endl;
else
cout << wynikk << "\n";
} catch (LiczbaException& w) {
cout << w.what() << endl;
}
} else {
try {
string wynik = RzymArab::arab2rzym(t);
cout << wynik << "\n";
} catch (LiczbaException& w){
cout << w.what() << endl;
}
}
}
return 0;
}
cpp file:
#include <iostream>
#include <cstdlib>
#include <cstring>
#include "RzymArab.hpp"
using namespace std;
class RzymArab
{
static int rzym2arab(string rzym) {
int wynik = 0;
for (int i = 0; i < rzym.length(); i++) {
int wart1 = 0;
int wart2 = 0;
for (int j = 0; j < 13; j++) {
if (rzym.at(i)==liczby[j].at(0)) {
wart1 = arabskie[j];
}
}
for (int k = 0; k < 13; k++) {
if (i<rzym.length()-1) {
if (rzym.at(i+1)==liczby[k].at(0))
wart2 = arabskie [k];
}
}
if (wart1 >= wart2) {
wynik+=wart1;
}else {
wynik+=(wart2 - wart1);
i = i + 1;
}
}
if (wynik > 3999)
cout << "Za duza liczba!";
if (wynik == 0)
cout << "Something get's wrong!";
return wynik;
}
static string arab2rzym(int arab) throw (LiczbaException) {
string wynik = "";
if (arab < 1 || arab > 3999)
throw LiczbaException("Zla podstawa");
for (int i = 0; i < 13; i++) {
while (arab >= arabskie[i]) {
wynik += liczby[i];
arab -= arabskie[i];
}
}
return wynik;
}
};
I got the errors while compiling:
" RzymArab.cpp:10:7: error: redefinition of 'class RzymArab'
class RzymArab
In file included form RzymArab.cpp:5:0:
RzymArab.hpp:26:7: error: previous definition of 'class RzymArab'
class RzymArab"
I don't know what is wrong, maybe something with pragma once but when i use old guard nothing change.

The class RzymArab is defined in the header (hpp) and in the body (cpp), this violates the one definition rule of C++ (ODR).
In the body, delete the class definition and define the members as following:
int RzymArab::rzym2arab(string rzym)
{
....
}
string RzymArab::arab2rzym(int arab) throw (LiczbaException)
{
....
}
Furthermore, defining RzymArab::liczby and RzymArab::arabliczby in the header also violates the ODR once the header is included more than once. So, move these definitions to the body too.
Finally, don't import namespaces in a header file (using namespace xxx). Generally, users of a header file expect their namespaces not to be polluted by including a header.
PS: You want to use a named constant instead of the magic number 13.
Exception specifications (throw (xx)) are an obsolete feature of C++. Since C++11 they have been superceded by noexcept specifiers. One reason that exception specifications have been made obsolete is that it is generally difficult to ensure that none but the specified exceptions are thrown. If the specification is violated, your program will by default terminate().

Related

Struct doesn't print with cout

I'm trying to print the structure in an array whose int prejetih member is highest.
#include <iostream>
using namespace std;
struct Tekma {
int prejetih;
};
Tekma najvec_kosev(Tekma tekme[]) {
int maksi = 0, index = 0;
for (int i = 0;i < 2;i++) {
if (maksi < tekme[i].prejetih) {
index = i;
maksi = tekme[i].prejetih;
}
}
return tekme[index];
}
void vpis(Tekma tekme[]) {
for (int i = 0;i < 2;i++)
cin >> tekme[i].prejetih;
}
int main() {
Tekma tekme[2];
vpis(tekme);
cout << najvec_kosev(tekme);
}
The compiler reports
C++ no operator matches these operands
operand types are: std::ostream << Tekma
over cout << najvec_kosev(tekme);
Here using a solution with std::vector and fixing your cout problem:
#include <iostream>
#include <vector>
using namespace std;
struct Tekma {
int prejetih;
};
Tekma najvec_kosev(vector<Tekma>& tekme) {
Tekma lowest = tekme[0]
for(auto& t : tekme) {
if(lowest.prejetih < t.prejetih) {
lowest = t;
}
}
return lowest ;
}
void vpis(vector<Tekma>& tekme) {
int input;
while(true) {
cin >> input;
// Check if the input is valid else quit the loop.
if(input == valid) {
Tekma newStruct = {input};
tekme.push(newStruct);
}
else {
// Stop the loop
break;
}
}
}
int main() {
vector<Tekma> tekme;
vpis(tekme);
cout << najvec_kosev(tekme).prejetih; // This fixes your error.
}

Using array from private access specifier

Here I have an array within the private section of my class which is unable to retain the values set in different members of the clas; during the fight sequence both of the values in the array equate to 0.
#include <iostream>
#include <string>
#include<math.h>
#include<cstdlib>
using namespace std;
class champions {
private:
int health_array[2] = { };
int attack_array[2] = { };
public:
void health_attack_set() {
int health_set{};
int attack_set{};
for (int i = 0; i < 2; i++) {
health_array[i] = health_set;
attack_array[i] = attack_set;
}
}
void fight_sequence(int random_champion, int random_opponent) {
cout << "FIGHT\n\n";
while (health_array[random_champion] > 0 or health_array[random_opponent] > 0) {
(health_array[random_opponent] -= attack_array[random_champion]);
if (health_array[random_opponent] <= 0) {
break;
}
(health_array[random_champion] -= attack_array[random_opponent]);
}
if (health_array[random_champion] > 0) {
cout << "CHAMPION 1 WINS!!!";
}
if (health_array[random_opponent] > 0) {
cout << "CHAMPION 2 WINS!!!";
}
if (health_array[random_champion] == 0 && health_array[random_opponent] == 0) {
cout << "NO ONE WINS!!";
}
}
void champion_1() {
health_attack_set();
health_array[0] = 400;
attack_array[0] = 150;
}
void champion_2() {
health_attack_set();
health_array[1] = 500;
attack_array[1] = 100;
}
};
int main() {
champions fight;
fight.fight_sequence(0, 1);
return 0;
}
I believe it may be a simple mistake but hard to spot; thank you for any help that is given.
I think your problems are coming from not understanding how to structure your code in the presence of classes and multiple objects. I have restructured your code below in a cleaner and more common way (it is not the only way to do it, but it is more typical). Hopefully there are not typos.
#include <iostream>
#include <string>
#include<math.h>
#include<cstdlib>
using namespace std;
class Champion{
public:
int health;
int attack;
Champion(int health_, int attack_) : health(health_), attack(attack_) {
}
};
void fight_sequence(Champion& champion, Champion& opponent) {
cout << "FIGHT\n\n";
while (champion.health > 0 || opponent.health > 0) {
(opponent.health -= champion.attack);
if (opponent.health <= 0) {
break;
}
(champion.health -= opponent.attack);
}
if (champion.health > 0) {
cout << "CHAMPION 1 WINS!!!";
}
if (opponent.health > 0) {
cout << "CHAMPION 2 WINS!!!";
}
if (champion.health == 0 && opponent.health == 0) {
cout << "NO ONE WINS!!";
}
}
int main() {
Champion champion_1(400, 150);
Champion champion_2(500, 100);
fight_sequence(champion_1, champion_2);
return 0;
}

Why does my code have an "Apple Mach-O Linker Error?"

I get this error when i build the program: Apple Mach-O Linker (ld) Error Linker Command failed with exit code 1. Usually when I try to fix this error, its because the file with the main function is #include-ing a file more than once. However, I do not believe that that is the case this time. I am also notified by X Code that the duplicate symbol _passed in: ranker.o and olympic.o.
//competitor.h
#ifndef __Olympic_Lab__competitor__
#define __Olympic_Lab__competitor__
#include <iostream>
using namespace std;
class Competitor {
char* name = nullptr;
int laneAssignment;
float time;
public:
Competitor(char n[], int lane);
~Competitor();
void setTime(float f);
char* getName(){ return name; }
int getLane(){ return laneAssignment; }
float getTime(){ return time; }
void print(){ cout << name << endl; }
};
#endif
//competitor.cpp
#include "competitor.h"
Competitor::Competitor(char n[], int lane){
name = n;
laneAssignment = lane;
}
Competitor::~Competitor(){
//does nothing for now
}
void Competitor::setTime(float t){
time = t;
}
//ranker.h
#ifndef __Olym__ranker__
#define __Olym__ranker__
#include <vector>
#include "competitor.h"
using namespace std;
int passed = 0;
class Ranker {
bool boolean = true;
public:
vector<Competitor*> rv;
Ranker(int lanes);
~Ranker();
int addList(Competitor* c);
Competitor* getLane(int lane);
Competitor* getFinish(int finish);
int getFilled();
};
#endif
//ranker.cpp
#include "ranker.h"
Ranker::Ranker(int lan){
rv.resize(lan - 1);
for(int i = 0; i <= rv.size(); i++){
rv[i] = nullptr;
}
}
Ranker::~Ranker(){
for(int i = 0; i <= rv.size(); i++){
delete rv[i];
}
}
int Ranker::addList(Competitor *c){
if(c != NULL && passed <= 4){
rv[passed++] = c;
return passed - 1;
}
return 0;
}
Competitor* Ranker::getLane(int lane){
for(int i = 0; i <= rv.size(); i++){
if(rv[i]->getLane() == lane && rv[i] != NULL){
return rv[i];
}
}
return rv[0];
}
Competitor* Ranker::getFinish(int finish){
if(boolean){
Competitor *temp = nullptr;
int highestIndex;
for(int i = rv.size(); i >= 0; i--){
highestIndex = i;
for(int j = i; j >= 0; j--){
if(rv[j] != nullptr && rv[highestIndex] != nullptr){
if(rv[j]->getTime() > rv[highestIndex]->getTime())
highestIndex = j;
}
}
temp = rv[i];
rv[i] = rv[highestIndex];
rv[highestIndex] = temp;
}
delete temp;
temp = *new Competitor*;
boolean = false;
}
return rv[finish - 1];
}
int Ranker::getFilled(){
int filled = 0;
for(int i = 0; i <= rv.size(); i++){
if(rv[i] != NULL){
filled++;
}
}
return filled;
}
//olympic.h
#ifndef _Olympic_Lab__olympic__
#define _Olympic_Lab__olympic__
#include "ranker.h"
#endif
//olympic.cpp
#include "olympic.h"
int main(){
const int lanes = 4;
Ranker rank(lanes);
Competitor* starters[4];
starters[0] = new Competitor("EmmyLou Harris", 1);
starters[1] = new Competitor("Nanci Griffith", 2);
starters[2] = new Competitor("Bonnie Raitt", 3);
starters[3] = new Competitor("Joni Mitchell", 4);
starters[0]->setTime((float)12.0);
starters[1]->setTime((float)12.8);
starters[2]->setTime((float)11.0);
starters[3]->setTime((float)10.3);
for(int i = 0; i < lanes; i++){
rank.addList(starters[i]);
}
cout << "Competitors by lane are:" << endl;
for(int i = 1; i <= lanes; i++)
rank.getLane(i)->print();
cout << "Rankings by finish are:" << endl;
for(int i = 1; i <= lanes; i++)
rank.getFinish(i)->print();
for(int i = 0; i < lanes; i++){
delete starters[i];
}
}
It would be appreciated if someone could assist me in finding exactly what causes this error. Thanks!
If you declare a variable in a header it will be duplicated in every file that includes the header.
So int passed = 0; in ranker.h is going to give you a lot of grief. ranker and olympian both have allocated a different passed and the linker now has no clue which one is the real passed.
So what you probably want is
extern int passed;
in ranker.h to declare that passed will exist at some point, if it doesn't yet, so it doesn't need to be allocated. The compiler will happily carry on and allow you to use passed.
And then in ranker.cpp, declare
int passed = 0;
to allocate passed and satisfy the linker. Now you have only one passed and anyone who includes ranker.h can see and use it.
If you want more than one passed, you have to do something else so that they don't share the same name and scope, but this doesn't look like your goal.
Off topic: resist the urge to put using namespace std;in a header file. It can lead to future problems that can be very hard to debug. More here: Why is "using namespace std" considered bad practice?

Reference array from class in an other class

I'm writing a program that converts decimal numbers into binary, octal and hexadecimal. I'm doing each conversion in different class, but i want to use the binary form of the number which is stored in an array(bin[31]) inside the 1st class. Is there a way to use that array in my other classes? My teacher said i should use references, but i don't know how to do it. My files are:
Binary.h
#ifndef BINARY_H
#define BINARY_H
class Binary{
public:
int num_;
static int bin[31];
int i;
int x;
Binary();
void Set(int temp);
int Get();
void ChangeToBinary();
void ChangeToBinaryComplement();
void TwoComplement();
void PrintBinary();
~Binary();
};
# endif
Binary.cpp
#include <stdio.h>
#include <iostream>
#include "Binary.h"
#include "Octal.h"
using namespace std;
Binary::Binary(){
}
void Binary::Set(int temp){
num_ = temp;
}
int Binary::Get(){
return num_;
}
void Binary::ChangeToBinary(){
x = 1;
for (i=0;i<30;i++){
x*=2;
}
for (i = 0; i<31;i++){
if (num_ -x >= 0){
bin[i] = 1;
num_ = num_ -x;
}
else{
kettes[i] = 0;
} x=x/2;
}
}
void Binary::ChangeToBinaryComplement(){
for (i=0;i<31;i++){
if (bin[i] ==0){
bin[i] = 1;
}
else {
bin[i] = 0;
}
}
}
void Binary::TwoComplement(){
for(i=30;i>0;i--){
if(bin[i] == 0){
bin[i] = 1;
break;
} else{
bin[i] = 0;
}
}
}
void Binary::PrintBinary(){
for (i=0;i<31;i++){
cout << bin[i];
}
cout << " " << endl;
}
Binary::~Binary()
{
}
Octal.h
#ifndef OCTAL_H
#define OCTAL_H
class Octal{
private:
int* oct_ = new int[10];
int i;
public:
Octal();
void ConvertToOctal();
void PrintOctal();
~Octal();
};
#endif
Octal.cpp
#include <stdio.h>
#include <iostream>
#include "Binary.h"
#include "Octal.h"
using namespace std;
Octal::Octal()
{
}
void Octal::ConvertToOctal(){
int k = 0;
int z = 0;
int o = 0;
for(i=0;i<31;i++){
if((help[i] ==1) && (k==0)){
z = z + 4;
k = k + 1;
}
else if((help[i] ==1) && (k==1)){
z = z + 2;
k = k + 1;
}
else if((help[i] ==1) && (k==2)){
z = z + 1;
k = k + 1;
}
else{
k = k + 1;
}
if(k==3){
oct_[o]=z;
z=0;
k=0;
o = o + 1;
}
}
}
void Octal::PrintOctal(){
for(i=0;i<10;i++){
cout << oct_[i];
}
}
Octal::~Octal()
{
}
If you have to use your own classes
You can add a method inside the Binary class that lets you get access to the pointer to the array containing the data. The method would probably look like this:
int getData(){
return bin;
}
You can also access the array directly using Binary::bin, which will also give you a pointer to the first element of the array.
It would be much better tho if you changed the array type from int to bool or char. If you want to do it even better - use the vector< bool > template class. It's basically an array of bools. You can read about it in the C++ Reference
If you just need the funcionality
You should really just use the standard manipulators. There is no real reason to reinvent the wheel. The easiest way to do this is by inputting a number into a stream, and outputing it into a string. Like this:
#include<string> // string
#include<sstream> // stringstream
#include<iostream> // cin, cout
#include<iomanip> // setbase
using namespace std;
int main(){
int number;
cin >> number;
stringstream parser;
parser << setbase(16) << number;
string convertedNumber;
parser >> convertedNumber;
cout << endl << convertedNumber << endl;
return 0;
}
Of course you can change the base inside the setbase manipulator.

Crashing when objects are deleted

It's crashing at the very end of the main() function where it needs to delete the starters objects. The error message that pops up when I run the program says: Debug assertion failed! Expression: _BLOCK_IS_VALID(pHead->nBlockUse). How do i fix it from crashing when deleting the starters objects?
#include <iostream>
#include <fstream>
#include "olympic.h"
using namespace std;
ofstream csis;
int main() {
const int lanes = 4;
Ranker rank(lanes);
csis.open("csis.txt");
// First make a list of names and lane assignments.
Competitor* starters[lanes];
starters[0] = new Competitor("EmmyLou Harris", 1);
starters[1] = new Competitor("Nanci Griffith", 2);
starters[2] = new Competitor("Bonnie Raitt", 3);
starters[3] = new Competitor("Joni Mitchell", 4);
// The race is run; now assign a time to each person.
starters[0]->setTime((float)12.0);
starters[1]->setTime((float)12.8);
starters[2]->setTime((float)11.0);
starters[3]->setTime((float)10.3);
// Put everyone into the ranker.
for (int i = 0; i < lanes; i++)
rank.addList(starters[i]);
// Now print out the list to make sure its right.
cout << "Competitors by lane are:" << endl;
csis << "Competitors by lane are:" << endl;
for (int i = 1; i <= lanes; i++)
rank.getLane(i)->print();
// Finally, show how they finished.
cout << "Rankings by finish are:" << endl;
csis << "Rankings by finish are:" << endl;
for (int i = 1; i <= lanes; i++)
rank.getFinish(i)->print();
for (int i = 0; i < lanes; i++)
delete starters[i];
csis.close();
}
ranker.cpp:
#include "ranker.h"
#include "competitor.h"
#include <stdlib.h>
Ranker::Ranker(int lanes) {
athlete = new Competitor*[lanes];
numAthletes = 0;
maxAthletes = lanes;
}
int Ranker::addList(Competitor* starter) {
if (numAthletes < maxAthletes && starter != NULL) {
athlete[numAthletes] = starter;
numAthletes++;
return numAthletes;
}
else
return 0;
}
Competitor* Ranker::getLane(int lane) {
for (int i = 0; i < numAthletes; i++) {
if (athlete[i]->getLane() == lane) {
return athlete[i];
}
}
return NULL;
}
Competitor* Ranker::getFinish(int position) {
switch(position) {
case 1:
return athlete[3];
break;
case 2:
return athlete[2];
break;
case 3:
return athlete[1];
break;
case 4:
return athlete[0];
break;
}
return NULL;
}
int Ranker::getFilled() {
return numAthletes;
}
Ranker::~Ranker() {
delete [] athlete;
}
competitor.h:
#ifndef _COMPETITOR_H
#define _COMPETITOR_H
class Competitor {
private:
char* name;
int lane;
double time;
public:
Competitor(char* inputName, int inputLane);
Competitor();
void setTime(double inputTime);
char* getName();
int Competitor::getLane();
double getTime();
void print();
~Competitor();
};
#endif
competitor.cpp:
#include "competitor.h"
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
Competitor::Competitor(char* inputName, int inputLane) {
name = inputName;
lane = inputLane;
}
Competitor::Competitor() {
name = 0;
lane = 0;
time = 0;
}
void Competitor::setTime(double inputTime) {
time = inputTime;
}
char* Competitor::getName() {
return name;
}
int Competitor::getLane() {
return lane;
}
double Competitor::getTime() {
return time;
}
void Competitor::print() {
cout << setw(20) << name << setw(20) << lane << setw(20) << setprecision(4) << time << endl;
}
Competitor::~Competitor() {
delete [] name;
}
Call stack:
before crash: http://i.imgur.com/d4sKbKV.png
after crash: http://i.imgur.com/C5cXth9.png
After you've added Competitor class, it seems the problem is that you delete its name in Competitor's destructor. But you assign it from string literal which can't really be deleted. I'm sure the stack trace leading to assertion will prove that.
One way of solving the problem would be using std::string to store the name.
Problem is when deleting the char* value on destructor, which is assigned with const char instead new char. So i have slightly changed the constructor to copy the const char to new char.
Competitor::Competitor(char* inputName, int charlen, int inputLane)
{
name = new char[charlen + 1];
memcpy(name , inputName, charlen );
name [charlen] = '\0';
lane = inputLane;
}