Compile in Linux/Unix issue C++ - c++

This is only part of an overall program and compiles and runs fine in Windows, however it does not like my strcpy in Linux/Unix. What am I doing wrong and how can I fix it? Also a note, I am not allowed to use string, only cstring.
Song.cpp
#include "Song.h"
Song::Song()
{
}
Song::~Song()
{
}
Song::Song(char* title, char* artist, char* duration, char* album)
{
strcpy(this->title,50,title);
strcpy(this->artist, 50, artist);
strcpy(this->duration, 50, duration);
strcpy(this->album, 50, album);
}
void Song::setTitle(char* title)
{
this->title= title;
}
void Song::setArtist(char* artist)
{
this->artist = artist;
}
void Song::setDuration(char* duration)
{
this->duration= duration;
}
void Song::setAlbum(char* album)
{
this->album= album;
}
char* Song::getTitle()
{
return this->title;
}
char* Song::getArtist()
{
return this->artist;
}
char* Song::getDuration()
{
return this->duration;
}
char* Song::getAlbum()
{
return this->album;
}
Song.h
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include <cctype>
using namespace std;
class Song
{
private:
char* title;
char* artist;
char* duration;
char* album;
public:
Song();
~Song();
Song(char* title, char* artist, char* duration, char* album);
void setTitle(char* title);
void setArtist(char* artist);
void setDuration(char* duration);
void setAlbum(char* album);
char* getTitle();
char* getArtist();
char* getDuration();
char* getAlbum();
};

You haven't allocated any memory for strcpy to copy into. Thus your constructor invokes undefined behavior.
You need to allocate a character array first. But then you also need to deallocate it in each of your setters. Otherwise the memory will be leaked, since you're reassigning the pointer that manages it.

Related

I am trying to solve the problem in C++ Files and Streams

#include <iostream>
class Model
{
public:
Model(const char *a)
{
message=a;
}
const char *car() { return message; }
const char *message;
};
class ModelCar
{
public:
ModelCar(const char *sn, const char *b="c")
{
filename=strdup(sn);
f=fopen(sn,b);
if (f==NULL)
{
throw Model("File can't be opened");
}
}
~ModelCar()
{
delete [] filename;
if (fclose(f)<0)
{
throw Model("File can't be closed");
}
}
void read(char *buf, int size)
{
if (fread(buf, 1, size, f)!=size)
{
throw Model("File can't be read");
}
}
const char *filename;
FILE *f;
};
Why I am getting error: ‘strdup’ was not declared in this scope , I tried and add #include <string.h> but still getting error
Can anyone please help me what is wrong in this code
First of all I suggest you to fix some problems with the code:
1.
delete [] filename;
filename=strdup(sn);
Okay your delete function suggests that your filename is a dynamic array which you never intialized. Also have you looked at what strdup returns, it returns a dynamic char, not an dynamic array. I would suggest you change:
delete [] filename;
to
free(filename);

Why I get this random weird number C++

I am new to using pointers with c++, so I am trying this small code but the problem is that when i try to print name i get this random weird number \364\277\357\376\326\241+\310\364\277\357\376\310. This is not the memory address, which is confusing and what confuses me more that when i replace name with getName() it works perfectly and prints the name! Thanks you!!
Person.cpp
#include "Pesron.hpp"
#include <string>
#include <iostream>
using namespace std;
Person:: Person()
{
}
Person::Person(string Name, int Age)
{
name=&Name;
age=Age;
}
void Person:: setName(string Name)
{
name=&Name;
}
void Person:: setAge(int Age)
{
age=Age;
}
string Person:: getName()
{
return *name;
}
int Person:: getAge()
{
return age;
}
void Person:: display()
{
cout<<*name<<" "<<age<<" ";
}
Person::~Person()
{
}
Student.cpp
#include "Student.hpp"
Student:: Student(string Name, int Age,int Grades, int ID):Person(Name , Age)
{
grades=Grades;
id=ID;
}
void Student:: setId(int ID)
{
id=ID;
}
int Student:: getId()
{
return id;
}
void Student:: setGrades(int Grades )
{
grades= Grades;
}
int Student:: getGrades()
{
return grades;
}
void Student:: display()
{
Person::display();
cout<<grades<<" "<<id<<endl;
}
main.cpp
#include "Pesron.hpp"
#include "Student.hpp"
#include "graduteStudent.hpp"
#include <iostream>
int main(int argc, const char * argv[]) {
// insert code here...
Student student("ZAID",21,2211,11);
student.display();
return 0;
}
Output
\364\277\357\376\326\241+\310\364\277\357\376\310 21 2211 11
Person::name looks like it is a std::string *. In Person::Person(string Name, int Age) you pass the paramater Name by value and then store the address of this local variable in name. When Name goes out of scope you have a dangling pointer.
(This also applies to void Person::setName(string Name))
Dereferencing Person::name is undefined behaviour, because the object it is pointing doesn't exist anymore. The solution is to simply store a std::string and not just a pointer to it.
So you get something like
class Person {
private:
std::string name;
int age;
public:
Person(std::string Name, int Age) : name(Name), age(Age) {}
};

