referenced memory conditionally modified in recursive loop - c++

I have two structs and a function
struct nodeT {
bool last;
string attribute1;
string attribute2;
string attribute3;
vector<charT> leafs;
};
struct charT {
char character;
nodeT *next;
};
void addNode(nodeT *n, string stringy, string &attribute1, string &attribute2, string &attribute3)
{
if (stringy=="") {
w->last=true;
return;
} else {
if (n->last==true) {
attribute1=n->attribute1; //these attribute fields were given values earlier
attribute2=n->attribute2;
attribute3=n->attribute3;
}
addNode(n, stringy.substr(1), attribute);
}
}
And addNode is called with
string test="";
addNode(root, "wordy", test, test, test);
The problem is the attribute reference string &attribute is not changed to 5, it continues the next call with the "" value.
I tried making it a pointer reference *attribute->n->attribute
And tied a reference &attribute = n->attribute
These were shots in the dark and did not work.
EDIT: addNode should have been called with individual memory references.
string test1="";
string test2="";
string test3="";
addNode(root, "wordy", test1, test2, test3);

Have you tried initializing attribute in a constructor?
struct nodeT {
bool last;
string attribute;
vector<charT> leafs;
nodeT() : attribute("5") {}
};
Your code looks somewhat, but not entirely, unlike Java... :-)

No of args for function declaration and function call don't match and function dosnt have variable arg. It should not clear compilation hurdels also.

The answers made by the contributors helped lead me to the answer but they have been hitting answers slightly off from the issue.
For setup, function uses structs nodeT and charT
and is was called with the equivalent of
root is defined globally in the class
string wordy = "hello";
string test="";
addNode(root, "wordy", test, test, test);
addNode should have been called with individual memory references.
string test1="";
string test2="";
string test3="";
addNode(root, "wordy", test1, test2, test3);
So when later when attributes 1, 2 and 3 are changed with unique values, there is a corresponding unique memory for each.

Related

Can I call the function like that?

If I have a struct.
struct studentRec
{
string name;
int sid;
string major;
int cohort;
};
Then, I have a function.
int compare_MajorName(const studentRec& s1, const studentRec& s2)
Can I call the function like that?
String major = ECE;
list = new studentRec[n];
compare_MajorName(list[mid], major)
No you can't.
Your function parameters require studentRecs. A String cannot be converted to a studentRec automagically. It wouldn't make sense.
You have two possibilities:
make an overrided function which accepts a String as a second parameter
simply compare the name inside the struct with your String:
list[mid].name == major for exemple

Use a string as a char

I have been given this definitions, the function should return what is in info->phrase. However info->phrase can contain a string in which case I can only make it return the first char on info->phrase. Is there a way to make a string compatible with the char type? I am new to c++.
struct rep_info {
int num;
char *phrase;
};
I´ve tried few thing but get type errors, this was my latest attempt
char *phrase_info(rep_info info) {
char text[std::strlen(info->phrase) + 1];
text = info->phrase;
return text;
}
Since you said you have been given these definitions, let's fix the problem with the current setup first. Looking at your function, you are trying to copy into this local array (incorrectly I might add), and return this local variable. There are a number of things wrong with this, including the syntax and the fact that the local variable is destroyed when the function exits.
If you just need to get the value of the phrase member variable, the simplest solution would be to just access the member variable directly and return it:
char *phrase_info(rep_info info) {
return info.phrase; //since info is not a pointer, use the '.' accessor
}
If you mean to pass a pointer to the function, you would re-write it like this:
char *phrase_info(rep_info *info) {
return info->phrase;
}
But it seems like you feel the need to copy the contents of info->phrase into a new memory space? If so, then you would do something like this where you first allocate new memory and return this buffer:
char *phrase_info(rep_info *info) {
char *buf = new char[std::strlen(info->phrase) + 1];
std::strcpy(buf,info->phrase); //copies info->phrase into buf
return buf;
}
You would then need to use delete on the returned memory value to clean up the memory allocated by new, otherwise you will have a memory leak.
Overall, all the above solution would potentially solve the problem given some parameters you haven't made clear. To round this out, this should be written more like:
class rep_info {
private:
int num;
std::string phrase;
public:
rep_info(int n, std::string p) : num(n), phrase(p) {}
std::string get_phrase() { return phrase; }
// other functions
};
//later in the code
rep_info info(...);
info.get_phrase();
Ideally, you would wrap these member variables into their own object with corresponding member functions that can get and set these values. Moreover, for handling strings in C++, std::string is the preferred option for storing, copying, modifying, etc. strings over the older char * C-style string.

Pointer pointed to string passed by function in C++

