Error with set Method C++ - c++

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> >.

Related

C++ invalid conversion from 'const char*' to char*

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();
}

c++ error: assigning to 'char *' from incompatible type 'const char *'

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

Is there empty std::string defined somewhere?

Is there empty std::string defined somewhere?
What I mean is following:
I can do:
// code #1
int process(const char *s = nullptr);
// later I can use:
process();
However, if I do:
// code #2
int process(const std::string &s = "");
// later I can use:
process(); // wait, an object is created...
It compiles and works, when I use the function, there is unneeded object creation.
Is there standard way to do following:
// code #3
const std::string EMPTY_STR;
int process(const std::string &s = EMPTY_STR);
// later I can use:
process(); // fine, no object is created...
This is not bottleneck, nor it is a premature optimization.
I believe C++ is not Java, so right way is not to create objects that you do not need.
Also I believe code 3 looks much better than code 2 and also it show the intention that string is empty (and probably will not be used), than code 2, where is not very clear why the string is "".
There's no (safe) way of making a reference refer to nothing. If you don't want an object to be created at all, you have to use a pointer;
int process(const std::string *s = nullptr);
If you want to use references, there must be an object somewhere. For that purpose, you could use a default-constructed (empty) string as default argument;
int process(const std::string& s = std::string());
First of all, I am slightly surprised you need an OBJECT. It is going to be a const object anyway, so what does it give you which simple const char* does not?
Second, there is a solution to your problem in a generic way. There is a genuine problem with following omnipresent code:
void foo(const std::string& data);
It allows using foo with both std::strings and const char*, and suits almost everybody. It does not matter for majority of users of foo(), but for someone really fixed on performance (as in nanoseconds) creation of temporary std::string from their const char* is a sore point. To solve this problem, StringRef was invented. It is not available in std, but it exits in many libraries including boost, and is simple to implement. The idea is following:
class StringRef {
...
StringRef(const std::string& str) : b(str.begin()), end(str.end()) {}
StringRef(const char* str) : b(str), end(str + strlen(str)) {}
...
private:
const char* const b;
const char* const e;
};
void foo(const StringRef str);

Passing user input to function with char* parameters

I'm new to this so I know this is probably something simple.
I have a function like this
void GroceryList::addRecord(char* itemName, char* itemType, char rating){
//do some code;
}
My problem is I am having trouble creating proper arguments to pass to the function.
I've tried something like
void main() {
string itemName;
cin >> itemName;
string itemType;
cin >> itemType;
string rating;
cin >> rating;
gradeBook.addRecord(itemName, itemType, rating);
}
I didn't expect it to work as the function is expecting char* but I can't for the life of me figure out how to get the user input into a variable that I can pass to the function. I've been search for literally 13 hours trying what I can find but no luck so far.
Well, don't use char*.
void GroceryList::addRecord(const std::string& itemName, const std::string& itemType, const std::string& rating) { /* ... */ }
You can get const char* (not char*) from string with c_str() member function, e.g. itemName.c_str(), but unless you're doing interop with C libraries, you don't need that.
Change the function prototype to
void GroceryList::addRecord(string itemName, string itemType, string rating){
//do some code;
}
I also recommend const correctness in your code, if you are not going to change the arguments, pass them by ref with const (for performance)
void GroceryList::addRecord(const string& itemName, const string& itemType, const string& rating){
//do some code;
}
All depends on the actual method body which you didn't describe.
Use std::string::c_str(); that's what it's for:
gradeBook.addRecord(itemName.c_str(), itemType.c_str(), rating.c_str());
This function returns a const char *. However, the addRecord function doesn't seem to be const-correct, so you need to fix that.
You can use string and then when passing just call c_str() on the string. For the rating you can just use a char.
Then calling the function looks like:
gl.addRecord(itemName.c_str(), itemType.c_str(), rating);
For this to work you'll need to change the function signature to const char* instead of char*.
The simple answer is that you can't. If you can modify
GroceryList::addRecord, change it to use std::string const&. If you
can't modify it, then you have to ask the question: why does it use
char*? There are two possible answers: the author didn't understand
const, or was too lazy to use it, and in fact doesn't modify the
pointed to strings. In this case, something like
const_cast<char*>( itemName.c_str() ) can be used; it's wordy, but
that's the price you pay when the code's author doesn't do his job
correctly. The other possible answer is that the code does modify
something through the pointer. In this case, the only solution involves
making a copy of the string into a char[], and passing it.

C++ classes , Object oriented programming

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;
}