I've got a string pointer string* ifxPtr;, what I'm trying to do is to set this pointer to point to the user input and then loop through each character of it.
string* ifxPtr;
void Expression::GetInfix(string data) // This method runs first and it's setting the pointer to point to previously passed user input
{
ifxPtr = &data;
ConvertToPostfix();
}
void Expression::ConvertToPostfix()
{
for (int i = 0; i < *ifxPtr->length; i++) // Here's the struggle, compiler is complaining about *ifxPtr with message Cannot apply binary '<' to 'int' and 'unassigned() const'
{
//Do something here
}
}
length is a function and it should be length()
You
don't need to deference the pointer if you use ->
The result
returned from length() is size_t
Here is what I would use:
int length = static_cast<int>((*ifxPtr).length());
foo-> is shorthand for (*foo).. Don't double up operators, also it should be length():
for (int i = 0; i < ifxPtr->length(); i++)
Also, be careful with that design, possibility of running into Undefined Behaviour with a simple mistake is big.
if you use and *before it means using the value which is pointed by the pointer.
string s,*p;
p=&s;
here *p.lenght() is same as s.length if you want to access through pointer you have to use it like this p->length().
Related
I'm trying to create a function called void find(int id, Student** s) that searches the array for the student with the id specified in parameter id, and returns that student pointer using parameter s. The task says I must use the parameter to return this data and to not use the return value.
I'm a little confused by what the last line means. I have this so far but the s == students[i] line causes the error: comparison between distinct pointer types ‘Student**’ and ‘Student*’ lacks a cast [
void StudentsArray::find(int id, Student** s){
for(int i = 0; i < studentsCount; ++i){
if(students[i]->getId() == id){
s=students[i];
}
}
}
I'm just a little confused on what I'm supposed to return and how I would go about doing so and would appreciate any help!
The second argument in the function says "A pointer to a pointer to Student"
To return it, you'll need to set it to a pointer of Student.
Taking a pointer of one of the student array is done like this: &student[i].
Once you have the pointer, you need to store somewhere, and you'll store it inside the given pointer-to-pointer by dereferencing it like this: *s
Put together, you'll need to *s = &student[i] to perform: "store in the memory area pointed by s the address of the student's item"
void StudentsArray::find(int id, Student** s){
*s = nullptr;
for(int i = 0; i < studentsCount; ++i){
if(students[i]->getId() == id){
*s = &students[i];
}
}
}
If this is disturbing at first, just remove a layer of indirection by writing:
void StudentsArray::find(int id, Student* & s) {
...
s = &student[i];
...
}
In that case, you are taking a reference (so if you modify it inside the function you're modifying it from the caller's site) to a pointer to student. When you assign it, it's like it's returned to the caller.
Why it's important
Sometimes, you need to be able to return more than one thing from a function. Either you build a structure holding the things and you return that but it's very painful to do and usually not very efficient, either you simply accept a pointer (or a reference) to these things and expect the function to fill them for you. From my own experience, this is what is done most of the time.
EDIT: Following remark from Tanveer Badar, it's good practice to expect the function to set the returned value to 0 (or better nullptr) if not found so you don't have to do it on the caller's site.
You could instead return the index where the match happened or -1 if none matched.
int StudentsArray::find(int id){
for(int i = 0; i < studentsCount; ++i){
if(students[i]->getId() == id){
return i;
}
}
return -1;
}
When I do this pointer arithmetic , it always give me an error
int main()
{
const int rowSize=40;
int* unique=nullptr;
int arr[rowSize]={1,1,11,31,21,22,2,2,3,32,31,3,4,34,45,5,55,5,55,5,6,46,64,6,7,27,74,7,7,7,7,11,11,11,11,11,1,2,13,4};
int amount=0;
for (int count=0; count<rowSize; count++)
{
if (arr[count]!=arr[count+1])
{
amount++;
}
}
unique= new int[amount];
for (int count=0; count<rowSize-1; count++)
{
if (arr[count]!=arr[count+1])
{
*unique=arr[count];
unique++;
}
}
for (int count=0; count<20; count++)
{
cout<<unique[count]<<" ";
}
cout<<endl;
delete [] unique;
unique=nullptr;
return 0;
}
Everytime I do this pointer arithmetic, *unique=arr[count] and unique++, it always give me a funky output at the end.
Changing the value of a pointer returned by the new[] operator is extremely dangerous, and never really the right way to go about coding. This is because, at some point, you will need to release that memory with a delete[] 'call' to the address that new[] gave you.
In your case, the module that calls your uniqueArr function gets a returned value that will no longer (in most cases) be the correct address for the delete[] call, and that will fail.
You would be far better off using the [] operator on your pointer, using an index value that you increment when appropriate (where you currently increment the pointer). Something like this:
//...
int* unique = new int[amount];
size_t uIndex = 0;
for (int count=0; count<rowSize-1; count++)
{
if (arr[count]!=arr[count+1])
{
unique[uIndex] = arr[count]; // The [] works fine with a 'new[]' pointer!
uIndex++; // You could even include this POST-increment inside the [], above!
}
}
//... You can now 're-use' "unique" as it will still be the original address.
//...
In this way, the value returned by the function will be unchanged from that returned by the new[] operator, and will be valid for any subsequent delete[] operation.
Feel free to ask for further clarification an/or explanation.
EDIT: An alternative (though, IMHO not good) approach would be to have a second int* pointer in which you save the value of unique, then restore unique to that value before 're-using' it (in a second loop, or before calling delete[]).
I am a bit confused when you pass NULL as a parameter
for example
int* array_create( int* array,size)
{
array = new int[size];
return array;
}
int main()
{
int* array = array_create(NULL,10);//can we pass NULL in this case?
delete[] array;
return 0;
}
I know the example is kinda stupid, but I am wondering if we can pass NULL as the parameter when the function assigns some heap memory to a pointer and returns it?
When you call your function like this...
int* array = array_create(NULL,10);//can we pass NULL in this case?
...you are getting behaviour like:
int* array_create(...)
{
int* array = NULL;
size_t size = 10; // using size_t as you'd missed any type
array = new int[size];
return array;
}
Ultimately, array is initialised to NULL then shortly afterwards overwritten with the value returned by new, so the initialisation serves no purpose.
For this code, there was simply no point passing an array argument... you could have created a local variable directly:
int* array_create(size_t n)
{
int* array = new int[size];
return array;
}
...or even...
int* array_create(size_t n)
{
return new int[size];
}
I am wondering if we can pass NULL as the parameter when the function assigns some heap memory to a pointer and returns it?
This requirement doesn't make much sense, as the two things are unrelated. You can pass whatever you like, and return whatever you like.
More commonly, a function might do something like:
void dump_bytes(std::ostream& os, unsigned char* p, size_t n)
{
if (p)
for (size_t i = 0; i < n; ++i)
os << static_cast<int>(p[i]) << ' ';
}
In dump_bytes, specifying a p value of NULL would fail the if (p) condition, ensuring the function didn't invoke undefined behaviour by dereferencing via a NULL pointer, even if n was not 0.
Just summarizing from the comments:
Yes, it is completely valid, but in Your example it is completely useless (you know that)
Some examples of this in real code:
In OpenGL you can tell the API if the data you want is coming from is from a buffer:
glBufferData(..., nullptr);
But wait! That's not null, that's nullptr?
Well in a c++11 compiler nullptr is a better option. Because NULL often usually resolves to 0, a version of the method that takes an int instead of a pointer the compiler will choose the int.
Here's some more data on that:
http://en.cppreference.com/w/cpp/language/nullptr
Also, if you want to edit an array, you should pass a pointer to a pointer.
I have a working code for a function which takes a character and a number and forms a string by duplicating that character that number of times. Here is a piece that works perfectly fine.
char * buildstr(char c, int n)
{
char * pc = new char[n+1];
for (int i = 0; i < n; ++i)
{
*(pc+i) = c;
}
*(pc+n) = '\0';
return pc;
}
But if I use another logic where I directly increment the pointer itself directly then I get an error when I free up the memory in the main function using delete [].
What could be my problem ?
Thanks,
char * buildstr(char c, int n)
{
char * pc = new char[n+1];
for (int i = 0; i < n; ++i)
{
*pc = c;
pc++;
}
*(pc) = '\0';
return pc;
}
The problem is that you're returning the incremented pointer. delete[] has to be invoked with a pointer value that was returned by a call to new[], otherwise you get undefined behaviour. The same applies to calls to free and pointers returned by malloc, calloc etc.
In the second example, you are incrementing the value of the pointer. When you try to delete it, it is pointing to the last position of the array.
This way, when you call delete[] on it, it crashes as it expects pc to point to the address that was originally allocated using new[].
I encourage you to use the first approach as you will be able to keep track of the base address through the lifetime of pc. Moreover, I think it would be easier for you to do this using array notation.
Consider using:
pc[i] = c;
instead of
*(pc+i) = c;
As it is more idiomatic and easy to read. If you are simply exercising your pointer arithmetic, stick to the first approach that you described.
In the first function let's say that your pointer start at 0x00100.
when you do the loop you get to the next adress so for exemple let's say 4 loop:
0x00100
0x00101
0x00102
0x00103
but at the end you return the pointer on the 0x00100 beceause you used index *(pc+i) where i is the index, so it is good.
Now on the second function you are doing the same exept that your are moving your pointer itself without index so you return your pointer at the last adress
0x00103
That is wy your second function doesn't work
I am pretty weak in understanding and working with pointers. So, Please help me here.
My objective is to pass an array pointer's address to a function ,(i.e.) the address the pointer is pointing to, and update the values directly in the address using the '*' operator, in the function, to avoid any return values. Moreover, the length of this array has to be changed dynamically in the function to which it is passed. This is my attempt. If there's a better method to update the value of an variable, without having it returned from a function, please do mention that to help me.
But am getting errors, as I know I am doing it wrong, but still wanted to try with what I know, since I thought the best way to learn is to do and make as many mistakes as possible. Please help me here
This is the main function
int main()
{
double *trans;
int *rots;
readctrls(rots,trans);
for(int i=0;i<trans.size();i++)
{
cout<<trans[i]<<endl<<rots[i];
}
}
Here, am trying to pass the address of the pointer arrays to the function readctrls. then later, print its values. I haven't mentioned a size, cuz it will be determined later in the function.
The function is just to read numbers from a text file, line by line and store these numbers in these 2 arrays. The readctrls function is as follows.
void readctrls(int*& rots,double*& trans)
{
fstream inputs;
inputs.open("input_coods.txt");
int nol = 0,i = 0;
string line,temp,subtemptrans,subtemprots;
while(getline(inputs,line))
{
++nol;
}
cout<<nol<<endl;
inputs.close();
inputs.open("input_coods.txt");
string *lines = new (nothrow) string[nol];
trans = new double[nol];
rots = new int[nol];
for(int i = 0; i<nol ; i++)
{
getline(inputs,lines[i]);
temp = lines[i];
for(int j = 0; j<temp.length() ; j++)
{
if(temp.at(j) == ' ')
{
subtemptrans = temp.substr(0,j);
subtemprots = temp.substr(j+1,temp.length()-j);
trans[j] = ::atof(subtemptrans.c_str());
rots[j] = atoi(subtemprots.c_str());
}
}
}
inputs.close();
}
Thanks a lot for your help guys. I was able to understand a bit and changed the code and was able to compile now without errors. however, the value I read from file and load into the array, doesn't seem to get reflected back in the main. Am getting the correct values from the file when I print the array in the function, but am getting zeros, when I print in the main(). Please help me here.
These are the contents of the file
0.2 0
0.2 0
0.2 0
0.2 0
0.2 0
while print 'trans', which takes the first number every line, in the function, am getting the correct values. But while printing in the main function
0
0
0
0.2.
I changed the pointer to pointer reference while passing to function. Please check edit in the function code. Thanks in advance.
The declaration
void readctrls(int &rots,double &trans)
tells the compiler that rots and trans are references to a single value each. They are not pointers.
To make matters worse, you are actually trying to pass a pointer-to-pointer as arguments when calling this function.
You should change the declaration to actually take pointers:
void readctrls(int* rots, double* trans)
then change your call to not use the address-of operator (as those are already pointers):
readctrls(rots, trans);
Your code has several errors. Here are some of them:
double *trans = new double[];
int *rots = new int[]; //^^You need to give the size
for(int i=0;i<trans.size();i++)
{
cout<<*trans[i]<<endl<<*rots[i];
}
trans and rots are simply array of double and integers, you simply use trans[i] to print the i-th element. Dynamic arrays should be used similarly to static arrays. Take a look at this pointer and arrays for some basic understanding. Meanwhile, look at dynamic memory in C++ for some understanding on this point.
void readctrls(int &rots,double &trans);
//^^expects reference to int and double while you are not passing int and double from main
An array and a pointer can be thought about similarly as a way of referring to a range in memory. If you want to refer to a range of memory via pointers, then just pass the pointer to the function, ie
double pd* = new double[10];
fun(pd);
...
void fun(double* pd, int numDoubles)
{
do {
double d = magicDoubleGenerator();
*pd = d; // read as "the value that pd points to" or "contents of pd"
} while (++pd < pd + numDoubles);
}
Pointers are hard until one day you realize "Ahh! they just point at things!"
There are many errors ...
inputs.open("input_coods.txt"); // second argument is missing
check this fstream open
void readctrls(int &rots,double &trans)
change to
void readctrls(int* rots, double* trans) // this creates pointer rots trans
*trans = new double[nol]; // remove *
*rots = new int[nol]; // remove *
double *trans = new double[]; // not specified the size
int *rots = new int[]; // not specified the size
readctrls(&rots,&trans); // this means you passing address of pointer
trans.size() ; // this is c++ double is not a class
I am recommending you to study c++ from this site C++ Tutorial