In my function I want to return an empty string "", function looks like this:
char *myFunction(nodeType *arg){
if (something){
return anotherFunction(arg);
} else {
return EMPTYSTRING;
}
}
(EMPTYSTRING should be replaced with correct expression to return "")
Some ways I came up with:
return ""
return '\0'
What is the right way to return an empty string?
It is not good idea to return "". Because, it is const char and you may try to dealloc it in where you get it from the function and this likely crashes your application.
So, I would return strdup(""), so you can free it safely.
return '\0' is not correct; it is a null character.
return "";
is more correct.
And you can make a small test function to test returning an empty string, before your data structure is implemented.
\0 is indeed a null-pointer constant, not an empty string, so returning that would still return a null pointer.
However you've got another problem here.
If anotherFunction returns a string that you don't need to free() then it is correct to return "" here. If it returns a dynamically malloc()ated string that you must free(), then you also need to return a dynamically allocated empty string here - return calloc(1, 1); would do the trick.
Related
I need to make a function that takes a string and a character, the function needs to remove all the occurrences of the character in the string and returns the total number of characters removed. I have managed to modify the string as to be able to remove the unwanted character but I can't seem to be able to replace the old string with the new one. Thanks for any replies in advance.
This is what I've managed so far:
int clearstr(char *st,char u){
int i,j=0,total=0,size=strlen(st);
char *new_str=calloc(size,sizeof(char));
for(i=0;i<size;i++){
if(st[i]!=u){
new_str[j]=st[i];
j++;}
else total++;
}
new_str[j]='\0';
printf("%s",new_str);
//until here all is good ,new_str has the modified array that i want but i can't find a way to replace the string in st with the new string in new_str and send it back to the calling function (main),thanks for any help //
return total;
}
You create a new string but you are not using it yet. You can use a function like memcpy or strcpy to copy the contents. You also don't deallocate the memory of the calloc call; this creates a memory leak. Try something like:
...
new_str[j]='\0';
printf("%s",new_str);
strcpy(st, new_str); // Copy the contents of the new string to the original one
free(new_str); // Clear the memory of the allocation in this function, otherwise you get a memory leak
return total;
...
What is the use of return value of strrev()? Even after reversing the string, the value will be modified in the given string.
Ex: char *strrev(char *src); Here after the string is reversed, the output will be present in the src. In that case what is the use of returning the string?
Either the return value or the string which we are passing also acts as output, that is enough. In that case what is the use of return value of strrev()?
To allow chaining.
Imagine you wanted to reverse a string, then reverse it back again (contrived example, but it makes the point). With chaining, you can do this:
strrev(strrev(charBuffer));
If sttrev returned void, you'd have to do:
strrev(charBuffer);
strrev(charBuffer);
to get the same result.
As #WernerHenze says in his comment, it also allows you to directly work with the output in function calls, like this:
printf("%s\n", strrev(charBuffer));
The possibility of chaining basically gives more flexibility to the programmer as to how the code is structured.
Chaining makes more sense, but it can also be used in an unlikely micro-optimisation. You can avoid saving a temporary value on the stack during the call. Eg.:
char *fn(char *s) {
strrev(s);
strlwr(s);
return strstr(s, "secret");
}
Over the calls to strrev() and strlwr() you need to keep a safe copy of s for subsequent use. You can eliminate this register save using:
char *fn(char *s) {
s = strrev(s);
s = strlwr(s);
return strstr(s, "secret");
}
As per the chaining answer, you could also use:
char *fn(char *s) {
return strstr(strlwr(strrev(s)), "secret");
}
But that can be a problem in more complex code.
I just tried it and it eliminated three mov instructions. Yay!!
Just trying to make a simple toString function but I'm having difficulty figuring out how I can create an sprintf style string without having to create a temporary variable.
i.e. It would be wonderful if the following worked
#myfile.c
bool status;
int state;
...
const char* myfileToString(void) {
return sprintf("myfile::status=%s;state=%d;", \
status ? "true" : "false", \
state);
}
this won't work since sprintf needs you to first create the string then pass it to the function.
i.e. I believe the following works
#myfile.c
bool status;
int state;
...
const char* myfileToString(void) {
char ret[40];
sprintf(ret, \
"myfile::status=%s;state=%d;", \
status ? "true" : "false", \
state);
return ret;
}
is there another function that I can use instead of sprintf or can I do something weird with sprintf like passing it some pointer to return directly sprintf(*return, "...", ...);
Okay...
Part 1:
Unless you're writing a macro, you don't need the backslash at the end of unfinished lines.
sprintf() requires a mutable buffer as it's first argument. You're not passing one, so you'll get all sorts of bad behavior here.
Part 2:
You're returning a pointer to a stack allocated object. That's going to cause undefined behavior.
What you should do:
Allocate the memory outside of this function. So:
void myfileToString(const char *str, size_t len) {
snprintf(str, len, "myfile::status=%s;state=%d;",
status ? "true" : "false",
state);
str[len - 1] = '\0';
}
You would call this by doing:
char box[40];
myfileToString(box, sizeof(box) /* 40 */);
Making this more reliable:
The family of sprintf() functions returns the number of characters written to a buffer. You could use this to send back an error (say a true or false return value) if the number of characters that was written was greater than the size of the buffer.
Finally, you could use the heap:
It's not the greatest practice, because it can mess with what people expect. But you could allocate memory on the heap for this data. You would need to remember to call free() on it in the future.
const char *myFileToString() {
char *str = malloc(40);
snprintf(str, 40, "myfile::status=%s;state=%d;",
status ? "true" : "false",
state);
str[40 - 1] = '\0';
}
In the first version you return what sprintf returns, which won't work as it doesn't actually return a string (please read the linked reference). In the second version of the function you return a pointer to a local variable, this leads to undefined behavior as the local variable goes out of scope when the function returns and the pointer no longer points to valid memory.
There are two primary solutions:
Allocate the string dynamically, e.g. using malloc, and return that pointer. Major drawback is that you must free the pointer you return.
Pass a character array as argument to the function, and use that as destination for the string.
Also, you should rather use snprintf than plain sprintf, because then you can control how much is written to the destination string, so you don't get a buffer overflow. On Windows using the Visual C++ compiler it's called _snprintf.
You don't want to use a local variable to build your sting in. Once you return, the variable will be lost and your return value will be undefined. Instead you can either allocate memory in your routine with malloc(), or you can pass a pointer to preallocated memory into your routine.
In either case you ought to use snprintf() instead of sprintf() to make sure you don't overflow your buffer.
You can't return a char[] in a function because it is allocated statically (on your stack) and destroyed at the end of your function. For you toString function, you have to use malloc in order to return a char* allocated dynamically (in your heap)
Your first method is totally wrong! You should not use like that!
Instead of sprintf you can use snprintf
snprintf(ret,sizeof(ret),"myfile::status=%s;state=%d;",status ? "true" : "false",state);
I use this (very nasty) trick:
struct strang
{
char s[100] ; /* this is arbitrary, but has to be enough ! */
} ;
and, by way of an example, to convert a struct sockaddr to a suitable string:
struct strang
sockaddr2strang(struct sockaddr* sa)
{
struct strang str ;
struct sockaddr_in* sin ;
....
switch (sa->sa_family)
{
AF_INET:
sin = (struct sock_addr_in*)sa ;
inet_ntop(AF_INET, &sin->sin_addr, str.s, sizeof(str)) ;
break ;
....
} ;
return str ;
} ;
The cunning part is that you can use the result in an expression or as the argument for another function, for example:
printf("....%s..%s..", ...., sockaddr2strang(&sa_local).s,
...., sockaddr2strang(&sa_peer).s) ;
Note that this is entirely pthread-safe, and does not require the caller to set up and pass in any auxiliary buffer(s) -- in particular (as shown here) if more than one string is required at the same time, the caller doesn't have to manage two (or more) buffers etc.
Obviously, this will not work for return strings of arbitrary size.
Thanks! Works perfectly now. Java has made me stupid :(
I am having some difficulty comparing strings in C. I get correct output when I don't use my isMorse function, but when I use it the output becomes inaccurate and displays random characters. As far as I can tell, the variable "morse" is actually changed when strcmp is called on it. I am thinking that it has to do with "morse" not being a constant, but I am unsure of how to remedy it.
Thanks!!
char *EnglishToMorse(char english)
{
static char *morse;
int i;
for (i = 0; i < LOOKUP_SIZE; i++)
{
if (lookup[i].character == english)
{
morse = lookup[i].morse;
return morse;
}
}
morse = &english; // Problem was here!!!
return morse;
}
I have a little guess. The function EnglishToMorse() might be returning a pointer to memory from the stack. If so, running another function after EnglishToMorse() will alter that memory. This would be due to a mistake in EnglishToMorse() -- declaring a local array of char and returning a pointer to it.
Without seeing the code for EnglishToMorse(), this is just a stab in the dark. You could provide us more code to look at, and win.
You have a static variable in EnglishToMorse, but it's the wrong one. There's no need for morse to be static -- you simply return it. But you do need english to be static -- rather than on the stack -- since you return its address. Also, it needs to be a NUL-terminated string. Do something like
char *EnglishToMorse(char english)
{
static char save_english[2]; /* initialized to 0's */
int i;
for (i = 0; i < LOOKUP_SIZE; i++)
if (lookup[i].character == english)
return lookup[i].morse;
save_english[0] = english;
return save_english;
}
Note, however, that the caller of EnglishToMorse must use the result or save it before EnglishToMorse is called again, since the second call may overwrite static_english.
The reason your morse variable appears to change is because it points to an area on the stack. The reason it points to an area on the stack is because you assigned it the address of your parameter english, which got pushed onto the stack when you called your function then popped off the stack once the function completed.
Now your morse variable will point to whatever memory takes that same location on the stack, which will constantly change throughout the lifetime of your program.
In my opinion, the best way to fix this problem would be to return a NULL pointer from EnglishToMorse if the character is not A-Z... then check for the NULL pointer in your isMorse function. After all, it's good practice to check for NULL pointers in code.
char* EnglishToMorse(char english)
{
int i;
english = toupper(english);
for (i = 0; i < LOOKUP_SIZE; i++)
{
if (lookup[i].character == english)
return lookup[i].morse;
}
return NULL;
}
int isMorse(char* morse)
{
int i;
/* Check for NULL, so strcmp doesn't fail. */
if (morse == NULL) return 0;
for (i = 0; i < LOOKUP_SIZE; i++)
{
if(strcmp(morse, lookup[i].morse) == 0)
return 1;
}
return 0;
}
It looks like the problem is likely in this function:
char *EnglishToMorse(char english) {
static char *morse;
// ...
morse = &english;
return morse;
}
You are returning the address of a parameter (english) that's passed into the function. This parameter ceases to exist after the function returns (and before the caller gets a chance to actually see the value). It appears as though you've attempted to fix this by declaring the morse variable static, but this only makes the morse variable itself static, not whatever it points to.
Also, strings in C must be terminated with a NUL character. By returning a pointer to a single character (as in english), there is no guarantee that the next byte in memory is or is not a NUL character. So the caller, who is expecting to see a NUL-terminated string, may get more than they bargained for.
char *EnglishToMorse(char english)
and
morse = &english;
are the problem.
You should never return a pointer to a local variable or a function parameter.
How do I return an array of strings from a recursive function?
For example::
char ** jumble( char *jumbStr)//reccurring function
{
char *finalJumble[100];
...code goes here...call jumble again..code goes here
return finalJumble;
}
Thanks in advance.
In C, you cannot return a string from a function. You can only return a pointer to a string. Therefore, you have to pass the string you want returned as a parameter to the function (DO NOT use global variables, or function local static variables) as follows:
char *func(char *string, size_t stringSize) {
/* Fill the string as wanted */
return string;
}
If you want to return an array of strings, this is even more complex, above all if the size of the array varies. The best IMHO could be to return all the strings in the same string, concatenating the strings in the string buffer, and an empty string as marker for the last string.
char *string = "foo\0bar\0foobar\0";
Your current implementation is not correct as it returns a pointer to variables that are defined in the local function scope.
(If you really do C++, then return an std::vector<std::string>.)
Your implementation is not correct since you are passing a pointer to a local variable that will go out of scope rather quickly and then you are left with a null pointer and eventually a crash.
If you still want to continue this approach, then pass by reference (&) an array of characters to that function and stop recursing once you have reached the desired end point. Once you are finished, you should have the 'jumbled' characters you need.
You don't :-)
Seriously, your code will create a copy of the finalJumble array on every iteration and you don't want that I believe. And as noted elsewhere finalJumble will go out of scope ... it will sometimes work but other times that memory will be reclaimed and the application will crash.
So you'd generate the jumble array outside the jumble method:
void jumble_client( char *jumbStr)
char *finalJumble[100];
jumble(finalJuble, jumbStr);
... use finalJumble ...
}
void jumble( char **jumble, char *jumbStr)
{
...code goes here...call jumble again..code goes here
}
And of course you'd use the stl datatypes instead of char arrays and you might want to examine whether it might be sensible to write a jumble class that has the finalJumble data as a member. But all that is a little further down the road. Nevertheless once you got the original problem solved try to find out how to do that to learn more.
I would pass a vector of strings as a parameter, by reference. You can always use the return value for error checking.
typedef std::vector<std::string> TJumbleVector;
int jumble(char* jumbStr, TJumbleVector& finalJumble) //recurring function
{
int err = 0; // error checking
...code goes here...call jumble again..code goes here
// finalJumble.push_back(aGivenString);
return err;
}
If you want to do it in C, you can keep track of the number of strings, do a malloc at the last recursive call, and fill the array after each recursive call. You should keep in mind that the caller should free the allocated memory. Another option is that the caller does a first call to see how much space he needs for the array, then does the malloc, and the call to jumble:
char** jumble(char* jumbStr)
{
return recursiveJumble(jumbStr, 0);
}
char** recursiveJumble(char* jumbStr, unsigned int numberOfElements)
{
char** ret = NULL;
if (/*baseCase*/)
{
ret = (char**) malloc(numberOfElements * sizeof(char*));
}
else
{
ret = jumble(/*restOfJumbStr*/, numberOfElements+1);
ret[numberOfElements] = /*aGivenString*/;
}
return ret;
}