No default constructor exists for class c++ [duplicate]

This question already has answers here:
Why does C++ allow us to surround the variable name in parentheses when declaring a variable?
(2 answers)
Closed 5 years ago.
Hello,
I'm trying to instantiate an anonymous object with a std::string variable 'name'. But intellisenen gives me error saying
E0291 no default constructor exists for class "Player" GoldGame e:\C++ Projects\Hello World\GoldGame\GoldGame.cpp 17
I have provided a constructor which can just take a std::string variable since other parameters are provided with default value.
Can you guys shed some light on this?
What confuses me even more is that when I change
Player(name);
to
Player a(name);
or to
Player("test");
then intellisense becomes totally fine with those.
GoldGame.cpp
#include "stdafx.h"
#include "Creature.h"
#include "Player.h"
#include <iostream>
#include <string>
int main()
{
std::cout << "Enter your name: ";
std::string name;
std::cin >> name;
Player(name);
return 0;
}
Creature.h
#pragma once
#include <string>
class Creature
{
public:
Creature(const std::string &name, const char symbol, const int health, const int damage, const int gold);
~Creature();
//getters
const std::string& getName() { return m_name; }
const char getSymbol() { return m_symbol; }
const int getHealth() { return m_health; }
const int getDamage() { return m_damage; }
const int getGold() { return m_gold; }
//health, gold and dead
void reduceHealth(const int healthMinus);
void addGold(const int gold);
bool isDead();
private:
std::string m_name;
char m_symbol;
int m_health;
int m_damage;
int m_gold;
};
Creature.cpp
#include "stdafx.h"
#include "Creature.h"
Creature::Creature(const std::string & name, const char symbol, const int health, const int damage, const int gold)
:m_name(name), m_symbol(symbol), m_health(health), m_damage(damage), m_gold(gold)
{
}
Creature::~Creature()
{
}
void Creature::reduceHealth(const int healthMinus)
{
m_health -= healthMinus;
}
void Creature::addGold(const int gold)
{
m_gold += gold;
}
bool Creature::isDead()
{
if (m_health>0)
{
return true;
}
else
{
return false;
}
}
Player.h
#pragma once
#include "Creature.h"
#include <string>
class Player :
public Creature
{
public:
Player(const std::string &name, const char symbol='#', const int health=10, const int damage=1, const int gold=0);
~Player();
const int getLevel() { return m_level; }
void levelUp();
bool hasWon();
private:
int m_level;
};
Player.cpp
#include "stdafx.h"
#include "Player.h"
Player::Player(const std::string & name, const char symbol, const int health, const int damage, const int gold)
:Creature(name,symbol,health,damage,gold)
{
}
Player::~Player()
{
}
void Player::levelUp()
{
++m_level;
}
bool Player::hasWon()
{
if (m_level>=20)
{
return true;
}
else
{
return false;
}
}
Player(name); does not do what you think it does. It declares a new variable name of type Player and calls a default constructor. If you want to instantiate an anonymous Player variable then you need to write
(Player(name));
// or
Player{name}; // list initialization since C++11

