I am new to C++. I have an exercise about constructor with const char* parameter.
class Book
{
private:
char* title;
}
public:
Book (const char* title)
{
this->title = title;
}
When I code the constructor like that, I receive error cannot convert const char to char*.
I tried using
strcpy(this->title, title);
then, it run, but I don't get the expected result.
Can anyone help me.
Thank you very much.
You are doing an exercise, did the course you are following not explain what you are supposed to do?
I would guess that this is an exercise in dynamic memory allocation and what you are expected to do is use strcpy after you have allocated some memory so that you have somewhere to copy the string to. Like this
this->title = new char[strlen(title) + 1];
strcpy(this->title, title);
You need to allocate one extra char because C style strings are terminated with an additional nul byte.
But any C++ programmer who was doing this for real (instead of it being a learning exercise) would use a std::string as paxdiablo says.
C++ doesn't let you easily change a const char * into a char * since the latter has no restrictions on how you can change the data behind that pointer.
If you're doing C++, you should be avoiding char * (legacy C) strings as much as possible. By all means take them as parameters if you must, but you should be turning them into C++ strings at the earliest opportunity:
class Book {
private:
std::string m_title;
public:
Book (const char *title) {
m_title = title;
}
};
The one thing you don't want to become is a C+ developer, that strange breed that never quite made the leap from C across to the C++ way of thinking :-)
And, actually, if a given book is never expected to change its title, you're better off making it constant and initialising it, rather than assigning to it, something like:
#include <iostream>
#include <string>
class Book {
public:
Book (const char* title): m_title(title) {};
void Dump() { std::cout << m_title << "\n"; }
private:
const std::string m_title;
};
int main() {
Book xyzzy("plugh");
xyzzy.Dump();
}
Related
I am trying to make a get method in a class medicine to get the description.
As I know of that in C++, there is no data type "String" like in Java, therefore I need to make an array of char to save the description. I couldn't find a way to make a method with return type "array of chars", I use a pointer like the following.
class Medicine {
public:
char description[100] = "testing";
char *getDescription() {
char *p_description;
char *p_subDescription = (char*)malloc(100 * sizeof(char));
strcpy(p_subDescription, description);
p_description = p_subDescription;
free(p_subDescription);
return p_description;
}
};
I have a question: is there any other way I can do to make the code shorter? I feel like this is too much work just for a method to get a string.
Thank,
If you want this to be static (class-specific), the easiest way I can think of is a static, public property:
class Medicine {
public:
static const std::string description;
};
const std::string Medicine::description = "testing";
You have to decided on your flavour of C++. If you want "C with classes", C++ very close to C, then you should be passing strings about as char *s to memory allocated with malloc. Your code is nearly correct (however you free memory then return it), but most people write a little function called strdup (in fact it's often provided, which means ironically it's best to call it mystrdup() to avoid collisions)
char *mystrdup(char *str)
{
char *answer = malloc(strlen(st) +1);
if(answer)
strcpy(answer, str);
return answer;
}
If you are writing a more modern version of C++, use the std::string class. It isn't especially efficient and it's widely criticised for being over-desinged, but it's standard. It does memory management for you, and it's easy to create one.
You can use std::string like this
class Medicine {
public:
char description[100] = "testing";
std::string getDescription() {
return description;
}
};
I am having trouble with a programming assignment for my c++ class and I am not sure how I should be doing this to not get an error. I am pretty new to programming, so this will probably be really easy.
In my instructions, we have to create a class to work with other code that is given to us with some guidelines. I have three files: program.h, program.cpp, and main.cpp.
program.h
//program.h
#include <iostream>
#include <stdint.h>\\This program uses type uint32_t so had to include this
#include <cstdlib>
class Program
{
public:
Program(); //was told to create a default constructor to initiate values if none are given
Program(char *, uint32_t, float); //was told to create an overloaded default constructor to change variables in program
void SetName ( const char* ); //given by the professor
//other function prototypes are here but they are working fine.
private:
char * name_; //given by professor
uint32_t code_;//given by professor
float cost_;//given by professor
};
program.cpp
//program.cpp
//other functions from class are in this file, just not giving any issues
Program::Program(char * name,uint32_t code, float cost) : name_(name), code_(code), cost_(cost)
{
}
Program::Program() : name_(NULL), code_(0x00000000), cost_(0.0)
{
}
void Program::SetName(const char* name)
{
name_= name; //where the issue appears to occur since name is a const char *
}
currently trying to compile program.o using makefile and program.h program.cpp so the main.cpp does not matter. When i try to compile, i receive the following error:
clang++ -oprogram.h program.cpp
program.cpp:17:9: error: assigning to 'char *' from incompatible type 'const char *'
name_ = name;
Since the function was void SetName (const char*); was given by the professor and has to be used. I am not sure how to fix this error since the variable char * name_; was also given to us by the professor. Pointers still confuse me some, but any help would be greatly appreciated. I always thought that constant data can be passed to nonconstant data but not vise versa.
Important point just to get this out of the way:
char * name_;
Defines a pointer to a character. This just makes a pointer. It does not make a character. You will need to provide the character that is pointed at later. This pointer can be used to change the memory at which it points.
const char* name
Defines a pointer to a character that cannot be changed.
A value that cannot be changed is fundamentally different from a value that can be changed. You can copy the unchangeable value into the changable, but you cannot do the reverse because that would require changing the unchangeable value.
A pointer that can be used to change a value cannot be pointed at an unchangeable value to prevent the obvious problem of using the pointer to attempt to change the value.
What you need to do is copy.
But first, you need to allocate storage to hold the copy. This should be covered by your text, leaving one problem: How much storage is needed?
First, you have to know what a string is and how they are represented in C. Not C++, but C. C++ does it a little bit differently and your professor will get to that eventually. I hope. God, I really hope. In the meantime, the professor has you working with C-style strings.
strlen solves the how much storage problem, mostly. strlen will tell you the length of a properly formatted string of characters. What it doesn't tell you is implied by the definition of a character string. Hope you read the link.
Now that you know how much storage you need, you allocate the storage with new.
Now that you have a name_ pointing to enough storage, you can copy from the constant memory at name into it. strcpy should be helpful here.
This is wonderful, but leave you with a small problem: what if there already was storage at _name? Shucks. We just overwrote the pointer to it. This is called a memory leak and is no small part of why C++ does strings differently.
OK, so before allocating storage for name_and copying the storage at name into it, first you need to test to make sure name_ is empty. Couple of ways to do this:
Set a canary value. A canary is an impossible value; something that you will never see. Typically for pointers we use NULL, a glorified 0. There is nothing at address zero by convention, so if you see a pointer pointing to zero something is up. If in the constructor you make sure that name_ is NULL, you will have an easy way to know if name_ isn't pointing at data yet.
Keep a length value and set it to zero in the constructor. If the length is zero, there's nothing there. As an added bonus since this allow you to know the length of your storage, you can compare it to the amount of storage needed by the new string. If the new string is the same size or smaller, you can write over the old string.
If you need to replace name_'s storage, delete[] the old storage before allocating new storage.
Putting it all together, and using option 2 because it's better, you get:
int len = strlen(name)
if len > length_
delete name_
name_ = new storage
strcpy(name_, name)
Note there are a few pieces missing you'll have to fill out.
And just to be an ass, this is what all that would look like with C++ strings:
name_ = name;
Look familiar? Aren't you glad your professor decided to teach you to program in C++ the worst, hardest way first?
There may be some typos. You have space in
#include < iostream >
Remove the space
#include <iostream>
Change char to
const char * name_;
Add semicolon after the last } in the Program class definition.
Example on the code:
main.cpp
#include <iostream>
#include "program.h"
using namespace std;
int main(int argc, char const *argv[]) {
cout << "Hello, World!" << endl;
char const * name = "Claus";
uint32_t code = 1967;
float cost (3.14f);
Program p (name, code, cost);
cout << "getName(): " << p.getName() << endl;
return 0;
}
program.cpp
#include "program.h"
Program::Program() {};
Program::~Program() {};
Program::Program(char const * name,uint32_t code, float cost) : name_(name), code_(code), cost_(cost) {}
void Program::SetName(const char* name) {
name_= name; //where the issue appears to occur since name is a const char *
}
char const* Program::getName() {
return name_;
}
program.h
#ifndef PROGRAM_H
#define PROGRAM_H
#include <stdint.h>
class Program {
public:
Program(); //was told to create a default constructor to initiate values if none are given
~Program();
Program(const char * , uint32_t, float); //was told to create an overloaded default constructor to change variables in program
void SetName (const char* );
const char* getName();
private:
const char * name_;
unsigned int code_;
float cost_;
};
#endif // PROGRAM_H
On my mac I compile it with
clang++ -std=c++11 -Wall -o main main.cpp program.cpp
I get warning about unused variables but that's OK.
I was inspired by user4581301's response to learn a bit C. C++ does alleviate it alot.
In program.cpp
Program::Program(char * name, uint32_t code, float cost) {
unsigned int len = strlen(name);
name_ = new char[len];
strcpy(name_, name);
code_ = code;
cost_ = cost;
}
void Program::SetName(const char* name) {
unsigned int len = strlen(name);
delete name_;
name_ = new char[len];
strcpy(name_, name);
}
This link helped me as well: how to initialize a char pointer in a class?
regards
Claus
I am new to C++ and I am getting an error.
Basically I have a variable char myName[150] and have a method called
void setName(char myNames) {
this->myName = myNames;
}
My error is myName[150] is not equal to myNames. I think the compiler is trying to say incompatible types however I don't know how to fix my code.
Also, I'm interested in storing two sets of values, multiple times. For example, {[0,10], [5,15], [6,69]...} - would I be right in having something like this
int **d[]; /dynamic array - grows in size and not fixed
void setValues(int a, int b){
//NEED HELP WITH IMPLEMENTATION HERE
}
I would greatly appreciate it if someone could help me out with my errors and questions. I am very keen on learning this C++ language - I really like C++ and C, and wish I learnt them as my first ever programming language
The compiler is telling you that the types are different: myName is a char[150], but myNames is a char. That assignment doesn't work. Maybe you meant:
void setName(const char* name) {
strncpy(myName, name, sizeof(myName));
}
or
std::string myName;
void setName(const std::string& name) {
myName = name;
}
or some equivalent.
For the second question, just use std::vector<std::pair<int,int> >.
How was the "string" type created in C++? In C, strings are character arrays, but how did C++ turn the character arrays into the "strings" we know of in C++?
The character array is still in there, it just has a class wrapped around it. Imagine something like this:
class String
{
private:
char* stringData;
public:
String(const char* str)
{
stringData = new char[strlen(str)+1];
strcpy(stringData, str);
}
~String() { delete[] stringData; }
String& operator += (const String& rhs)
{
char* newStringData = new char[strlen(rhs) + strlen(stringData) + 1];
strcpy(newStringData, stringData);
strcpy(newStringData + strlen(stringData), rhs);
delete[] stringData;
stringData = newStringData;
return *this;
}
};
That's obviously a very incomplete example, but you get the idea, right?
The actual implementation of std::string is pretty comprehensive, but it's nothing you couldn't do yourself. Here's some differences in the official std::string class from what I posted:
The length of the string is usually included as a member variable, so you don't have to keep calling strlen to find the length.
The std::string class uses templates, so you're not limited to the char type. If you're using Unicode, you can use std::wstring, which uses 16- or 32- bit strings by replacing the char type with the wchar_t type.
Usually there's lots of optimizations to choose from. Lately the most popular has been the "short string" optimization.
Once you've relatively comfortable with C++, you should try writing your own string class. It's not something you would use in practice, but it's a really good exercise for library writing.
By writing a class that encapsulated a lot of string functions, and by overloading a bunch of operators.
string really is just a class like any other:
string s = "hello"
is an overload of the equals operator defined:
string& operator= ( const char* s );
for example.
It's just a class named 'string', something like this:
class string
{
private:
//members
char* c;
public:
//methods
bool operator==(const string& other) const;
};
I have a very simple class named person which is given below , I have a problem with only two functions , i.e setstring () function and setname() function , I am calling setstring() function from the setname function.
The only problem is when in the main function I write
Object.setname(“Zia”);
The result is ok as shown in the output screen,
Now when I write
Object.setname(“Zia ur Rahman”);
Nothing is displayed as you can see the output screen.
I know the problem is when I pass the name pointer to setstring () function but I am confused about it please explain it in detail that what is happening here.
#include<iostream.h>
class person
{
char* name;
public:
person();
void setname(const char*);
void setstring(const char*, char*);
void print()const;
};
person::person()
{
name=new char[3];
strcpy(name,"NILL");
name[3]='\0';
}
void person::setstring(const char* s, char*p)
{
if(s!=NULL)
{
delete[] p;
p=new char[strlen(s)];
strcpy(p,s);
p[strlen(s)]='\0';
}
}
void person::setname(const char* n)
{
setstring(n, name);//passing data member name
}
void person::print()const
{
cout<<"Name: "<<name<<endl;
}
main()
{
person object;
object.setname("Zia ur Rahman");
object.print();
system("pause");
}
alt text http://img264.imageshack.us/img264/8867/inheritanceimage004.jpg
alt text http://img263.imageshack.us/img263/3770/inheritanceimage003.jpg
The specific reason that nothing is being printed is that in setstring, p is copy of the name pointer, not a reference to it. Try changing the signature of setstring to:
void setstring(const char* s, char*& p);
(note the &).
See the other answers for other significant errors in the code - unless these problems are fixed, you are likely to get crashes or strange behaviour.
And unless the purpose of the code is just to learn dynamic arrays, use std::string instead :-).
If you want to do correct OO-oriented programming in C++ you should maybe stay away from direct pointer management but use the STL string class and use references instead of pointers. Then you should have an easier time and your source should produce the correct output.
Otherwise check your constructor of the person class, the name-array has just 3 elements but you're referencing the 4th one there (indices 0-2!). Also in the setstring() method you're not allocating enough space for the trailing '\0' in the array!
For starters:
name=new char[3];
strcpy(name,"NILL");
name[3]='\0';
name has three elements - you are treating it as if it had five. In a similar vein:
p=new char[strlen(s)];
should be:
p=new char[strlen(s) + 1];
In fact, that function is completely wrong - you are supposed to be copying the string into 'name', not the mysterious 'p' parameter. If you really want that function, then 'p' must be a pointer to a pointer or a reference to a pointer.
Have you thought about using std::string from STL?
Though first problem I see is this.
person::person()
{
name=new char[3];
strcpy(name,"NILL");
name[3]='\0';
}
Your allocating an array of char's, the size of the array is 3 characters, then your copying "NILL" into it with strcpy so your filling in the array with all the characters but without the null terminator \0. "NILL" is a const string and such has a null terminator that is implicit but not shown for example "NILL\0". The \0 is a control character that is used to indicate the end of the string. Then you have an index out of bounds when you access the 3rd element of name array,when your size of your array is 3.
To help you find out the other parts that could be going wrong, here are some of the links to the function you use.
strcpy
strlen
strcpy will copy the whole string from one buffer to the next including the null terminator control character.
Strlen will return amount of characters between the beginning of the string and the terminating null character. Though it will not count the null character as a character. Thats why you will see suggestions with strlen(string)+1 to include the null terminator.
Though your doing well keep up the work, you will understand these little gotcha when using the standard library functions.
Suppose s have 5 chars. Then new char[strlen(s)]; allocates the memory of 5 chars. Then p[strlen(s)]='\0' is equivalent to p[5]=0. It's very very bad. p[5] does not exsist.
void person::setstring(const char* s, char*p)
{
if(s!=NULL)
{
delete[] p;
p=new char[strlen(s)];
strcpy(p,s);
p[strlen(s)]='\0'; //<<<< LOOK! Out of range
}
}
It's rather C, than C++ code.
There is C++ equivalent:
#include <string>
#include <iostream>
class person
{
std::string name_;
public:
person();
//preferable design is to set object invariant in appropriate constructor
explicit person(const std::string &name);
std::string get_name() const;
void set_name(const std::string &name);
void print()const;
};
person::person()
: name_("NILL")
{}
person::person(const std::string &name)
: name_(name)
{}
std::string person::get_name() const
{
return name_;
}
void person::set_name(const std::string &name)
{
name_ = name;
}
void person::print()const
{
std::cout<<"Name: "<<name_<<std::endl;
}
int main()
{
person person1;
person1.set_name("Zia ur Rahman");
person1.print();
//this is better design decision
//because after constructor we have valid object
person person2("Zia ur Rahman");
person2.print();
std::cin.get();
return 0;
}