How to use char * in C - c++

I have main function like this:
void main()
{
char *s;
inputString(s);
printf("%s",s);
}
and inputString function:
void inputString(char *&s)
{
//Some code line to input a string and set s point to this string
}
Is there have a function auto malloc memory enough store string which inputed (I need input string in inputString function).

Just 3 lines of code (put these inside int main() )are enough
std::string s;
std::cin >> s; //or getline() as desired
std::cout << s;

If you keep using this C style approach, then no, you will have to make assumptions and allocate enough memory yourself. The C++ approach is much more superior, use std::strings and don't do manual allocations:
#include <string>
#include <iostream>
void inputString(std::string& s)
{
//Don't bother for the memory management
}
int main()
{
std::string s;
inputString(s);
std::cout << s ;
}
Also do note that your code is not legal C++. void main() is illegal!!!
Edit: At the time of this answer the question was tagged C++. Later the question was retagged NOT by the OP, and I don't quite agree with it...

You're mixing C and C++ in your example.
In your case before you can use s it should be initialized. For example, like this:
void inputString(char *&s)
{
s = strdup(xxx); // or malloc, calloc, etc.
}
But really, then it's better to just use plain old C:
char* inputString(void)
{
char* s = strdup(xxx);
return s;
}

Assuming that you are doing this is C and not C++.
There are two approaches, either inputString must allocate the memory or the caller of inputString must allocate the memory.
if inputString allocates the memory your function will probably look something like:
char* inputString(void)
{
int len = strlen (MyInternalString) + 1;
char* s = malloc (len);
strncpy(s, MyInternalString, len);
return s;
} //similar to what Rustram illustrated
you should also include:
void freeString(char* str)
{
free(str);
}
as well. This makes it clear to the user that they are required to manage the memory of the returned string themselves.
Alternatively you can write inputString where the user is expected to provide the required memory. This will then look something like
int inputString(char* str, int maxLen) //
{
if (maxLen >= myInternalStringLength + 1)
{
strncpy(str, myInternalString, maxLen)
}
return myInternalStringLength + 1;
}
Here the user of my string can check the return code to see if the buffer that he allocated was big enough. If it was too small, then he can always realloc a bigger one
Your main now becomes:
int main()
{
char *s = NULL;
int len = inputString(s, 0);
s = alloca(len); //allocates the memory on the stack
len = inputstring(s, len);
printf("%s",s);
} //no need to free the memory because the memory alloca'ed gets
//freed at the end of the stack frame

int main()
{
std::string s;
inputString(s);
printf("%s",s.c_str());
}
and inputString function:
void inputString(std::string& s)
{
//Some code line to input a string and set s point to this string
std::cin >> s;
}

Related

How to convert my string into array of chars

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");
}

Deletion of Dynamically Allocated Memory

I have been given a task, where I need to create the string_copy function Note that the function body and prototypes have been given by the source and that needs to be maintained. The portions written by me are after the comment write your code here.
#include <iostream>
using namespace std;
int string_length(const char* string_c);
char* string_copy(const char* string_c);
int main()
{
const char* string_c = "This is a string and is a long one so that we can create memory leaks when it is copied and not deleted";
// write your code here
int length = string_length(string_c);
cout << "Copied String: " << string_copy(string_c) << endl;
return 0;
}
int string_length(const char* string) {
int length = 0;
for (const char* ptr = string; *ptr != '\0'; ++ptr) {
++length;
}
return length;
}
char* string_copy(const char* string) {
// we need to add 1 because of ’\0’
char* result = new char[string_length(string) + 1];
// write your code here (remember zero-termination !)
int i;
for (i = 0; string[i] != '\0'; ++i)
{
result[i] = string[i];
}
result[i] = '\0';
return result;
}
Now task tells me
that it is very important that any memory allocated with e=new TYPE is
released later with delete e (and a=new TYPE[size] with delete [] a)
else this will lead to an error.
It is not exactly clear if error means compile/runtime error or error as in my task did not meet the requirement error.
My question is, in this code how do I delete the intermediate dynamically created result array? If I delete result, won't it fail the purpose of the task? Then how am I to respect the quotation above or maybe simulate memory leak as given in the long string constant?
Thanks.
EDIT: Why the negative votes? Please at least explain the reason! I am not asking any solution or something, but mere suggestion if I am missing some point or not!
The caller of string_copy would be responsible for releasing the memory when it's done with it by calling delete[] on it.
This is, by the way, a terrible way to write C++ code. You should be using std::string or std::vector<char> or something like that.
Here's why:
int length = string_length(string_c);
char* copy = string_copy(string_c);
cout << "Copied String: " << copy << endl;
delete[] copy;
return 0;
Yuck.
In fact the ideal solution is to use std::string and not char *. There is no real need of using char * instead of std::string in your example.
With std::string:
You don't need to new anything
You don't need to delete anything
You can do everything with std::string, that you do with char *.