C++ - '(const char*)' not declared in scope? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I want to make a custom String class for C++. But when I do this:
g++ test.cpp sys/Base.h sys/Base.cpp
I get this error:
sys/Base.cpp: In function 'const char* Base::toChar()':
sys/Base.cpp:57:13: error: 'strval' was not declared in this scope
return strval;
^
sys/Base.cpp: In function 'std::string Base::toStr()':
sys/Base.cpp:60:20: error: 'strval' was not declared in this scope
return string(strval);
^
test.cpp
#include "sys/Base.h"
int main() {
Base::write("Hello there.\n");
return 0;
}
sys/Base.h
// Header file handling
#ifndef ARAVK_BASE_H
#define ARAVK_BASE_H
// Includes
#include <string>
// Global variables
#define EXIT_YAY 0
#define EXIT_ERR 1
using namespace std;
namespace Base {
// Classes:
class String {
static const char* strval;
public:
// Constructors:
String();
String(char[]);
String(const char*);
String(string);
// Destructors:
~String();
// Operators:
// =
void operator=(const String&);
void operator=(const char*&);
void operator=(const string&);
// Conversion:
const char* toChar() const;
string toStr() const;
};
// Functions:
// Input-Output:
// Write:
void write(String);
void write(string);
void write(const char*);
// Read:
String read();
// Executing:
String run(String);
}
#endif
sys/Base.cpp
// Including
#include "Base.h"
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
// Global variables
#define EXIT_ERR 1
#define EXIT_YAY 0
/* ------------------------ */
using namespace std;
namespace Base {
// Classes
// String functions
// Constructors
String::String() {
const char* strval = "";
}
String::String(const char* str) {
const char* strval = str;
}
String::String(string str) {
const char* strval = str.c_str();
}
String::String(char str[]) {
const char* strval = str;
}
// Destructors
String::~String() {
delete strval;
}
// Operators
// =
void String::operator=(const String &strp) {
strval = strp.toChar();
}
void String::operator=(const char* &strp) {
strval = strp;
}
void String::operator=(const string &strp) {
strval = strp.c_str();
}
// Conversion:
const char* toChar() {
return strval;
}
string toStr() {
return string(strval);
}
// Functions:
// Input-Output:
// Write
void write(String str) { printf(str.toChar()); }
void write(const char* str) { printf(str); }
void write(string str) { printf(str.c_str()); }
// Read
String read() { char str[100]; scanf("%s", str); return String(str); }
//TODO: More to come
// Executing
/*String run(String command) {
const char* cmd = command.toChar();
char buffer[128];
string result = "";
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
if (!pipe) throw runtime_error("popen() failed!");
while (!feof(pipe.get())) {
if (fgets(buffer, 128, pipe.get()) != NULL)
result += buffer;
}
return String(result);
}*/
String run(String command) {
char buffer[128];
std::string result = "";
const char* cmd = command.toChar();
FILE* pipe = popen(cmd, "r");
if (!pipe) throw std::runtime_error("popen() failed!");
try {
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
} catch (...) {
pclose(pipe);
throw;
}
pclose(pipe);
return String(result);
}
}
I'm not sure why this is happening. I think it's related to how I've declared/defined the const char* 'strval'. Can anybody help?
P.S: If the answer is too big, this project is on Github: AravK/C-Applications
Let's take a look at your constructor:
String::String() {
const char* strval = "";
}
This declares a local variable called strval. The variable is local to the constructor; it doesn't exist once execution of the constructor completes.
What you need instead is a member variable - declare it inside the class, but not inside a member method or constructor. In fact, you have already defined it as such in the header file:
class String {
static const char* strval;
So, remove the const char * from your constructor and add a class qualifier, so that the line becomes an assignment to the existing variable, rather than creation of a local:
String::String() {
String::strval = "";
}
And also change the return statement that is giving you the error:
return String::strval;
Or perhaps - and this is likely what you really wanted - remove the static qualifier from the variable definition, and change the constructor instead to just:
String::String() {
strval = "";
}
Furthermore, your destructor incorrectly deletes data that was not necessarily dynamically allocated, or which may belong to another object:
String::~String() {
delete strval;
}
This requires re-working. At the moment the simplest solution is to remove the delete strval altogether.
Your read() function potentially instigates a buffer overflow, by using scanf("%s") with a fixed size buffer and unknown input size:
char str[100]; scanf("%s", str); return String(str);
Finally, your command line:
g++ test.cpp sys/Base.h sys/Base.cpp
... should not include the header file (Base.h). You are specifying the units you want compiled, and Base.h is already included in Base.cpp; it is not a standalone unit that should be compiled invidually.
yes you did not define the variable in your class as a field.
there is 3 locals déclaration in your constructors.
just add it the way you have done in the header.
static const char* strval
and remove the définition in your constructors. Just keep the assignement part.
regards

Using dynamically allocated c-style strings in a class with copy and assignment operator giving unexpected results

This program compilation succeeded but it doesn't work.
I guess it has something to do with the assignment operator or the copy constructor but I can't figure out what...
Header:
class employee{
char *name;
unsigned int salary;
public:
employee();
employee(const char*);
employee(const char*,unsigned int);
employee (const employee&);
employee operator = (employee);
void init(const char*,unsigned int);
void print();
~employee();
};
Cpp:
#include <iostream>
#include <string>
#include "class.h"
using namespace std;
employee::employee() : salary(1000)
{
name=new char[20];
}
employee::employee(const char* ename) : salary(1000)
{
strcpy_s(name,20,ename);
}
employee::employee(const char* ename,unsigned int salary)
{
name=new char[20];
strcpy_s(name,20,ename);
this->salary=salary;
}
employee::employee(const employee& emp)
{
name=new char[20];
int i=0;
while (name[i]!='\0')
{
name[i]=emp.name[i];
i++;
}
salary=emp.salary;
}
void employee::init(const char* ename, unsigned int salary)
{
name=new char[20];
strcpy_s(name,20,ename);
this->salary=salary;
}
void employee::print()
{
cout<<"name: ";
int i=0;
while (name[i]!='\0')
{
cout<<name[i];
i++;
}
cout<<"\n"<<"salary: "<<salary<<endl;
}
employee employee::operator = (employee emp)
{
strcpy_s(name,20,const_cast <const char*>(emp.name));
emp.salary=salary;
return *this;
}
employee::~employee()
{
delete [] name;
}
Main:
#include <iostream>
#include "class.h"
using namespace std;
int main()
{
employee emp1 ("Bill Jones",5000),emp5("Michael Adams");
employee emp2;
emp2=emp1;
employee emp3;
emp3=emp2;
employee * workers= new employee [3];
workers[0]=emp3;
workers[1]= employee("katy Ashton");
delete [] workers;
}
While you may be doing this as an exercise, I recommend you read up on What is the Rule of Three? It and similar FAQs will guide you on how to properly overload copy/assignment operators and writing your own copy constructors and handle dynamic memory appropriately. For now, to avoid error-prone code, I suggest you use std::string and forgo overloading entirely. Your new class should look like this:
#include <iostream>
using namespace std;
class employee{
std::string name;
unsigned int salary;
public:
employee();
employee(std::string);
employee(std::string,unsigned int);
void init(std::string,unsigned int);
void print();
~employee();
};
employee::employee() : salary(1000)
{
name = "";
}
employee::employee(std::string ename) : salary(1000)
{
name = ename;
}
employee::employee(std::string ename,unsigned int salary)
{
name = ename;
this->salary=salary;
}
void employee::print()
{
cout<<"name: "<<name;
cout<<"\n"<<"salary: "<<salary<<endl;
}
employee::~employee()
{
}
int main()
{
employee emp1 ("Bill Jones",5000),emp5("Michael Adams");
employee emp2;
emp2=emp1;
employee emp3;
emp3=emp2;
employee * workers= new employee [3];
workers[0]=emp3;
workers[1]= employee("katy Ashton");
for (int i = 0; i < 2; i++)
{
workers[i].print();
}
delete [] workers;
}
I think you are missing name = new char[20]; in the employee constructor that takes just the name parameter
I don't know what the error message is, but I guess the reason is:
employee::employee(const char* ename) : salary(1000)
{
strcpy_s(name,20,ename);
}
you don't allocate any space for name here and you use this constructor later: ,emp5("Michael Adams");
Therefore it crashes (I guess)
I believe that this part is wrong:
while (name[i]!='\0')
{
name[i]=emp.name[i];
i++;
}
the while-condition should be emp.name[i]!='\0'.
(consider using strcpy_s, which does the same thing.)
Another problem is in your employee::employee(const char* ename) constructor, where you copy into array, which is not allocated. You need to allocate it first:
employee::employee(const char* ename) : salary(1000)
{
name = new char[20]; // typo! it was 10... better use defines in this situation!
strcpy_s(name,20,ename);
}
Of course, you should describe your problem more precisely.