I'm trying to use strtok to break up a string and push into a stack. could be integers or '+' or '-' signs. i have traced the problem to the push function, and void ** a is a void pointer to array.
It prints out garbage value when i did the cout << getVP(a) << " " ;
my getVP function
int Stack::getVP (void* a) const
{
return *(static_cast <char *>(a));
}
Please don't ask me why i'm not using std::Stack. I'm not tasked to do so yeah got to do it in array.
edited: made some changes to my codes, right now when i store it in void * temp, it doesn't print out the right input. anyone?
Your code is all over the place:
This code is incorrect - comments are corrects/notes:
void Stack::push (char* temp)
{
a = new void * [MAX]; // Assume a is a member variable of type 'void **' it will
// be a memory leak for starters. Why not make a an array
// or char *. i.e.
// char *a[MAX];
// or better string string a[MAX];
if (!isFull())
{
top = top + 1;
*a = temp; // This is incorrect - should be a[top] = temp;
// Possibly want to duplicate temp here
cout << getVP(a) << " " ; // Why make this complicated function
// Just cout << a[lop] << endl; would do
++a; // Not needs and confuses things
}
}
Related
My college professor recently gave us a task of implementing our own smart pointer classes. In his boilerplate code for copying strings I found this piece beautiful syntactic sugar:
while (*sea++ = *river++);// C Sting copy
I looked further into this code and found that it is the exact code as found in strcpy.c and further explanation of how it works, in the following stackoverflow question:
How does “while(*s++ = *t++)” copy a string?
When I tried to use this syntactic sugar in my following code it gave garbage as a result and deleted the string stored in "river":
#include<iostream>
#include<cstring>
using namespace std;
void main()
{
const char *river = "water";// a 5 character string + NULL terminator
char *sea = new char[6];
while (*sea++ = *river++);
cout << "Sea contains: " << sea << endl;
cout << "River contains: " << river << endl;
}
RESULT:
I know that I can simply achieve the desired result with the following code instead:
int i = 0;
while (i<6)
{
sea[i] = river[i];
i++;
}
But this is not the answer I want. I would like to know is there something wrong with the implementation of my while loop or the instantiation of my char pointers?
You are getting garbage displayed because your pointers are pointing at garbage when you go to display them. You are advancing the pointers while looping, but you need to use the original pointers when displaying the data.
Also, you have a memory leak, as you are not freeing the char[] buffer.
Try this instead:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
const char *river = "water";// a 5 character string + NULL terminator
char *sea = new char[6];
const char *p_river = river;
char *p_sea = sea;
while (*p_sea++ = *p_river++);
cout << "Sea contains: " << sea << endl;
cout << "River contains: " << river << endl;
delete [] sea;
return 0;
}
The "error" is technically an undefined behavior due to pointer gone out of bound respect to to the memory they refer.
The interesting part is WHY that happens.
And it is due by the confusion between the pointers and what they point to.
sea and river are not strings. The strings are anonymous variable residing somewhere in memory, with the two pointer indicating their start.
You should never touch them, otherwise you will be no more able to access those strings further.
If you need to move pointers, use other ones.
A more proper example should be this one
using namespace std;
int main() //< note `void main` is a C++ dialcet
{
// note the use of `const` after the `*`:
// you cannot modify these pointers.
const char * const river = "water"; // a 5 character string + NULL terminator
char * const sea = new char[6];
{
// in this inner scope, other non-const pointers are
// initialized to point to the same memory
const char* r = river;
char* s = sea;
while (*s++ = *r++); // the loop moves the mutable pointers
// note how `river++` or `sea++` is an error, being them `*const`
}
// there are no more `r` and `s` here, but `sea` and `river` are still the same.
cout << "Sea contains: " << sea << endl;
cout << "River contains: " << river << endl;
//now we have an array allocated with new to return to the system
delete[] sea; //< the importance to not move the `sea` pointer
}
Note how delete deletes the array, not the pointer.
To go more in advance, two things can be done.
The first is make the inner scope a proper function:
using namespace std;
void copy(const char* r, char* s)
{
// in this function, other non-const pointer (parameters) are
// initialized to point to the same memory upon call
while (*s++ = *r++); // the loops moves the mutable pointers
// note how `river++` or `sea++` is an error, being them not visible.
}
int main() //< note `void main` is a C++ dialect
{
const char * const river = "water"; // a 5 character string + NULL terminator
char * const sea = new char[6];
copy(river, sea);
cout << "Sea contains: " << sea << endl;
cout << "River contains: " << river << endl;
//now we have an array allocated with new to return to the system
delete[] sea; //< the importance to not move the `sea` pointer
}
and the second is get rid of the new/delete pair in a same context, using -for example- an std::unique_ptr<char[]>
But this is taking too far!
Because ASCII-art is always useful for figuring out pointer problems...
This is before your while loop:
river points to
|
V
+-+-+-+-+-+--+
|w|a|t|e|r|\0|
+-+-+-+-+-+--+
+-+-+-+-+-+-+
|?|?|?|?|?|?|
+-+-+-+-+-+-+
^
|
sea points to
But after your loop, you have this:
river points to
|
V
+-+-+-+-+-+--+
|w|a|t|e|r|\0|
+-+-+-+-+-+--+
+-+-+-+-+-+--+
|w|a|t|e|r|\0|
+-+-+-+-+-+--+
^
|
sea points to
So you see, the copy has indeed been performed, but you've also moved the pointers. That means if you try and print them out, you'll get whatever garbage lies after those memory blocks.
Were you to save copies of the pointers from before the while loop, and print those out instead, you'd get the output you're looking for.
Class C {
struct Something {
string s;
// Junk.
}
// map from some string to something.
map<string, Something> map;
// Some more code:
const Something *Lookup(string k) const {
const something *l = SomeLookUpFunction();
cout << l;
cout << &l->s;
cout << l->s;
return l;
}
}
// Some Test file
const C::Something *cs = C::Lookup("some_key");
cout << cs;
cout << &cs->s;
cout << cs->s;
The weird thing is this outputs:
* For lookup fucntion:
0x9999999
0x1277777
some_string
* For test code
0x9999999
0x1277777
000000000000000000000000000000000000000000 ....
In test file it gives a very long string of zeros, but the addresses are the same. Any idea what could be going wrong ?
Since you have not shared code for function SomeLookUpFunction, I have to guess that you are returning pointer to local object of type Something. This is a bad idea, see similar QA.
To start fixing your code, you should start by returning simple object, instead of pointer, as shown below:
// Some more code:
const Something lookup(string k) const {
const something l = SomeLookUpFunction(); // return simple object
cout << &l;
cout << &l.s;
cout << l.s;
return l; // same object
}
Of course you should improve the code by providing copy constructors for type something and even improving your map.
I wrote a simple function to perform in place reversal:
void in_place_reverse(char *str){
if(!str || !(*str)){
return;
}
char *str_end = str+strlen(str)-1;
int temp;
while(str < str_end){
temp = *str;
*(str++) = *str_end;
*(str_end--) = temp;
}
}
I'm just wondering why when I do something like this:
char str[] = "Reverse me!";
cout << "Original: " << str << endl;
in_place_reverse(str);
cout << "Reversed: " << str << endl;
str wasn't changed inside of the function. The reason I ask is because the line *(str++) is incrementing the pointer that points to str. So what I'm really asking is why something like this isn't necessary:
char *str_beg = str;
char *str_end = str+strlen(str)-1;
int temp;
while(str_beg < str_end){
temp = *str_beg;
*(str_beg++) = *str_end;
*(str_end--) = temp;
}
So that we're not actually changing the pointer that points to the first position of str.
You actually are doing this implicitely because 'str' is passed by value (read: 'as a copy in a temporary variable').
To clarify this without the (distracting) pointer: consider
void increment(int x) {
x++;
}
int i = 1;
cout << i << endl;
increment(i);
cout << i << endl;
This will print '1' twice. The x that is seen inside the increment routine has the same value like the passed i. But it is not the same variable i. In fact it is a copy of i. When we return from the routine, the copy is discarded. Further reading: This would be different if we'd pass x by reference, like so:
void increment(int &x) {
x++;
}
The declaration of the function void in_place_reverse(char *str) results in a copy of the pointer being created when the function is called, in a variable called str that is private and local to the in_place_reverse. You can modify this value all you like without affecting the original that exists in the scope of the calling function.
I realize the way I am approaching this is wrong, but I don't know why.
I am very new to C++/programming in general.
I want my program to do the following.
If I cin "setwanted joe" I want it to store joe into a char array. I have it so I can succesfully seperate and cout joe, but I am can't return the char array from the function.
Here's my example code.
char * GETNAME (char *searchinput, char*searchtext)
{
char returnname[64];
int starter=0;
for(;;)
{
if (*searchinput == *searchtext)
{
searchinput++;
searchtext++;
}
if (*searchinput == ' ')
{
searchinput++;
searchtext++;
}
if (*searchinput!='\0' && *searchinput!= *searchtext && *searchinput != ' ')
{
returnname[starter] = *searchinput;
starter++;
searchinput++;
searchtext++;
}
if (*searchinput=='\0')
{
returnname[starter]='\0';
cout << "Char Array to Return: " << returnname << endl;
return returnname;
}
}
}
Above is the function I made to try to return the name from the char array.
Here is the code I was using to call the function.
char Recv[256];
cin >> Recv;
char * wantedname = new char[64];
wantedname = GETNAME(Recv,"setwanted");
cout << "Returned Name: " << wantedname << endl;
Thanks for reading/your patience I know this is messy.
Use std::array, std::vector or std::string (in case of array of characters) to easily return an array of items. You're code invokes undefined behavior due to returning a pointer to a local temporary object. I prefer this
std::string GETNAME(const std::string &searchinput,const std::string &searchtext)
{
std::string returnname;
...
return returnname;
}
The following sample of code if from a book "C++ von A bis Z" (second edition, translation: C++ from A to Z) at page 364. The sample is wrong.
// overload operator +=
#include <iostream>
#include <cstring>
using namespace std;
class String {
private:
char* buffer;
unsigned int len;
public:
String(const char* s="") {
// cout << "Constructor: " << s << "\n";
len = strlen(s);
buffer = new char [len+1];
strcpy(buffer, s);
}
~String() {
// cout << "Destructor: " << buffer << "\n";
delete [] buffer;
}
String(const String& s) {
// cout << "Copy_Constructor: " << s.get_buffer() << "\n";
len = s.len;
buffer = new char [len+1];
strcpy(buffer, s.buffer);
}
char* get_buffer() const {
return buffer;
}
// returning a reference is more efficent
// String& operater+=(const String& str1)
String operator+=(const String& str1) {
// cout << "Assignment_Operator +=: " << str1.get_buffer() << "\n";
String tmp(*this);
delete [] buffer;
len = tmp.len + str1.len;
// invalid pointer
// buffer = new char[len+1];
buffer = new char [len]+1;
strcpy(buffer, tmp.buffer);
strcat(buffer, str1.buffer);
// wrong return_type
// return *this;
return buffer;
}
};
int main(void) {
String string1("Adam");
String string2("Eva");
string1+=" und ";
string1.operator+=(string2);
cout << string1.get_buffer() << "\n";
return 0;
}
The lines with the comments are my "fixes". Now I want to know what "new char [len]+1" does? I think the following:
it allocates sizeof(char)*len memory from heap
and returns the WRONG address to the pointer *buffer
but what is the wrong address: "first address of the new memory on heap + 1" or "first address of the new memory on heap + sizeof(char)*1)?
What happens?
Thanks
// edit
Thank you all! You helped me!
I just wanted to know, what this statement will return.
new char [len]+1;
The line itself is, of course, a typo from the author of the book.
Let's break it down:
new char[len];
returns a pointer to an array of char.
new char[len] + 1;
returns the next address in memory.
It's basically cutting off the first character.
EDIT: As others have mentioned, this is most probably a typo, it should be new char[len+1]. I'm just explaining what the code does, but you should only use pointer arithmetics if you really know what you're doing. Trying to delete the returned pointer would be UB, as cHao pointed out. You'll also get UB if len == 1 and attempt to work with the returned pointer.
If you add an integer i to a T*, this will add sizeof(T) * i to the pointer. So in this case, since new char[len] returns a char*, + 1 will indeed add sizeof(char) * 1 to it.
new Type[size] + 1 will allocate an array of size size and yield the address of the element with index 1 - that the second element. Nothing special, just pointer arithmetic. new[] would yield the address of the element with index 0 and size +1 is done on that address it yields address of element with index 1.
It simply returns the pointer to the second array item =)
Read about C pointers ;)
+sizeof(char)*1, but I failed to see why did you do it.
I think it's a typo, and it should be new char [len+1]. The +1 is for the string terminator character that must exist.