I'm learning to use pointer to copy char array.
I have the following code in C++. What I'm trying to do is to transfer and array (set1) using pointer to another pointer array (temp).
But when I try to print out (temp), it is not the same as (set1).
Transfer an array via pointer to another temp array pointer.
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
char set1[] = "ABC";
char* p = &set1[0];
int tempSize = 0;
char* temp = new char[256];
for (int i = 0; i < 3; i++)
{
*temp = *p;
cout << *temp; // ABC
++temp;
++tempSize;
++p;
}
cout << "\n";
for (int i = 0; i < tempSize; i++)
{
cout << temp[i]; // Why ABC is not printed?
}
delete [] temp;
return 0;
}
// Why ABC is not printed?
Because your pointer is travelling in undefined behavior region:
char* temp = new char[256];
...
++temp; // gone !!
On top of that,
you are not terminating the string with \0 in the end (may not be needed in your code)
delete[]ing this corrupt pointer in the end.
Since you are writing for learning purpose, I would suggest simple fix to your code:
char* const temp = new char[256];
^^^^^ ensures `temp` is not modifiable
Now use temp[i] for traversing purpose.
It's because in the loop copying the array, you change temp. After the loop, it points to one beyond the copied data.
Also, you forget to terminate the new allocated array. You should add the character '\0' at the end.
The problem is this line:
++temp;
You are incrementing the pointer and then write to it. In the end temp[i]; does not point to the beginning of your string, but to the end.
The easiest way to do this is to remove the first for loop with:
for (int i = 0; i < 3; i++)
{
temp[i] = set1[i];
}
temp[4] = '\0'; // don't forget to close the string
C-style strings have a null terminator - "ABC" contains four characters. Also, I'm not at all sure that the delete call on temp is valid - you have been incrementing it since it was 'newed'.
Related
I have a problem that my code
char* strdup(const char* s)
{
int n = 0;
for(; *s != 0; s++)
{
n++;
}
char* p = new char[n+1];
for(int i = 0; i < n; i++)
{
p[i] = s[i];
}
p[n] = 0;
return p;
}
int main()
{
const char* p = "testing";
char* p_copy = strdup(p);
std::cout << p << '\n' << p_copy << std::endl;
return 0;
}
doesn't work as intended.
I want to write a function which takes in const char* and copies it to a new allocated char memory. When it is done it should return a pointer to the char.
Now when I try it out my output is simply:
testing
thanks for any help in advance
Try not incrementing s before you start copying it to p. I notice that in your first for loop you increment s until it points at a null, and then later use that pointer value to start your string copy. No wonder you are getting a null string.
Here:
for(; *s != 0; s++)
You increment s. So it no longer points to the beginning of the input string. It points to the null terminator of the string. Then, here:
for(int i = 0; i < n; i++)
{
p[i] = s[i];
You try to copy n characters starting from the null terminator, and you end up reading past the end of the array which has undefined behaviour.
Solution: Make a copy of s for counting the characters:
const char* s2 = s;
for(; *s2 != 0; s2++)
Even better, you could refactor the length counting part into a reusable function called strlen.
I am having a problem with passing a char* to an array of char** on my Teensy.
Below is the problematic part:
for (j = 0; j < rulesamountsingle; j++) {
emptybuffer(buff);
char temp[10];
while(!Serial.available());
len = Serial.available();
for (i = 0; i < len; i++) {
temp[i] = Serial.read();
}
temp[len-1] = 0;
fuzzyRulesSingle[j] = temp;
Serial.print(fuzzyRulesSingle[j]);
Serial.print('\n');
}
As you can see, fuzzyRulesSingle[j] (where fuzzyRulesSingle is a char**) will be filled by the variable temp (a char*). As I increment j, the next address in fuzzyRulesSingle will be filled by a new temp.
However, when I print my fuzzyRulesSingle OUTSIDE the code above, all fuzzyRulesSingle will be filled with the last value of temp.
Where have I gone wrong?
You are pointing fuzzyRulesSingle[j] to the temporary char array temp.
A simple way to fix this is to change the fuzzyRulesSingle[j] = temp; to strcpy(fuzzyRulesSingle[j], temp) and changing the declaration of fuzzzyRulessSingle to the size required.
OR
you can declare temp outsize the loop and use malloc to allocate memory necessary and then assign it to fuzzyRulesSingle[j]
I am having issues de-allocating memory that I used in my char* array. In my code snippet below, I am creating a char* array named input that holds pointers to single words at a time followed by a pointerNULL at the end of the array. This is the only time (I believe) I allocate memory in my code.
char* input[999];
//exec commands
for(unsigned int i = 0; i < commands.size(); i++)
{
string current = "";
string word = "";
int k = 0;
for(unsigned int j = 0; j < commands.at(i).size(); j++) //iterate through letters
{
current = commands.at(i);
//cout << "current: " << current << endl;
if(current[j] == ' ')
{
input[k] = new char[word.size() + 1];
strcpy(input[k], word.c_str());
k++;
word = "";
}
else
word += current[j]; //add letter
//cout << "word: " << word << endl;
}
input[k] = new char[word.size() + 1];
strcpy(input[k], word.c_str());
k++;
input[k] = new char[1]; //add the NULL char *
input[k] = NULL;
...
Later on, I attempt to de-allocate this memory with this snippet of code:
for(int z = 0; z < k; z++)
{
delete[] input[z];
}
I am iterating through my char* array and deleting the memory allocated at each index. Without using this snippet, valgrind informs me of memory leaks. Using this snippet, valgrind informs me of less memory leaks than before. I am still stuck with the issue of memory still being definitely lost.
I am unsure what I am missing to remove the rest of the allocated memory (or if the cause of the rest of the memory leaks is in fact somewhere else in my code). I appreciate any and all help, suggestions, and tips.
I think, your problem is in below case,
input[k] = new char[1]; //add the NULL char *
input[k] = NULL;
here, without free-ing input[k], you're assigning NULL to it. Thus, the previous input[k] is lost.
If you really want input[k] to hold NULL, (maybe as a sentinel value), you can simply do
input[k] = NULL;
No need to allocate memory separately.
You don't need to create a new char on where it says input[k] = new char[1]; //add the NULL char * Just leave the NULL assignment in and it should work fine.
I need reverse my char string only with pointers. How can I do this? My code:
// this cannot be modified !!!
char s[10] = "abcde";
char *pS;
// my code
pS = new char;
int count = 5;
for (int i = 0; i < 10; i++)
{
if (s[i] != '\0') // not null
{
pS[count - 1] = s[i];
count--;
}
}
cout << "Reversed = " << pS;
Sometimes if works fine, I see only 5 chars, they are reversed. But sometimes I see some extra chars (looks like temp symbols). Where I miss something? Thank you!
your char array "s" contains 10 chars, but you only initialize the first 6 chars of that array with "abcde" and the \0 terminator.
When you loop over the complete array, you access not initialized chars.
I also see, that you try to write to memory, which you didn't allocate.
You only allocate memory for 1 char for you "pS" pointer, but you try to access it's memory like it is an array of chars in your for-loop.
Instead of using hardcoded:
int count = 5;
you also could use the string function strlen() to determine the length of the c-string.
Edited (untested code):
char s[10] = "abcde";
char pS[10];
for (int i = 0; i < strlen(s); i++)
{
if (s[i] == '\0') // not null
{
// stop loop, as soon as you reach the end of the original string
break;
}
pS[strlen(s) - 1 - i];
}
// now add the termination char \0 to your pS array
pS[strlen(s)] = '\0';
cout << "Reversed = " << pS;
Just giving you the hint how to reverse the string using pointers:
Take two pointers front and rear where front is pointing to first char of string and rear is pointing to last char of string.
Check if front is less than rear
If yes, swap the value of first and last character. If no , just print the string.
Increment front pointer and decrement rear pointer
Repeat from step 2.
After reading another book I fully understand pointers and how to correctly allocate memory. Here is my final code which correctly reverse array of char string (I don't need universal code, just working example + without std methods for reversing):
// not edited part - based on exercise (I mean I cannot change pS to char[5] etc.
char s[10] = "abcde";
char *pS;
pS = new char[strlen(s) + 1]; // allocate correct memory size based on string size
cout << "Size is " << sizeof(pS) << endl; // just for testing
int count = strlen(s); // for iteration
pS[count] = '\0'; // last symbol must be '\o' (thanks to Mr.Yellow)
for (int i = 0; i < 10; i++) // 10 because array of char still has 10 elements
{
if (s[i] != '\0') // looks like "not garbage memory"
{
count--;
pS[count] = s[i]; // set correct value
}
}
cout << "Reversed = " << pS << endl;
Thank you to all who helps me!
I am fairly new to C++, and this problem I am having has had me stumped for like the last 2 hours. What I am trying to do is create an array of pointers to my class Word objects, so a 2 dimensional array, which is **wordPtrList. Then I need to delete the memory of certain objects in the array and set their pointers to null. I have written a smaller version of what I am trying to accomplish below.
int main()
{
char *cArray;
cArray = new char[4];
int i;
for (i = 0; i < 3; i++)
cArray[i] = 'a';
cArray[i + 1] = '\0'; //cArray is a null terminated string
Word **wordPtrList;
wordPtrList = new Word* [3];
for (i = 0; i < 3; i++)
{
wordPtrList[i] = new Word(cArray);
}
wordPtrList[1]->del();
delete wordPtrList[1];
wordPtrList[1] = '\0';
return 0;
}
class Word
{
private:
char* ptr_;
int len_;
public:
Word(const char* word)
{
len_ = strlen(word);
ptr_ = new char[len_];
strcpy(ptr_, word);
}
~Word()
{
delete [] ptr_;
ptr_ = 0;
}
void del()
{
delete [] ptr_;
ptr_ = 0;
return;
}
};
When I do this however, I get:
Debug Error Heap Corruption Detected after normal block
This is in VS 2010 on Windows 7.
So what I am asking is, how do I delete the memory of my object so that I can set wordPtrList[1] to Null?
You are allocating 4 bytes to cArray (meaning you have access to write to bytes 0 through 3), and then writing to cArray[4]. You also allocate one byte too small in the Word constructor.
char *cArray;
cArray = new char[4];
int i;
for (i = 0; i < 3; i++)
cArray[i] = 'a';
cArray[i] = '\0'; //cArray is a null terminated string - i is now 3
and
Word(const char* word)
{
len_ = strlen(word);
ptr_ = new char[len_ + 1];
strcpy(ptr_, word);
}
should do the trick.
Look at this code:
for (i = 0; i < 3; i++)
cArray[i] = 'a';
cArray[i + 1] = '\0'; //cArray is a null terminated string
The problem is at the last line which is using i+1 as index, which is going out of range, as by the time the loop exits, the value of i is already 3; that means i+1 will become 4 which cannot be a valid index when you've allocated cArray as:
cArray = new char[4]; //taken from your code
The solution is this:
cArray[i] = '\0'; //Now, it is correct. Here i is equal to 3
That is, use i instead of i+1; Or simply use 3.
In C++, you could std::fill instead of manual loop, as:
std::fill(cArray, cArray + 4, 'a'); //done
Even better avoid using char* with new as much as possible, and prefer using std::string instead.
There are two obvious off-by-one errors in the code (when you get out of the first loop what is the value of the variable i? when calling strlen did you remember to consider the space needed by the null terminator?).
Also please note that c strings are not "null terminated", they are "NUL terminated" with uppercase letters and only one "L". NUL is the name of the ASCII control character with all bits set to zero and is represented in C++ with '\0'.
In one place you used NUL character as a null pointer, and while this is technically correct (because of a design bug of the C++ language) it's better to understand that the two concepts are quite different.
As others have said, you're basically accessing an array index which is out of bounds of the array.
I would go with Nathan Wiebe's solution.
In the future, when you have the option to do this, it's recommended to use std::vector<T> as that will allow you to store any type you wish in a dynamically resizeble array. In other words, providing you don't access an index which is outside of the vector's bounds, you could do something like this:
std::vector< char* > str;
for( size_t i = 0; i < str.size(); ++i )
{
str.push_back( 'a pointer to a block of memory consisting of characters' );
}
class Word
{
public:
Word( const char* str )
{
mStrs.push_back( str );
}
~Word( void )
{
for( size_t i = 0; i < mStrs.size(); ++i )
{
if( mStrs[ i ] )
{
delete mStrs[ i ];
mStrs[ i ] = NULL;
}
}
mStrs.clear();
}
private:
void del( size_t index )
{
if( index > mStrs.size() )
{
//error - throw new exception or something
}
delete mStrs[ index ];
}
std::vector< const char* > mStrs;
};