Passing pointer to char* array into function to manipulate values on Arduino

[PLEASE CHECK FINAL EDIT BELOW FOR UPDATE]
My C++ is a bit rusty (to say the least) and I'm having an issue trying to pass a char array into a function to manipulate the values. Example code below:
void myFunction(char* splitStrings,String stringToSetInLoop) {
char substringPtr[stringToSetInLoop.length()];
stringToSetInLoop.toCharArray(substringPtr, stringToSetInLoop.length());
for(int i = 0; i < 10; i++) {
splitStrings[i] = *substringPtr;
}
}
char *mySplitStrings[10];
myFunction(*mySplitStrings,String("Repeat Me"));
Serial.println(mySplitStrings[0]);
The code does not crash, but it outputs a blank line. I suspect that I need to initialize a 2 dimensional array outside the function to pass in so that memory space is allocated. I'm guessing that, although the substring pointer exists inside the function, the memory is destroyed, leaving the char* array mySplitStrings[0] pointing at nothing. Also, I think I need to pass in the reference to the array memory space, not as a pointer.
The ultimate goal here is to be able to pass a char array into a function, assign some values to it, then use those values back in the main code loop. If there's a better way to achieve this, then please let me know.
Thanks in advance. Please free me from my personal pointer/reference hell!
EDIT: Further note, this code is being run on an arduino, so the C++ is limited.
EDIT: When I try to pass in a reference to the char* pointer, I get this error, which I'm not sure how to change the function parameters to fix: error: cannot convert char* ()[10] to char for argument 1 to void myFunction(char*, String). Can anybody please take a stab at showing me a working example?
EDIT:
Thanks to the responses... I now have a working static library function that splits strings passed as a char* array. I know it's not pretty, but it does work. Thanks you to those who contributed. Code below:
void ExplodeString::explode(char* explodeResults[], String str, String delimiter) {
int delimiterPosition;
int explodeResultsCounter=0;
String subString;
do {
delimiterPosition = str.indexOf(delimiter);
if(delimiterPosition != -1) {
subString = str.substring(0,delimiterPosition);
char *subStringPtr[subString.length()+1];
subString.toCharArray(*subStringPtr, subString.length()+1);
explodeResults[explodeResultsCounter++] = strdup(*subStringPtr);
str = str.substring(delimiterPosition+1, str.length());
} else { // here after the last delimiter is found
if(str.length() > 0) {
subString = str;
char *subStringLastPtr[subString.length()+1];
subString.toCharArray(*subStringLastPtr, subString.length()+1);
explodeResults[explodeResultsCounter++] = strdup(*subStringLastPtr);
}
}
} while (delimiterPosition >=0);
}
Usage:
char* explodeResults[10];
ExplodeString::explode(explodeResults, String("cat:dog:chicken"), String(":"));
Serial.println(explodeResults[0]);
Serial.println(explodeResults[1]);
Serial.println(explodeResults[2]);
EDIT: Man, this is sooo much easier when you use the stdlib:
void ExplodeString::explode(std::vector<std::string> &explodeResults, std::string str, char delimiter) {
std::stringstream data(str);
std::string line;
while(std::getline(data,line,delimiter))
{
explodeResults.push_back(line);
}
}
Usage:
std::vector<std::string> commandsResult;
char delimiter[] = ",";
std::string _inputString = "my,string,to,parse";
ExplodeString::explode(commandsResult, _inputString, delimiter[0]);
How to pass an array of char*:
void myFunction(char* splitStrings[10], String stringToSetInLoop) {
// ...
char *mySplitStrings[10];
myFunction(mySplitStrings, String("Repeat Me"));
This will also work:
void myFunction(char* splitStrings[], String stringToSetInLoop) {
and this:
void myFunction(char** splitStrings, String stringToSetInLoop) {
Also, seems there is STL for avr platform - include it, C++ without STL is smth strange.
You are not allocating space for character arrays and just passing pointer of character array.
Instead of using char*splitStrings[10], you can use 2d char array with sufficient space to accomodate max length string. Assuming you max string length is less that 64 you can do something like this.
char splitString[10][64];
void myFunction(char**splitStrings,String stringToSetInLoop)
or
void myFunction(char splitString[][64], String stringToSetInLoop)
{
int len = stringToSetInLoop.length();
for(int i = 0; i<10; i++)
{
for(int j = 0; i<len; j++)
{
splitString[i][j] = stringToSetInLoop.charAt(j);
}
}
}

C++ char* problems [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
#include<iostream>
using namespace std;
int main()
{
char *name="Siva",*str;
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
cout<<str;
return 0;
}
The first program gives output Sivaœ> i.e siva with some garbage values....
But the second program show segmentation fault...Please help me to find out
exact answer...
#include<iostream>
using namespace std;
int main()
{
int i=0;
char *name="Siva",*str;
for(i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
cout<<str;
return 0;
}
char *name="Siva",*str;
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str is a pointer, but it doesn't yet point to anything.
Since you're in C++, you should be using std::string:
#include<iostream>
#include <string>
using namespace std;
int main()
{
char *name="Siva";
std::string str;
for(int i=0;i<strlen(name);i++)
{
str += name[i];
}
cout<<str;
return 0;
}
Even better, get rid of the hand-written loop:
#include <algorithm>
int main()
{
char *name="Siva";
std::string str;
std::copy (name, name + strlen (name), std::back_inserter (str));
cout<<str;
return 0;
}
Better even still, there's no reason in this particular example why you need to do any of that at all:
char* name = "Silva";
std::string str = name;
cout << str;
By the way, string literals in C++ are inherently const:
const char* name = "Silva";
If you really must use a char*, first I would strongly question why, and then I would tell you to do this:
int main()
{
const char *name="Siva";
char* str = new char [strlen (name)+1]; // +1 for the null terminator
strcpy (name, str);
cout << str;
delete [] str;
return 0;
}
I would even more strongly question your need to copy it byte-by-byte:
int main()
{
const char *name="Siva";
char* str = new char [strlen (name)+1]; // +1 for the null terminator
for (size_t i = 0; i < strlen (name); ++i )
str [i] = name [i];
str [strlen (name)] = '\0';
cout << str;
delete [] str;
return 0;
}
You have undefined behaviour here:
str[i]=name[i];
str has not been initialized to anything. You are writing to places you shouldn't.
There are two problems with this.
The pointer str doesn't point to allocated memory, so writing through it is undefined behavior.
Even if it did point to valid memory, you're not writing the correct amount of data. When copying a string, you need to copy the 0 byte at the end which marks the end of the string; so the upper limit of your loop should bt strlen(name) + 1. Or you could use a library method like strdup() instead of your own for loop.
The reason the "working" version prints some garbage characters is that there's no 0 at the end of the copied string to tell iostreams to stop printing. The reason the "working" one doesn't crash, and the other one does, is pure dumb luck: the garbage in str, by chance, points to memory you're allowed to write to, while in the crashing program, it points to memory you're not allowed to write to. Simple as that.
It is because you have no memory allocated for str. (it will cause an undefined behavior)
You can mix that by using a merory allocation function like in this example :
#include<iostream>
using namespace std;
int main()
{
char *name="Siva",*str;
// Allocate memory with malloc
str = (char*)malloc( (strlen(name)+1) * sizeof(char) );
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str[strlen(name)] = 0;
cout<<str;
// Free the allocated memory
free(str);
return 0;
}
As you are using c++, you can do :
#include<iostream>
using namespace std;
int main()
{
char *name="Siva",*str;
// Allocate memory with new
str = new char[strlen(name) + 1];
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str[strlen(name)] = 0;
cout<<str;
// Free the allocated memory
delete []str;
return 0;
}
EDIT :
The reason you have some weird caracters at the end of your ouput is that because you string is not terminated with a '\0', it will continue to print it. (This will occur only if you don't have a segmentation fault )
There are a couple problems with your code.
Firstly, *str is not allocated, so it starts off by pointing to whatever bit of memory the pointer value happens to start off as.
Secondly, strlen() returns the length of the string excluding the terminating null character. So what you are doing is copying all the values of name into some random bit of memory, not terminating it, then telling the system to print that off, which could be any length.
str[i]=name[i]; is illegal, causes Undefined behavior, because you have not allocated memory for str.
Before for loop allocate memory for destination string str:
str = malloc (strlen(name) + 1 );
Also you forgetting string termination, after for-loop add terminate string str[i] = '\0';
Undefined behavior refers to computer code whose behavior is unpredictable.
You code should be:
char *name="Siva", *str;
str = malloc (strlen(name) + 1 ); // mistake
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str[i] = '\0'; // forgetting
To understand further you can read this answer: strcat() implementation works but causes a core dump at the end
Your problem is using char arrays and pointers to represent strings in language which has proper string type.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name = "Siva", str;
str = name;
cout << str;
return 0;
}
Problem is with str[i]=name[i] you must know that C++ does not care for memory leaks
as Java or some others. So you must allocate memory to a variable or pointer in order to avoid these problems. Already there are number of answers, you can also try
str=new char[strlen(name)+1];
and do not forget to terminate the char array with null when you done copy. In this case
str[strlen(name)]='\0';

Initialize const char * with out any memory leaks

Below is my sample code. Its just a sample which is similar to the code which i'm using in my applicaiton.
#define STR_SIZE 32
void someThirdPartyFunc(const char* someStr);
void getString(int Num, const char* myStr)
{
char tempStr[] = "MyTempString=";
int size = strlen(tempStr) + 2;
snprintf((char*)myStr, size, "%s%d", tempStr, Num);
}
int main()
{
const char * myStr = new char(STR_SIZE);
getString(1, myStr); // get the formated string by sending the number
someThirdPartyFunc(myStr); // send the string to the thirdpartyFunction
delete myStr;
return 0;
}
I am getting an exception if i use this code. I think the problem is with deleting the "myStr". But delete is really necessary.
Is there any other way to format the string in getString and send it to the ThirdPartyFunc??
Thanks in advance.
you are allocating not an array of chars but one char with this line:
const char * myStr = new char(STR_SIZE);
and that one allocated char is initialized with the value of STR_SIZE, causing a "char overflow" in this case.
if you want an array of size STR_SIZE:
const char * myStr = new char[STR_SIZE];
(note the rectangular [ ]). you have to deallocate such allocated chunk of memory by using the delete[] operator.
personal note: the code you have written above (manually allocated strings etc) is good educational wise; you will do a lot of such mistakes and thus learn about the inner workings of C / C++. for production code you do not want that, for production code you want std::string or other string-containers to avoid repeating string-related mistakes. in general you are not the one who sucessfully reinvent how string-libraries will work. the same is true for other container-types like dynamically-growable-arrays (std::vector) or dictionary-types or whatever. but for educational fiddling around your code above serves a good purpose.
there are other problems in your code snippet (handing over const char* to a function and then modifying the ram, not calculating correctly the size parameter when calling snprintf etc), but these are not related to your segfault-problem.
Re the technical, instead of
const char * myStr = new char(STR_SIZE);
do
char const myStr[STR_SIZE] = "";
Note that both have the problem that the string can’t be modified.
But you only asked about the allocation/deallocation problem.
But then, there's so much wrong at levels above the language-technical.
Here's the original code, complete:
void someThirdPartyFunc(const char* someStr);
void getString(int Num, const char* myStr)
{
char tempStr[] = "MyTempString=";
int size = strlen(tempStr) + 2;
snprintf((char*)myStr, size, "%s%d", tempStr, Num);
}
int main()
{
const char * myStr = new char(STR_SIZE);
getString(1, myStr); // get the formated string by sending the number
someThirdPartyFunc(myStr); // send the string to the thirdpartyFunction
delete myStr;
return 0;
}
Here's how to do that at the C++ level:
#include <string> // std::string
#include <sstream> // std::ostringstream
using namespace std;
void someThirdPartyFunc( char const* ) {}
string getString( int const num )
{
ostringstream stream;
stream << "MyTempString=" << num;
return stream.str();
}
int main()
{
someThirdPartyFunc( getString( 1 ).c_str() );
}
The #define disappeared out of the more natural code, but note that it can very easily lead to undesired text substitutions, even with all uppercase macro names. And shouting all uppercase is an eyesore anyway (which is why it's the macro name convention, as opposed to some other convention). In C++ simply use const instead.