Do not understand about strcpy in C++ - c++

char* s1;
strcpy(s1,"smilehihi");
s1[6] = 'a';
When I compile, VS do not have any errors. But in the runtime, my code makes mistake. I think I do not really understand about strcpy

The main issue here is not the strcpy() function but the fact that you don't allocate any memory for the string itself.
If I were you, I would do something like
char* s1=(char*)malloc(SIZE); // the SIZE is the predefined maximum size of your string
strcpy(s1,"smilehihi");
s1[6] = 'a';
Edit:
Just as an advice, consider using stpncpy(). It helps to avoid buffer overflow, and, in your case, will help you avoid exceeding the maximum size of char*
char * stpncpy(char * dst, const char * src, size_t len);

The problem is that you have not allocated any space for what you wish to store in s1: "smilehihi". You declare s1 as a pointer variable, but it needs something to point at. You can allocate space by using the new operator.
char* s1 = new char[stringLength + 1]; //stringLength = length of string stored
// + 1 to hold null terminator character
strcpy(s1, "smilehihi");
s1[6] = 'a';
You have to declare #define _CRT_SECURE_NO_WARNINGS at the top of your main file to avoid an error during compilation due to strcpy() being deprecated.

You need to allocate variable first by malloc() or by using the keyword new .
Also deallocate the memory at the end

At first you should allocate char* s1.
char *s1 = new char[9]; // C++ version
or you can you use C version:
char *s1 = (char*)malloc(9);
Then you can use following code:
strcpy(s1, "smilehihi");
s1[6] = 'a';

Related

String to const char * in c++ puts garbage at end

