I have a struct containing a char pointer and I have a char array containing data. I would like to have the data within the char array copied to the char pointer.
I have tried strcpy and strncpy but I get a seg fault on both, when trying to copy the data over. I cant figure out what I am doing wrong.
struct
struct Message
{
Header hdr;
char *dataArr;
Footer ftr;
};
main
int main(){
// create message struct
Message send1;
// create stream
std::ostringstream outStream;
//
// STREAM GETS DATA HERE
//
std::string temp = outStream.str();
char arr[temp.size()];
strcpy(arr, temp.c_str());
int sz = sizeof(arr)/sizeof(char);
// print arr size and contents
std::cout << "arr size: " << sz << "\n";
for(int i=0; i<sz; i++){
std::cout << arr[i];
}
// copy char array into structs char pointer
//strncpy(send1.dataArr, arr, sz);
strcpy(send1.dataArr, arr); <-- Segmentation fault here
return 0;
}
You first need to allocate memory to copy your data.
Or use strdup that will do it for you
Related
Here is a problem. When I try to convert it by using strncpy_s, array has some type of "trash data" from memory in the end of it. Even when I fill buffer with "\0". How to convert it clear?
typedef class Ryadok {
private:
int LengthOf = 0;
char text[20];
string* address;
public:
Ryadok(string strin) {
this->text[0] = '\0';
memset(text, '\0', sizeof(text));
strncpy_s(text, strin.c_str(), sizeof(text) - 1);
this->address = &strin;
for (int i = 0; i < sizeof(strin); i++) {
cout << this->text[i];
}
}
~Ryadok() {
}
}*cPtr;
int main()
{
Ryadok example("sdsdfsdf");
}
The idea to use c_str() function to convert the std::string to a a-string. Then we can simply call strcpy() function to copu the c-string into char array
std::string s = "Hello World!";
char cstr[s.size() + 1];
strcpy(cstr, s.c_str()); // or pass &s[0]
std::cout << cstr << '\n';
return 0;
When using the strncpy_s function you tell it to copy as many chars as will fit into your buffer "text". Since the string you create the "example" instance with is shorter, the copy function will keep going after the end of the actual string.
That is where your garbage comes from. Even worse you risk a Segmentation Fault this way. Your code might access parts of the RAM it is not allowed to read from. That will cause it to crash.
You are right though to copy the data pointed to by the return of c_str(). The pointer returned by c_str() points to data that belongs to the std::string object and might be changed or even invalidated by that object. (Read more here)
Here's a modified version of your code that should avoid the garbage:
typedef class Ryadok {
private:
int LengthOf = 0;
char text[20];
string* address;
public:
Ryadok(string strin) {
this->text[0] = '\0';
memset(text, '\0', sizeof(text));
if(strin.length()+1 <= sizeof(text)) {
strncpy_s(text, strin.c_str(), strin.length()+1);
} else {
//some error handling needed since our buffer is too small
}
this->address = &strin;
for (int i = 0; i < sizeof(strin); i++) {
cout << this->text[i];
}
}
~Ryadok() {
}
}*cPtr;
int main()
{
Ryadok example("sdsdfsdf");
}
Here is a simple program where I am trying to pass a structure to a function by reference and a string. The function is supposed to detect the length of the string and assign it a member of the structure. Here is the program:
#include <iostream>
#include <string.h>
struct stringy // structure definition
{
char *str;
int ct;
};
void set(stringy &beany, const char *testing); // function definition
int main()
{
stringy beany;
char testing[] = "Reality isn't what it used to be.";
set(beany, testing); // function call
return 0;
}
void set(stringy &beany, const char *testing) // function prototype
{
int i=0;
while (*(testing+i) != '\0') // this loop counts the number of characters
{
i++;
std::cout << i << "\n";
}
beany.str = new char[i]; // dynamic storage allocation
std::cout << strlen(beany.str); // printing the length of the string
}
For some reason the output of the last line in the function set() is 47 while the value of "i" is 33. The last 15 bytes are filled with garbage value. I want that the length of beany.str should be equal to the length of *testing.
You allocate memory for beany.str but you don't initialize that memory. The contents of the allocated memory, without any initialization, is indeterminate (and in practice will be seemingly random).
Also don't forget that old C-style strings needs to be terminated by the special '\0' character (or functions like strlen will not work).
Both of these problems, using uninitialized memory and forgetting the terminator, will lead to undefined behavior.
beany.str = new char[i]; // dynamic storage allocation
std::cout << strlen(beany.str); // printing the length of the string
strlen looks for the terminating null character '\0'. There is no guaranteed one in beany.str, because you assign it the result of new char[i], which does not zero-initialize the elements. It allocates space for i characters that are not initialized to zero.
Even if they were, strlen would return 0, because it would immediately find '\0' at the first position. If you don't somehow remember i yourself, the size information will be lost.
Look at the output of the following program:
#include <iostream>
int main()
{
char *str = new char[100];
for (int i = 0; i < 100; ++i)
{
std::cout << str[i] << "\n";
}
}
The behaviour is undefined. What you will probably see are some seemingly random characters.
If you want zero-initialization, use new char[i]().
But still, strlen will be 0:
#include <iostream>
#include <string.h>
int main()
{
char *str = new char[100]();
for (int i = 0; i < 100; ++i)
{
std::cout << str[i] << "\n";
}
std::cout << strlen(str) << "\n";
}
You should just get rid of array-new and array-delete. Use std::string.
#include <stdio.h>
#include <string.h>
int main()
{
std::string data;
data = "hello world";
char string1[] = data;
}
If I must use char string1[] and not char *string1, is there a way I can copy content of string data into this char string1[]?
file.cpp: In function ‘int main()’:
file.cpp:13:22: error: initializer fails to determine size of ‘string1’
You can call method c_str on std::string object and copy result to your array.
Since the size of data may be variable, it cannot be copied via initialization of a static array.
One way you can do it is with dynamic allocation (which C++ string handles automatically):
char *string1 = strdup(data.c_str());
// do stuff with string1
free(string1);
If you are familiar with loops, then the easiest way is to copy the contents of string to char array one by one. As you are not going to use char pointer so you have to fix the size of char array, say 20.
int main()
{
string data;
data = "hello world";
int size = data.size(); // size of data
char string1[20]; //you can change the size of char array but it must be greater than size of data string
for (int i = 0; i < size; i++) {
string1[i] = data[i];
}
return 0;
}
Using stack memory (only if you are sure that the data.size() is less than 1000.):
char result[1000];
strcpy(result, data.c_str());
Or using heap memory:
char* result = new char[data.size() + 1];
strcpy(result, data.c_str());
// ...
delete[] result;
I'm trying to return an array of char arrays. While I am able to create the array succesfully, I am apparently returning it incorrectly.
Is my syntax off or am I committing some other error that I am overlooking?
Here are the most relevant lines, the full functions follow
// prototype
char * testFunc();
// Function
char * testFunc() {
char* ptrArray[2];
return(*ptrArray);
}
// Assignment in main()
int main {
char * res = testFunc();
}
Here is a simplified version of the full code
#include <iostream>
using std::cout;
// prototype
char * testFunc();
int main() {
short i, j;
char * res = testFunc();
for (i=0; i < 2; i++)
cout <<"This is res[" << i << "] : " << res[i] <<"\n";
return(0);
}
char * testFunc() {
char word1[] = "one";
char word2[] = "two";
// create an array of char*
char* ptrArray[2];
ptrArray[0] = word1;
ptrArray[1] = word2;
for (int i=0; i<2; i++)
cout <<"This is ptrArray[" << i << "] : " << ptrArray[i] <<"\n";
return(*ptrArray);
}
Returning objects allocated in the automatic storage (also known as "stack objects") from a function is undefined behavior. When you need to return an array in C, you have three options:
Return an object allocated in the static storage area,
Return an object allocated in the dynamic storage area, or
Take a buffer and max size, and return the actual size of the array.
The first option is rarely applicable, because it makes your function non-reentrant. The third option is widespread, but it has limitations: when you must return more data than fits into the buffer, the API needs to be called multiple times.
This leaves us with option number two: use new to allocate the memory that you are returning, copy the data into it, and return the result to the caller. It is now caller's responsibility to free the dynamic memory:
// You need two asterisks: a string needs one asterisk, you return
// a 1-D array of strings, so you need another level of indirection.
char ** testFunc() {
char word1[] = "one"; // Automatic memory - needs a copy
char word2[] = "two"; // Automatic memory - needs a copy
// create an array of char*
char** ptrArray = new char*[2];
ptrArray[0] = new char[strlen(word1)+1]; // Plus one for the null terminator
strcpy(ptrArray[0], word1);
ptrArray[1] = new char[strlen(word2)+1]; // Plus one for the null terminator
strcpy(ptrArray[1], word2);
for (int i=0; i<2; i++)
cout <<"This is ptrArray[" << i << "] : " << ptrArray[i] <<"\n";
return ptrArray;
}
Note: you may not have reached the standard library yet, so the solution below may not apply. However, you should know that the above solution is not the best C++ can do: you can rewrite this wit dynamic containers, and make the code much easier to read:
vector<strig> testFunc() {
vector<string> res;
res.push_back("one");
res.push_back("two");
return res;
}
In C++11 you can do even better:
vector<string> test() {
return vector<string> {"one", "two"};
}
A single "character array" is roughly equivalent to char *. To return an array of arrays, you need char ** or perhaps char[]*.
As the other answer says, if you're returning pointers from inside a function these need to be "global" memory -- not local variables which are only ever valid within the function. Returned pointers to "stack-based" local variables are no longer valid after the function returns, since that stack-space will be overwritten by the next function-call (or sooner).
[Since the original posting, it has been suggested that const char* and (presumably) const char** would be preferred, for "const correctness"].
My C++ is rusty.. but:
const char** testFunc() {
const char word1[] = "one";
const char word2[] = "two";
// create an array of char*
const char** ptrArray = (const char **) malloc( 2 * sizeof(char *));
ptrArray[0] = word1;
ptrArray[1] = word2;
for (int i=0; i<2; i++)
cout <<"This is ptrArray[" << i << "] : " << ptrArray[i] <<"\n";
return ptrArray;
}
And in main:
int main() {
short i;
// get the array -- will now be our responsibility to free
const char** ptrArray = testFunc();
for (i=0; i < 2; i++) {
// read single pointer (char*), from our array of pointers (char**)
const char* word = ptrArray[i];
cout <<"This is res[" << i << "] : " << word <<"\n";
}
// free it.
free( ptrArray);
return(0);
}
As the original question is posed, the inputs for the array are string constants. Returning a mutable array of constant strings is thus preferred, to returning a mutable array of mutable strings.
Even if the full system (not shown in the question) built up the strings programmatically, as per other the answer, it is more than likely they would best be returned as const char * -- not treated as buffers for further modification.
I have a problem with simple reading from the file that shares file pointer between a few objects (It works for me with just simple istream, but not when I am using shared pointer of istream pointers).
I am trying to read the whole file to the buffer (file itself is a few lines long.
The code compiles, but throws segmentation fault.
The class that uses shared_ptr:
RecordsSplitter::RecordsSplitter(char *filename):iStream( new ifstream(filename, ifstream::in|ifstream::binary))
{
}
string RecordsSplitter::buildRecord() {
char *buffer;
int buffer_length;
iStream->seekg (0, ios::end)_
buffer_length = iStream->tellg();
cout << buffer_length;
iStream->seekg(0, ios::beg);
iStream->read(buffer,buffer_length);
iStream->close();
cout << buffer;
return 0;
}
int main(int argc, char* argv[]) {
RecordsSplitter *splitter;
splitter = new RecordsSplitter(argv[2]);
int return_num = splitter->buildRecord();
return 0;
}
You declare your buffer but you don't initialise it anywhere.
You need this in your buildRecord function or a use of malloc if you so desire.
buffer = new char[buffer_length];
Your seg fault is caused by this uninitialised pointer
Don't forget to clean up!
delete[] buffer;