Char pointer assignment not working - c++

I have piece of code here.
void MyString::rm_left_space(char *s){
int size = getSize(s);
char s2[size];
char *s1=&s2[0];
int i=0;
while(*(s+i)==' '){
i++;
}
for (int k=i,l=0; k<size; k++) {//start from i, discarding spaces
*(s1+l) = *(s+k);
l++;
}
s=s1;
}
void MyString::rm_right_space(char *s){
int countSpacesfromLast=0;
int size = getSize(s);
int j=size-1;
while(*(s+j)==' '){
countSpacesfromLast++;
j--;
}
char *s2=new char[size-countSpacesfromLast];
for (int t=0; t<size-countSpacesfromLast; t++) {
*(s2+t)=*(s+t);
}
s=s2;
}
void MyString::rm_space(char *s){
rm_left_space(s);
rm_right_space(s);
}
Where there is s=s1 and s=s2 assignment does not happen. How come pointer assignment is not working.
In rm_space method s is unchanged after function calls. Why?

In rm_space method s is unchanged after function calls. Why?
Because s is passed by value. In other words - it's not the variable s that is passed but the value that s holds. The variable s in the called function and the variable s in the calling function are two different variables. Consequently, changes made to one of them does not change the other.
If you want to change s in the calling function inside the called function, you need to use call-by-reference.
Something like:
void MyString::rm_left_space(char*& s){
However, notice that your code have a major problem as it seems you are trying to assign s2 in the called function to s in the calling function. You should never do that as s2 goes out of scope as soon as the function returns.
Example: Difference between pass-by-value and between pass-by-value
This simple program uses pass-by-value
#include <iostream>
void foo(int x)
{
x = 42;
std::cout << "Inside foo: x=" << x << std::endl;
}
int main()
{
int x = 21;
std::cout << "Before foo: x=" << x << std::endl;
foo(x);
std::cout << "After foo: x=" << x << std::endl;
return 0;
}
The output is
Before foo: x=21
Inside foo: x=42
After foo: x=21 // notice x didn't change
because x in foo and in main are two different variables.
This simple program uses pass-by-reference
#include <iostream>
void foo(int& x) // Notice the &
{
x = 42;
std::cout << "Inside foo: x=" << x << std::endl;
}
int main()
{
int x = 21;
std::cout << "Before foo: x=" << x << std::endl;
foo(x);
std::cout << "After foo: x=" << x << std::endl;
return 0;
}
The output is
Before foo: x=21
Inside foo: x=42
After foo: x=42 // notice that x changed
because now x inside foo is a reference to x in main
These examples used int but exactly the same applies for pointers.
Example: Using pointers
#include <iostream>
int x = 21;
int y = 5;
void foo(int* p)
{
*p = 42;
p = &y;
std::cout << "Inside foo: p = " << p << std::endl;
std::cout << "Inside foo: *p = " << *p << std::endl;
}
int main()
{
int* p = &x;
printf("%p\n", (void*)p);
std::cout << "Before foo: p = " << p << std::endl;
std::cout << "Before foo: *p = " << *p << std::endl;
foo(p);
std::cout << "After foo : p = " << p << std::endl;
std::cout << "After foo : *p = " << *p << std::endl;
return 0;
}
Output:
Before foo: p = 0x60106c
Before foo: *p = 21
Inside foo: p = 0x601070
Inside foo: *p = 5
After foo : p = 0x60106c // Pointer value did NOT change
After foo : *p = 42 // Pointed to value DID change
Replacing
void foo(int* p)
with
void foo(int*& p)
will give:
Before foo: p = 0x60106c
Before foo: *p = 21
Inside foo: p = 0x601070
Inside foo: *p = 5
After foo : p = 0x601070 // Pointer value DID change
After foo : *p = 5 // Consequently, the pointed to value also changed

I am new to StackOverflow, if there's any mistake, please Kindly judge me
I am not sure that whether I was misunderstand what you mean, so if there's any misunderstanding, please let me know.
I guess you want to do remove left space in a string, right?
e.g.
" Hello" --> "Hello"
if so, here is my version
#include <iostream>
using namespace std;
#define SIZE 7
void rm_left_space(char* s){
int size = SIZE; //Because I don't know how to getSize, so I use fixed size instead
char s2[size];
char *s1 = &s2[0];
int i = 0;
while(*(s+i) == ' '){
i++;
}
cout << i << endl;
for (int k=i,l=0; k<size; k++) {//start from i, discarding spaces
*(s1+l) = *(s+k);
l++;
}
s=s1; // <-- Shallow copy
}
void rm_left_space_2(char* s){
int size = SIZE;
char *s2 = new char[SIZE]; <-- you should use dynamic array instead of static array
int space_num = 0;
while(*(s+space_num) == ' '){
space_num++;
}
for (int i = 0; i < SIZE; i++){
s2[i] = s[(i + space_num)%size];
}
// s = s2; // <--- shallow copy
for (int i = 0; i < SIZE; i++){ // You should copy whole array
s[i] = s2[i];
}
}
int main(){
char s[] = " hello";
cout << s << endl;
rm_left_space_2(s);
cout << s << endl;
return 0;
}
The output:
hello
hello
Also, you could check the post,
static array vs dynamic array in C++

Related

Pass reference of array of objects to function

I'm trying to change a parameter of an object inside an array, but it seems like it's creating a new one when I pass it to the function.
I already saw similar questions and answers like this one, but it doesn't work for me, because I don't have a fixed array size in the final code.
I created a very short version of the code to show the problem.
#include <iostream>
using namespace std;
class Vect {
public:
Vect(int x, int y)
{
_x = x;
_y = y;
}
int _x;
int _y;
};
void ChangeX(Vect tests[], int size)
{
for (int i = 0; i < size; i++) {
tests[i]._x = 39;
}
}
int main()
{
Vect v1 = Vect(1,2);
Vect v2 = Vect(6,3);
cout << "Initial X: ";
cout << v1._x;
cout << "\n";
Vect vectors[2] = { v1, v2 };
cout << "Final X: ";
ChangeX(vectors, 2);
cout << v1._x;
return 0;
}
I expect the output to be:
Initial X: 1
Final X: 39
But in reality is:
Initial X: 1
Final X: 1
Also, using C++ vectors is not the solution for now. I'm running low on program memory usage and have a very small space for extra code.
Your issue has nothing to do with your function. It is updating the contents of the array correctly. There is no need to pass the array itself by reference.
The real problem is with the array itself. The statement Vect vectors[2] = {v1, v2}; makes copies of the v1 and v2 objects in the array. Your function is modifying the copies, and then afterwards you output values from the originals instead of the copies. So, your output does not change, since the function is not modifying the originals.
To accomplish what you are attempting, pass in an array of pointers instead, where the pointers are pointing at the original objects, not copies of them, eg:
#include <iostream>
class Vect {
public:
Vect(int x, int y){
_x = x;
_y = y;
};
int _x;
int _y;
};
void ChangeX(Vect* tests[], int size){
for(int i = 0; i < size; i++){
tests[i]->_x = 39;
}
}
int main()
{
Vect v1(1,2);
Vect v2(6,3);
std::cout << "Initial X:\n";
std::cout << v1._x << "\n";
std::cout << v2._x << "\n";
Vect* vectors[2] = {&v1, &v2};
ChangeX(vectors, 2);
std::cout << "Final X:\n";
std::cout << v1._x << "\n";
std::cout << v2._x << "\n";
return 0;
}
Live Demo
Otherwise, start out with an array to begin with, eg:
#include <iostream>
class Vect {
public:
Vect(int x, int y){
_x = x;
_y = y;
};
int _x;
int _y;
};
void ChangeX(Vect tests[], int size){
for(int i = 0; i < size; i++){
tests[i]._x = 39;
}
}
int main()
{
Vect vectors[2] = {Vect(1,2), Vect(6,3)};
std::cout << "Initial X:\n";
std::cout << vectors[0]._x << "\n";
std::cout << vectors[1]._x << "\n";
ChangeX(vectors, 2);
std::cout << "Final X:\n";
std::cout << vectors[0]._x << "\n";
std::cout << vectors[1]._x << "\n";
return 0;
}
Live Demo

Get space for array with malloc

Trying to pass pointer for array:
class aaa{
public:
int a ;
int b ;
std::string c ;
};
void abc(aaa* a [])
{
*a = (aaa*)malloc(sizeof(aaa)* 5);
a[0]->c ="ddd" ;
a[1]->c ="ccc" ; //crash
a[2]->c ="eee" ;
}
int main() {
aaa * a;
abc(&a);
cout << "!!!Hello World!!!"<< a++->c << endl;
cout << "!!!Hello World!!!"<< a++->c << endl;
return 0;
}
On second array element assignment I have crash. Where is the problem? Does malloc not creates enough space?
UPD.
I can't change function void abc(aaa* a []) signature because of some reason. It is not mistakable signature even it looks not nice.
I have updated program according recomendations in answers, but I still have crash in getting second array element member:
cout << "!!!Hello World!!!"<< a[1].c << endl;
Why? What I do wrong in code below?
struct aaa{
public:
int a ;
int b ;
std::string c ;
};
int abc(aaa* a [])
{
int asize =5;
*a = (aaa*)malloc(sizeof(aaa) * asize);
for (int i;i<asize;i++)
{
a[i] = new aaa();
}
a[0]->c ="ddd" ;
a[1]->c ="ccc" ;
a[2]->c ="eee" ;
return asize;
}
int main() {
aaa * a;
int asize=abc(&a);
cout << "!!!Hello World!!!"<< a[0].c << endl;
cout << "!!!Hello World!!!"<< a[1].c << endl; //crash
cout << "!!!Hello World!!!"<< a[2].c << endl;
for (int i=0; i<asize;i++)
{
cout << "free "<<i<<endl;
a[i].~aaa();
}
free(a);
cout << "end"<<endl;
return 0;
}
The problems are multifold:
mallocing non-POD types so their constructors don't run (catastrophic)
Failure to free the things you malloc (bad)
mallocing in C++ at all (not stylish)
Passing aaa* a[] when you meant aaa** a (valid but misleading)
No #includes, or namespace qualifier on cout and endl (invalid testcase)
Here's what your program should look like:
#include <vector>
#include <string>
#include <iostream>
class aaa
{
public:
int a;
int b;
std::string c;
};
std::vector<aaa> abc()
{
std::vector<aaa> result;
result.reserve(3);
result.push_back({0, 0, "ddd"});
result.push_back({0, 0, "ccc"});
result.push_back({0, 0, "eee"});
return result;
}
int main()
{
const auto a = abc();
std::cout << "!!!Hello World!!!"<< a[0].c << std::endl;
std::cout << "!!!Hello World!!!"<< a[1].c << std::endl;
std::cout << "!!!Hello World!!!"<< a[2].c << std::endl;
}
(Live demo)
Or, to keep your five up-front element allocations:
std::vector<aaa> abc()
{
std::vector<aaa> result(5);
result[0].c = "ddd";
result[1].c = "ccc";
result[2].c = "eee";
return result;
}
I strongly suggest forgetting everything you know about C, when you write C++.
You can use malloc, but you still need to call constructors, for this you need new, this defeats idea of using malloc.
const int asize = 5;
void abc(aaa*& a)
{
a = (aaa*)malloc(sizeof(aaa) * asize); // you need to release memory later
for (int i = 0; i < asize; ++i) {
new (a+i) aaa(); // you need to call constructors to intialize string
}
// now you can use strings
a[0].c = "ddd";
a[1].c = "ccc";
a[2].c = "eee";
}
int main() {
aaa * a;
abc(a);
cout << "!!!Hello World!!!" << a[0].c << endl;
cout << "!!!Hello World!!!" << a[1].c << endl;
// finally you need to call destructors
for (int i = 0; i < asize; ++i) {
a[i].~aaa();
}
free(a);
return 0;
}
After showing you how you can make it work, i would like to propose another solution. If you care about memory and don't want to use std::vector, you can use std::unique_ptr.
std::unique_ptr<aaa[]> data;
data = std::make_unique<aaa[]>(asize);
data[0].c = "text";
cout << data[0].c;
// no need to manually release memory
EDIT:
As of updated question. If you really want to pass array of pointers then you can do the following:
const int asize = 5;
void abc(aaa* a[]) {
// If array is really big, then you probably should preallocate memory and call placement new for every element.
for (int i = 0; i < asize; ++i) {
a[i] = new aaa; // again, you have to release memory
}
// now you can use strings
a[0]->c = "ddd";
a[1]->c = "ccc";
a[2]->c = "eee";
}
int main() {
aaa * a[asize];
abc(a);
cout << "!!!Hello World!!!" << a[0]->c << endl;
cout << "!!!Hello World!!!" << a[1]->c << endl;
for (int i = 0; i < asize; ++i) {
delete a[i];
}
return 0;
}
It would be very nice if you could use unique_ptr instead of raw pointer.

Reference to pointer issue?

This is what i have:
void g(int *&x) {
int a = 3;
x = &a;
}
void h(const int *&x) {
int b = 2;
x = &b;
}
int main() {
int *p = new int;
*p = 5;
g(p);
cout << p << " " << *p << endl; // Print #2
cout << p << " " << *p << endl; // Print #3
const int*p1 = p;
h(p1);
cout << p << " " << *p << endl; // Print #4
cout << p << " " << *p << endl; // Print #5
}
From what i understand, Print#2 and Print#3 should have the same result but it isn't when i compile it. It goes for Print#4andPrint#5 too. Can someone help me?
Updated : This is the output looks like when i compiled it on my computer:
00EFF9D4 3 //1
00EFF9D4 1552276352 //2
00EFF9D4 2 //3
00EFF9D4 1552276352 //4
shouldn't (1) and (2) be the same ? (3) and (4) either.
I assume you mean int a in g().
Your function make the pointer point to a local variable, which after the termination of the function, will go out of scope.
You then dereference the pointer, which invokes Undefined Behavior.

C++ Swapping Pointers

I'm working on a function to swap pointers and I can't figure out why this isn't working. When I print out r and s in the swap function the values are swapped, which leads me to believe I'm manipulating a copy of which I don't understand because I pass by reference of p and q.
void swap(int *r, int *s)
{
int *pSwap = r;
r = s;
s = pSwap;
return;
}
int main()
{
int p = 7;
int q = 9;
swap(&p, &q);
cout << "p = " << p << "q= " << q << endl;
return 0;
}
Prints: p = 7q = 9
Inside your swap function, you are just changing the direction of pointers, i.e., change the objects the pointer points to (here, specifically it is the address of the objects p and q). the objects pointed by the pointer are not changed at all.
You can use std::swap directly. Or code your swap function like the following:
void swap(int *r, int *s)
{
int temp = *r;
*r = *s;
*s = temp;
return;
}
The accepted answer by taocp doesn't quite swap pointers either. The following is the correct way to swap pointers.
void swap(int **r, int **s)
{
int *pSwap = *r;
*r = *s;
*s = pSwap;
}
int main()
{
int *p = new int(7);
int *q = new int(9);
cout << "p = " << std::hex << p << std::endl;
cout << "q = " << std::hex << q << std::endl << std::endl;
swap(&p, &q);
cout << "p = " << std::hex << p << std::endl;
cout << "q = " << std::hex << q << std::endl << std::endl;
cout << "p = " << *p << " q= " << *q << endl;
return 0;
}
Output on my machine:
p = 0x2bf6440
q = 0x2bf6460
p = 0x2bf6460
q = 0x2bf6440
p = 9 q= 7
The line r=s is setting a copy of the pointer r to the copy of the pointer s.
Instead (if you do not want to use the std:swap) you need to do this
void swap(int *r, int *s)
{
int tmp = *r;
*r = *s;
*s = tmp;
}
You passed references to your values, which are not pointers. So, the compiler creates temporary (int*)'s and passes those to the function.
Think about what p and q are: they are variables, which means they are slots allocated somewhere in memory (on the stack, but that's not important here). In what sense can you talk about "swapping the pointers"? It's not like you can swap the addresses of the slots.
What you can do is swap the value of two containers that hold the actual addresses - and those are pointers.
If you want to swap pointers, you have to create pointer variables, and pass those to the function.
Like this:
int p = 7;
int q = 9;
int *pptr = &p;
int *qptr = &q;
swap(pptr, qptr);
cout << "p = " << *pptr << "q= " << *qptr << endl;
return 0;
You are not passing by reference in your example. This version passes by reference,
void swap2(int &r, int &s)
{
int pSwap = r;
r = s;
s = pSwap;
return;
}
int main()
{
int p = 7;
int q = 9;
swap2(p, q);
cout << "p = " << p << "q= " << q << endl;
return 0;
}
Passing by reference is not the same as passing by value or by pointer. See C++ tutorials on the web for an explanation. My brain is too small to waste cells storing the fine details I can find on the web easily.
If you are into the dark arts of C I suggest this macro:
#define PTR_SWAP(x, y) float* temp = x; x = y; y = temp;
So far this has worked for me.

C++ how to overload method using pass by value and pass by reference

How do I make the following overload work
#include <iostream>
using namespace std;
int subtractFive (int a)
{
a = a - 5;
return a;
}
int subtractFive (int &a)
{
a = a -5;
return a -5;
}
int main()
{
int A = 10;
cout << "Answer: " << subtractFive(*A) << endl;
cout << "A Value "<< A << endl;
cout << "Answer: " << subtractFive(A) << endl;
cout << "A Value "<< A << endl;
return 0;
}
Tried but doesnt compile
#include <iostream>
using namespace std;
int subtractFive (int a)
{
a = a - 5;
return a;
}
void subtractFive (int* a)
{
*a = *a -5;
}
int main()
{
int A = 10;
cout << "Answer: " << subtractFive(A) << endl;
cout << "A Value "<< A << endl;
subtractFive(A);
cout << "A Value "<< A << endl;
return 0;
}
You might try specifying an overload that takes an address as an argument:
int subtractFive (int *a)
{
*a = *a -5;
return *a -5;
}
Declare one function as pass by address the other by value or reference:
void subtractByFive(int * p_value)
{
if (p_value != NULL)
{
*p_value -= 5;
}
return;
}
A value and a reference have the same type so you can't overload on it. If you want two functions one of which modifies its parameter and one that returns the new value then you either have to give them different names or different types (e.g. make the latter function use a pointer type).