I have a struct that needs to store const char * for later. The string gets destroyed by then. The code that i have till now for the same is
HttpRequest* send(string reply)
{
int len = strlen(reply.c_str());
char *buffer = new char[len+1];
strncpy(buffer, reply.c_str(), len);
cout << "LEN:"<<reply.length()<<endl;
cout << "OG:"<<reply<<endl<<"TC:"<<buffer<<endl<<"CS"<<reply.c_str()<<endl;
this->res.response = "test";
return this;
};
res.response is the char * that i want to store the value in. The output from cout that i am getting is
LEN:5
OG:hello
TC:hello�������������������q{
CShello
This behavior is pretty strange to me. Can someone please explain what i am doing wrong. Also the above code shows me using strlen but i am getting the same result using length() in c++ also.
Also it is worth mentioning that this happens only the first time that i invoke this, after that it goes fine.
You never put the null terminator:
char *buffer = new char[len+1];
strncpy(buffer, reply.c_str(), len);
buffer[len] = 0; // <-- HERE
strncpy doesn't add it.
Your arguments to strncpy() make the function misunderstand that there is no space for terminating null-character, so it isn't written. Correct the argument like
strncpy(buffer, reply.c_str(), len+1);
In this code, it is guaranteed that the length of buffer is sufficient to store the string, so you can simply use strcpy() instead of the strncpy() like this:
strcpy(buffer, reply.c_str());
You can use strdup() function if your system supports it. Using it, the lines
int len = strlen(reply.c_str());
char *buffer = new char[len+1];
strncpy(buffer, reply.c_str(), len);
can be replaced with
char *buffer = strdup(reply.c_str());
Note that strdup() is a function from C and it uses malloc() internally, so you must use free(), not delete[], to free the memory allocated via strdup().
Don't use strncpy until you've read and understood its documentation. And then don't use it. It's a very specialized function, and there's no need to deal with its quirks here. The code in the question allocates enough space for the result, so just use strcpy.
The problem is that this statement
strncpy(buffer, reply.c_str(), len);
does not copy the terminating zero ( '\0' ) of the original string to buffer.
You should use the standard C function strlen with objects of type std::string only in case when the objects contain embedded zeroes. Otherwise use member functions of the class std::string size or length.
Instead of the standard C function strncpy you could use standard C function strcpy to copy the zero-terminated string in the buffer.
For example
char *buffer = new char[len+1];
strcpy( buffer, reply.c_str() );

Deleting a dynamic array after it has been returned from a function

I am new to C++ and paranoid of memory leaks. I'll strip my code down to just the important bits:
If I have a function like this:
char * myString = "Discombobulate";
char * ToUppercase()
{
int length = strlen(myString);
char * duplicateString = new char [length];
strcpy(duplicateString, myString);
//char arithmetic to turn every letter in duplicateString to uppercase
return duplicateString;
}
Obviously, I need to perform a delete[] to avoid memory leaks. Now what I wanted to know is if I can do the delete in main(), like so:
int main () {
char * result = Upper();
std::cout << result << std::endl;
delete[] result;
}
Will this work properly? Is there any catch to doing it like this?
Now what I wanted to know is if I can do the delete in main()
Yes, you can and you should.
BTW1: Think about using std::string, std::vector, smart pointers, to avoid such kind of manual memory management, since it's c++.
BTW2:
char * duplicateString = new char [length];
should be
char * duplicateString = new char [length + 1];
The last position will be used for the terminating null character '\0'.
Will this work properly?
Yes. As long as it is a valid pointer, you could delete it outside of the function that called new. Should you? Well...
Is there any catch to doing it like this?
Yes. It's bad practice. You're allocating resources in a function and expecting the caller to clean them up. It goes against RAII, as people in the comments have explained. Along with the advice to use std::string (do use it), you can use std::unique_ptr and friends instead of raw pointers.
YEs you can delete it the way you have... By the way, you can also assign memory for the pointer and pass that as a parameter to the function and delete it after it returns from the function.
char * duplicateString = new char [length + 1];
ToUppercase(char* duplicateString );
if( duplicateString ){ delete []duplicateString ; duplicateString = NULL;}

exception of strcpy function in c++ console program

exception in strcpy();
void recid(string str,int *begin, int *end)
{
char *f,*str2;
const char c1[2]=":",c2[2]="-";
strcpy(str2,str.c_str());
f=strtok(str2,c1);
f=strtok(NULL,c2);
*begin=atoi(f);
f=strtok(NULL,c2);
*end=atoi(f);
}
could you help me to solve it?
str2 is an uninitialised pointer. strcpy does not allocate memory so is currently trying to write to an arbitrary address which you don't own and very likely isn't writable by your code.
You need to point str2 to valid memory before calling strcpy.
str2 = (char*)malloc(str.size()+1);
strcpy(str2,str.c_str());
You should also free the memory later in your program
free(str2); // cannot dereference str2 after this point
The problem is that you write in an uninitialized/random memory location by not initializing str2.
First solution:
str2 = new char[str.size() + 1];
strcpy(str2, str.c_str());
...
delete[] str2.
Second (better solution): Do not use pointers in your code unless you have to:
std::string str2 = str1;
Also, consider using std::ostringstream for tokenization into std::strings and converting to int.

How can I transfer string to char* (not const char*)

I wanna do something like:
string result;
char* a[100];
a[0]=result;
it seems that result.c_str() has to be const char*. Is there any way to do this?
You can take the address of the first character in the string.
a[0] = &result[0];
This is guaranteed to work in C++11. (The internal string representation must be contiguous and null-terminated like a C-style string)
In C++03 these guarantees do not exist, but all common implementations will work.
string result;
char a[100] = {0};
strncpy(a, result.c_str(), sizeof(a) - 1);
There is a member function (method) called "copy" to have this done.
but you need create the buffer first.
like this
string result;
char* a[100];
a[0] = new char[result.length() + 1];
result.copy(a[0], result.length(), 0);
a[0][result.length()] = '\0';
(references: http://www.cplusplus.com/reference/string/basic_string/copy/ )
by the way, I wonder if you means
string result;
char a[100];
You can do:
char a[100];
::strncpy(a, result.c_str(), 100);
Be careful of null termination.
The old fashioned way:
#include <string.h>
a[0] = strdup(result.c_str()); // allocates memory for a new string and copies it over
[...]
free(a[0]); // don't forget this or you leak memory!
If you really, truly can't avoid doing this, you shouldn't throw away all that C++ offers, and descend to using raw arrays and horrible functions like strncpy.
One reasonable possibility would be to copy the data from the string to a vector:
char const *temp = result.c_str();
std::vector<char> a(temp, temp+result.size()+1);
You can usually leave the data in the string though -- if you need a non-const pointer to the string's data, you can use &result[0].

How to make an array to store char arrays of variable size?

I need an array to store char arrays of variable size. I could use vectors or anything else, but unfortunately this is for a MPI project and I am forced to use an array so I can send it using MPI::COMM_WORLD.Send(...) function.
My idea comes from this link.
This is a simplified example of the problem I have:
char* arrayStorage[3]; //I want to store 3 char arrays of variable size!
int index = 0;
char array_1[RANDOM_SIZE] = {.....};
char array_2[RANDOM_SIZE] = {.....};
char array_3[RANDOM_SIZE] = {.....};
arraySorage[index] = array_1;
index++;
arraySorage[index] = array_2;
index++;
arraySorage[index] = array_3;
index++;
I have also seen people talking about malloc and stuff like that, but I don't know much about pointers. I do malloc, I have to call free and I don't know where, so I am avoiding that for now.
This code obviously doesn't work, array_1, array_2, array_3 are all OK, but when I try to access them I get garbage. The problem seems to be inside the index variable. Maybe I shouldn't be doing index++, perhaps I should be doing index += RANDOM_SIZE, but that also fails.
How can I store variable size char arrays in an array?
Use malloc and free (or new and delete in C++). You can do it with vectors too - as vectors can be treated as arrays.
char *str = "hello world";
// need the +1 for null character
arraySorage[0] = (char *)malloc (strlen(str) + 1);
strcpy(arraySorage[0], str);
...
free(arraySorage[0]);
with new/delete
arraySorage[0] = new char[strlen(str)+1];
strcpy(arraySorage[0], str);
...
delete arraySorage[0];
Using vector and std::string is the correct C++ way, for lots of reasons, including not leaking memory and proper handling of exceptions.