I have a question on the pointer used by string in a function. my code is below.
void printName(int *max,int *min,string *maxFirst, string *maxLast)
{
ifstream infile;
infile.open("input.txt");
string firstName,lastName;
float age;
infile>>firstName>>lastName;
while(firstName!="Term") {
infile>>age;
if(age==*max)
{
maxFirst=&firstName;
maxLast=&lastName;
cout<<*maxFirst<<' '<<*maxLast<<endl;
}
}
To use this function, in main(), I define it like
int main()
{
void printName(int *,int *,string *,string *);
int *pMaxAge, *pMinAge;
string *maxFirst,*maxLast;
pMaxAge=&maxAge;
pMinAge=&minAge;
printName(pMaxAge,pMinAge,maxFirst,maxLast);
cout<<"\nThe oldest employee is "<<*maxFirst<<' '<<
*maxLast<<endl;
}
I skip some part of my code. While the first cout works fine, the second one doesn't work. Is there any problem with my pointer passing please?
Thanks.
Your understanding of pointers is a complete mess. You should go and RTFM on pointers, from the ground up. Nothing you do here makes sense.
First you declare 4 pointers, not initialized to anything. Then you pass them to a function which takes pointer arguments by value, and expect changing the pointers' values to affect anything outside the function.
You should allocate these variables in your main function, and then pass them either by reference or by address, and assign to them properly when doing so.
For instance:
void printName(int *max,int *min,string *maxFirst, string *maxLast)
{
ifstream infile;
infile.open("input.txt");
string firstName,lastName;
float age;
infile>>firstName;
while(firstName!="Term") {
infile>>lastName>>age;
if(age==*max)
{
*max = (int)age;
*maxFirst=firstName;
*maxLast=lastName;
cout<<*maxFirst<<' '<<*maxLast<<endl;
}
infile>>firstName;
}
}
int main()
{
int MaxAge = 0, MinAge;
string maxFirst,maxLast;
printName(&MaxAge,&MinAge,&maxFirst,&maxLast);
cout<<"\nThe oldest employee is "<<maxFirst<<' '<<
maxLast<<endl;
}
In the printName function you need to assign to the content of the pointer:
*maxFirst = firstName;
*maxLast = lastName;
You also need to pass pointers to the existing variables as function arguments:
string maxFirst;
string maxLast;
printName(pMaxAge, pMinAge, &maxFirst, &maxLast);
The same probably applies to the integer arguments.

Calling functions and returning values

I am a beginner in C++.I have a function which returns some parameters that i need ,to use in the rest of my program.I am trying to access that function within another class.I am confused with the way i can do it...Can anyone please help me..?
Following is my code :
void SampleProgram :: myFunction()
{
string sInput;
GetInfo getInfo(sInput); //creating instance of the class containing the function
string sSw="";
string sName="ram";
string sList="list";
getInfo.getRequiredInfo(sSw,sName,sList); //calling the function
}
How can i access the output parameters of getRequiredInfo() ..?and save it if the ouput parameters are as following :string name,int status
Please help me...
You'd have to show us the declaration of getRequiredInfo(), but presumably it's something like
X result = getInfo.getRequiredInfo(sSw,sName,sList);
We don't know what X is without seeing that declaration.
In case getRequiredInfo get the address of the strings, try this:
getInfo.getRequiredInfo(&sSw, &sName, &sList);
Now the function can change the value of the arguments.
You can able to return single value in function.
so You can create struct containing string and int and return that as the result.
struct
{
string name;
int k;
}result;
result r = getInfo.getRequiredInfo(sSw,sName,sList); //calling the function
you can save the output parameters like these:
string _name;
int nk;
_name = r.name;
nk = r.k;
The simplest would be return a pair<string,int> from the function. So your function signarutre would be pair<string,int> getRequiredInfo(const string& s1, const string& s2, constr string& s3);. You can then access the string and int part usinf first and second members of the pair.
It sounds as though getRequiredInfo has the behaviour of both reading from and writing to some of the parameters you've passed in.
In C++, unlike in C#, there's no way to specify that a function should, or must, change the value of a given parameter. Indeed, if you have defined your function like this:
void GetInfo::getRequiredInfo(string a, string b, string c);
then all three parameters will be passed by value meaning any changes made to them inside the function will be changing copies of those objects, rather than the objects themselves.
As other contributors have suggested, if you really want to change the parameters you passed in, you could either do so by passing references:
void GetInfo::getRequiredInfo(string a, string& b, string& c);
or (more typically) by passing pointers:
void GetInfo::getRequiredInfo(string a, string* b, string* c);
However, if you want your function to simply read the parameters and return a value (which is the more accepted term for what you're calling 'output parameters') then you have to express your tuple of "name + status" as a single value.
You could use the built in pair template as someone else just suggested:
pair<string,int> getRequiredInfo(string a, string b, string c);
Or you could define your own struct to do it, like someone else suggested:
struct NameAndStatus
{
string name;
int status;
};
NameAndStatus getRequiredInfo(string a, string b, string c);

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