Related
i ma new c and i am trying sprintf along with pointers. all i get in console is return buf; as is please help me with this code.
#include <stdio.h>
char* stringa(char* str);
int main()
{
char* ss = "123";
stringa(ss);
return 0;
}
char* stringa( char* str)
{
char buf [100] ;
sprintf(buf,"hello %s", str);
return buf;
}
i tried many other ways too like sprintf_c and my computer shut down for serious. i am learning c.
Maybe this is what you want
#include <stdio.h>
char* stringa(char* dest, char* src)
int main()
{
char buf [100] ;
char* ss = "123";
printf("%s\n", stringa(buf, ss));
return 0;
}
char* stringa(char* dest, char* src)
{
sprintf(dest,"hello %s", src);
return dest;
}
In function 'char* stringa(char* str)' you are not allocating space in the heep for the char array 'buf' you are allocating space on the stack for that variable. (meaning after the function finishes, the variable 'buf' will be wiped away because it will be out of scope) therefore you must ask the compiler to allocate space in memory for this array, I recommend using malloc()
ex:
char* stringa( char* str)
{
char *buf = (char*)malloc(sizeof(char) * 100);
sprintf(buf,"hello %s", str);
return buf;
}
char* stringa( char* str)
{
char buf [100] ;
sprintf(buf,"hello %s", str);
return buf;
}
The problem with this code is that the buf char array is local to the stringa function. When the function returns, the memory occupied by the buf array is not valid anymore (for example, it could be reused later to store the content of other variables, arrays, etc.).
So when the function returns, you are giving the caller a pointer to garbage memory, to invalid data. The C compiler is trying to help you with that warning message; it's telling you: "Sorry, you are trying to pass back to the caller the address of a local variable (i.e. the buf char array) that is not valid anymore when the function terminates."
To fix this problem one option could be to allocate the char array for the output string at the call site, and let the invoked stringa function write into the caller-provided array:
#include <stdio.h>
char* stringa(char* dest, const char* str);
int main()
{
const char* ss = "123";
char buf[100];
stringa(buf, ss);
return 0;
}
/* Write the final message into 'dest'.
* Return the same dest address.
*/
char* stringa(char* dest, const char* str)
{
/* Note: better using a safe string function
* to prevent buffer overflows (e.g. sprintf_s),
* passing the maximum destination array size as well.
*/
sprintf(dest,"hello %s", str);
return dest;
}
Note that I also added some consts in your code to enforce some const-correctness for read-only input strings.
I have the following code:
char* get_address_string(PACKAGE* pkg){
char *c;
sprintf(c, "%02x:%02x:%02x:%02x:%02x:%02x", pkg->address[0], pkg->address[1],
pkg->address[2], pkg->address[3], pkg->address[4], pkg->address[5]);
return c;
}
The code works fine. However, I know this is not the proper way to return a string in C. I am receiving the warning "c is used uninitialized in this function".
What is the proper way to write this function in C?
"Proper way to return a string in C" is not truly possible. In C, a string is a character array (up to and including the null character) and arrays, by themselves, cannot be returned from a function.
A function can return pointers. So the usual method of "return a string" it to:
Return a pointer. char *foo1(...) like char *strdup()
Pass in a pointer to a character array and modify its contents. void foo2(char *,...) like int sprintf(char *dest, const char *format, ...)
Combine 1 & 2 char *foo3(char *, ...) like char *strcpy(char *dest, char *src)
Pass the address of a pointer and update that. foo4(char **ptr) like ssize_t getline(char **lineptr, size_t *n, FILE *stream)
The key is that the memory associated with the pointer must be valid after the function is complete. Returning a pointer to a function's non-static memory is undefined behavior. Successful methods include having the calling code pass in the pointer, or the function providing it via memory allocation of pointer to some persistent value like a global variable or string constant.
What is the proper way to write this function in C?
Current design practice encourages functions like #2 & #3 above to also supply a size_t size so the function knowns the limitations of the memory available.
char *foo2(char *s, size_t size, const pkg_T *pkg) {
int result = snprintf(s, size, "%02x:%02x:%02x:%02x:%02x:%02x",
pkg->address[0], pkg->address[1], pkg->address[2],
pkg->address[3], pkg->address[4], pkg->address[5]);
// encoding error or not enough room
if (result < 0 || result >= size) return NULL;
return s;
}
Another method would allocate memory (I favor the above though). This obliges the calling code to free() the memory.
#define UINT_MAX_WIDTH (sizeof(unsigned)*CHAR_BIT/3 + 3)
char *foo2alloc(char *s, size_t size, const pkg_T *pkg) {
char buf[(UINT_MAX_WIDTH+3)*6 + 1];
int result = snprintf(buf, sizeof buf, "%02x:%02x:%02x:%02x:%02x:%02x",
pkg->address[0], pkg->address[1], pkg->address[2],
pkg->address[3], pkg->address[4], pkg->address[5]);
// encoding error or not enough room
if (result < 0 || result >= size) return NULL;
return strdup(buf);
}
c is a pointer, but no memory is allocated. The return value is ok, that's how it can be done in C.
But you need to allocate memory.
Since c is uninitialized, sprintf writes to an unknown memory location, which leads to unspecified behavior. It might crash immediately, it might not crash at all, or it might crash on some completely unrelated line of code.
You need to initialize the pointer by allocating memory to it with malloc.
char* get_address_string(PACKAGE* pkg){
char *c = malloc(20); // enough room for output as 00:11:22:33:44:55 plus null terminator
if (c == null) {
perror("malloc failed");
exit(1);
}
sprintf(c, "%02x:%02x:%02x:%02x:%02x:%02x", pkg->address[0], pkg->address[1], pkg->address[2], pkg->address[3], pkg->address[4], pkg->address[5]);
return c;
}
Note that even though you know ahead of time how much memory you need, you can't set it aside at compile time via an array. This is wrong:
char* get_address_string(PACKAGE* pkg){
char c[20]; // allocated on the stack, contents unspecified on return
sprintf(c, "%02x:%02x:%02x:%02x:%02x:%02x", pkg->address[0], pkg->address[1], pkg->address[2], pkg->address[3], pkg->address[4], pkg->address[5]);
return c;
}
As is this:
char* get_address_string(PACKAGE* pkg){
char c[20]; // allocated on the stack, contents unspecified on return
char *p = c;
sprintf(p, "%02x:%02x:%02x:%02x:%02x:%02x", pkg->address[0], pkg->address[1], pkg->address[2], pkg->address[3], pkg->address[4], pkg->address[5]);
return p;
}
Since c is allocated on the stack, when get_address_string returns the contents are unspecified, leading again to unspecified behavior.
I prefer allocating heap from the caller so that it's clear who should free it.
#include <stdio.h>
#include <malloc.h>
bool GetString(char ** retString, size_t size)
{
// use size to do range check
sprintf_s(*retString, size, "blah blah blah");
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
size_t size = 100;
char *data = (char *)malloc(size);
if (data)
{
GetString(&data, size);
free(data);
}
return 0;
}
I'm trying to program a function that allows me to locate a substring "from" in a string "src", and replace the "from" substring with the "to" substring in all cases, and output the new string through "dest"; however I think my code looks a bit iffy, and I do not understand (conceptually) how I would return an output with dest, given that the output is of type void. I was wondering if someone could offer some assistance?
for example:
find_replace("pooppoop poop", "poo", "hel", dest) should return
"helphelp help"
thank you!
void find_replace(char* src, char* from, char* to, char* dest)
{
dest = (char * ) malloc(sizeof(src)+sizeof(from));
int i;
int j;
int check = 1;
for (i = 0; i <= strlen(src) - 1; i++) {
if (src[i] == from[0]) {
for (j = 0; j <= strlen(from) - 1; i++) {
if (src[i+j] != from[j]) {
check = 0;}
else {
continue;
}}}
if (check == 1) {
char * str3 = (char *) malloc(1 + strlen(&src[i]) + strlen(to));
strcpy(str3, &src[i]);
strcat(str3, to);
}
else { continue; }
}
return ;
You allocate memory for a new string in your example, but the calling code cannot acces this variable.
Basically, there are three methods to pass a string. Each has advantages and drawbacks.
Pass a fixed-size buffer
int repl1(char *dest, int n, const char *src, const char *find, const char *repl)
Here, the calling function provides a buffer to which the function can write. It is a good idea to provide a maximum buffer length, so that the function does not overflow that buffer. The arguments, whose contents you don't intend to change should be const, i.e. pointers to unmodifiable data.
Such a function can be void, but it could also return an integer that indicates how long the string in dest is.
The advantage is that you can easily pass automatic buffers. The disadvantage ist that these buffers might be too small for the task.
Call the function like this:
char buf[80];
int n = repl1(buf, sizeof(buf), str, "this", "that");
Return allocated memory
char *repl2(const char *src, const char *find, const char *repl)
Here, the function should allocate new memory to hold the buffer. The function returns the pointer to the new memory. That memory "belongs" to the calling function, which then is responsible for freeing the memory.
The advantage is that the function can allocate enough memory for the task. The disadvantage is that the calling function must take care of managing the new memory.
Call the function like this:
char *dest = repl2(str, "this", "that");
// Do stuff whith 'dest' ...
free(dest);
Pass a pointer to a poiner to char
int repl3(char **dest, const char *src, const char *find, const char *repl)
This is a variant of returning the pointer, where the pointer is passed by reference and can therefore be changed. The function also has access to the old contents to the dest char buffer. That is not useful in your case. I have only mentioned this possibility for completeness.
Call the function like this:
char *buf;
int n = repl3(&buf, str, "this", "that");
This answer addresses the ways of passing data. Your code uses the second method, so you should return dest, but not pass it in as parameter. I have not looked at your function logic.
Void type method won't return anything, what you can do is change the type of your function to string and return a string.
Void means nothing, so you can't return a value with a void function.
I assume you want to use call-by-reference instead of call-by-value, if you want to use a void function.
This means, that you give a pointer to the function, to tell where your array is located. Then you work with your 'real' array, instead of a copy.
[Apart from analyzing the logic of your function] A function with a return type void won't [and can't] return any value using the return statement. Also, worthy to mention, you cannot return more than one value [as you need] using a return statement, either.
To get the return value(s) in your case, you're supposed to call your function and pass pointer(s) to char as argument. Then, inside your function, when you assign/alter values of the locations pointed by those pointers, they will get modified and after returning from your function, in the caller function, you'll have the modified value.
This is another way to have more than one return value at a time from a called function.
printf("%s\n",find_replace("pooppoop poop", "poo", "hel", dest));
char * find_replace(char* src, char* from, char* to, char* dest)
{
dest = (char * ) malloc(sizeof(src)+sizeof(from));
int i;
int j;
int check = 1;
for (i = 0; i <= strlen(src) - 1; i++) {
if (src[i] == from[0]) {
for (j = 0; j <= strlen(from) - 1; i++) {
if (src[i+j] != from[j]) {
check = 0;}
else {
continue;
}}}
if (check == 1) {
char * str3 = (char *) malloc(1 + strlen(&src[i]) + strlen(to));
strcpy(str3, &src[i]);
strcat(str3, to);
return str3 ;
}
else { continue; }
}
return "";
}
The line:
dest = (char * ) malloc(sizeof(src)+sizeof(from));
overrides the address passed in
void find_replace(char* src, char* from, char* to, char* dest)
If you want to allocate memory inside the function (which I think you have to, because the caller cannot know how much to reserve), you have to tell the caller where the result data ends up in. Either you opt for an out-parameter:
void find_replace(char* src, char* from, char* to, char** dest)
{
*dest = malloc(...);
or, what I would prefer, you return the pointer:
char* find_replace(char* src, char* from, char* to)
{
char* dest = malloc(...);
// ...
return dest;
}
char * myFunction () {
char sub_str[10][20];
return sub_str;
}
void main () {
char *str;
str = myFunction();
}
error:return from incompatible pointer type
thanks
A string array in C can be used either with char** or with char*[]. However, you cannot return values stored on the stack, as in your function. If you want to return the string array, you have to reserve it dynamically:
char** myFunction() {
char ** sub_str = malloc(10 * sizeof(char*));
for (int i =0 ; i < 10; ++i)
sub_str[i] = malloc(20 * sizeof(char));
/* Fill the sub_str strings */
return sub_str;
}
Then, main can get the string array like this:
char** str = myFunction();
printf("%s", str[0]); /* Prints the first string. */
EDIT: Since we allocated sub_str, we now return a memory address that can be accessed in the main
To programmers just starting out, the concept of a "stack" or the "heap" might be a little confusing, especially if you have started programming in a higher level language like Ruby, Java, Python, etc.
Consider:
char **get_me_some_strings() {
char *ary[] = {"ABC", "BCD", NULL};
return ary;
}
The compiler will rightfully issue a complaint about trying to return address of a local variable, and you will most certainly get a segmentation fault trying to use the returned pointer.
and:
char **get_me_some_strings() {
char *ary[] = {"ABC", "BCD", NULL};
char **strings = ary;
return strings;
}
will shut the compiler up, while still getting the same nasty segmentation fault.
To keep everyone but the zealots happy, you would do something a little more elaborate:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **get_me_some_strings() {
char *ary[] = { "ABC", "BCD", NULL };
char **strings = ary; // a pointer to a pointer, for easy iteration
char **to_be_returned = malloc(sizeof(char*) * 3);
int i = 0;
while(*strings) {
to_be_returned[i] = malloc( sizeof(char) * strlen( *strings ) );
strcpy( to_be_returned[i++], *strings);
strings++;
}
return to_be_returned;
}
now use it:
void i_need_me_some_strings() {
char **strings = get_me_some_strings();
while(*strings) {
printf("a fine string that says: %s", *strings);
strings++;
}
}
Just remember to free the allocated memory when you are done, cuz nobody will do it for you. That goes for all the pointers, not just the pointer to the pointers! (i think).
To make more sense of it all, you might also want to read this: What and where are the stack and heap?
Reason:
you need the return type to be char(*)[20]. But even in this case you don't want to return a pointer to a local object from the function.
Do:
Use malloc to allocate sub_str, and return char**.
The cause of your compiler error is simple, but not the answer to what you really want to do. You are declaring that the function returns a char *, while returning a char **.
Without knowing the details of what you're doing, I'm going to assume one of two things are true:
1) The purpose of the function is to create and return an array of strings.
2) The function performs some operation(s) on an array of strings.
If #1 is true, you need several malloc calls to make this work (It can really be done with only two, but for purposes of simplicity, I'll use several).
If you don't know how large the array is supposed to be, your function declaration should look like this:
char ** allocateStrings ( int numberOfStrings, int strLength );
The reason for this is because you're essentially returning a pointer to an array of pointers and you need to know how many strings and how long each string is.
char ** allocateStrings ( int numberOfStrings, int strLength )
{
int i;
//The first line is allocating an array of pointers to chars, not actually allocating any strings itself
char ** retVal = ( char ** ) malloc ( sizeof ( char * ) * numberOfStrings );
//For each string, we need to malloc strLength chars
for ( i = 0; i < numberOfStrings; i ++ )
{
//Allocate one extra char for the null pointer at the end
retVal [ i ] = ( char * ) malloc ( sizeof ( char ) * ( strLength + 1 ) );
}
return retVal;
}
As somebody else pointed out, it's best practice to have whatever does the allocating also do the deallocating. So a cleanup function is needed.
void cleanupStrings ( char ** strArray, int numberOfStrings )
{
int i;
for ( i = 0; i < numberOfStrings; i ++ )
{
//Should be checking to see if this is a null pointer.
free ( strArray [ i ] );
}
//Once the strings themselves are freed, free the actual array itself.
free ( strArray );
}
Now, keep in mind that once the cleanup function is called, you no longer have access to the array. Trying to still use it will most likely cause your application to crash.
If #2 is true, then you want to allocate the strings, process the strings, and clean them up. You should use the two functions above to allocate/deallocate your strings, then a third function to do whatever with them.
void processStrings ( char ** strArray, int numberOfStrings, int strLength );
As others have said, you cannot return a local char array to the caller, and have to use heap memory for this.
However, I would not advise using malloc() within the function.
Good practice is that, whoever allocates memory, also deallocates it (and handles the error condition if malloc() returns NULL).
Since your myFunction() does not have control over the memory it allocated once it returned, have the caller provide the memory in which to store the result, and pass a pointer to that memory.
That way, the caller of your function can de-allocate or re-use the memory (e.g. for subsequent calls to myFunction()) however he sees fit.
Be careful, though, to either agree on a fixed size for such calls (through a global constant), or to pass the maximum size as additional parameter, lest you end up overwriting buffer limits.
As others correctly said you should use dynamic memory allocation by malloc to store your array inside heap and return a pointer to its first element.
Also I find it useful to write a simple array of string implementation which has a minimal API for data manipulation.
Type and API:
typedef struct {
char **array_ptr;
int array_len;
int string_len;
} array_t;
array_t* array_string_new(int array_len, int string_len);
int array_string_set(array_t *array, int index, char *string);
char* array_string_get(array_t *array, int index);
int array_string_len(array_t *array);
Usage:
It creates an array with 4 dimensions that can store strings with 4 characters length. If the string length goes beyond the specified length, just its first 4 characters will be stored.
int main()
{
int i;
array_t *array = array_string_new(4, 4);
array_string_set(array, 0, "foo");
array_string_set(array, 1, "bar");
array_string_set(array, 2, "bat");
array_string_set(array, 3, ".... overflowed string");
for(i = 0; i < array_string_len(array); i++)
printf("index: %d - value: %s\n", i, array_string_get(array, i));
/* output:
index: 0 - value: foo
index: 1 - value: bar
index: 2 - value: bat
index: 3 - value: ...
*/
array_string_free(array);
return 0;
}
Implementation:
array_t*
array_string_new(int array_len, int string_len)
{
int i;
char **array_ptr = (char**) malloc(array_len * sizeof(char**));
for(i = 0; i < array_len; i++) {
array_ptr[i] = (char*) malloc(string_len * sizeof(char));
}
array_t *array = (array_t*) malloc(sizeof(array_t*));
array->array_ptr = array_ptr;
array->array_len = array_len;
array->string_len = string_len;
return array;
}
int
array_string_set(array_t *array, int index, char *string)
{
strncpy(array->array_ptr[index], string, array->string_len);
return 0;
}
char*
array_string_get(array_t *array, int index)
{
return array->array_ptr[index];
}
int
array_string_len(array_t *array)
{
return array->array_len;
}
int
array_string_free(array_t *array)
{
int i;
for(i = 0; i < array->array_len; i++) {
free(array->array_ptr[i]);
}
free(array->array_ptr);
return 0;
}
Notice that it is just a simple implementation with no error checking.
i use that function to split a string to string array
char ** split(char *str, char *delimiter)
{
char *temp=strtok(str,delimiter);
char *arr[]={temp};
int i=0;
while(true)
{
elm=strtok (NULL, delimiter);
if(!temp) break;
arr[++i]=temp;
}
return arr;
}
first of all You can not return a string variable which is stored in stack you need use malloc to allocate memory dynamicaly here is given datails with the example
Go https://nxtspace.blogspot.com/2018/09/return-array-of-string-and-taking-in-c.html
get a proper answer
char *f()
{
static char str[10][20];
// ......
return (char *)str;
}
int main()
{
char *str;
str = f();
printf( "%s\n", str );
return 0;
}
You can use static instead of malloc. It's your choice.
Bear with me. I have not coded in c in 8 years and am totally baffled why my string manipulation is not working. I am writing a program that loops forever. In the loop I initialize two char pointers each is passed to a function that add text to the char pointer (array). When the functions are done I print the char pointer and free the two char pointers. However the program dies after 7 iterations with the following error message
* glibc detected * ./test: double free or corruption (fasttop): 0x0804a168 ***
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include string.h
#include stdio.h
#include stdlib.h
#include errno.h
#include time.h
char *SEPERATOR = "|";
void getEvent (char* results);
void getTimeStamp(char* timeStamp, int timeStampSize);
void stringAppend(char* str1, char* str2);
int main (int argc, char *argv[])
{
int i = 0;
while(1)
{
i++;
printf("%i", i);
char* events= realloc(NULL, 1);
events[0] = '\0';
getEvent(events);
char* timestamp= realloc(NULL, 20);
timestamp[0] = '\0';
getTimeStamp(timestamp, 20);
printf("%s", events);
printf("timestamp: %s\n", timestamp);
free(events);
free(timestamp);
}
}
void getEvent (char* results)
{
stringAppend(results, "a111111111111");
stringAppend(results, "b2222222222222");
}
void getTimeStamp(char* timeStamp, int timeStampSize)
{
struct tm *ptr;
time_t lt;
lt = time(NULL);
ptr = localtime(<);
int r = strftime(timeStamp, timeStampSize, "%Y-%m-%d %H:%M:%S", ptr);
}
void stringAppend(char* str1, char* str2)
{
int arrayLength = strlen(str1) + strlen(str2) + strlen(SEPERATOR) + 1;
printf("--%i--",arrayLength);
str1 = realloc(str1, arrayLength);
if (str1 != NULL)
{
strcat(str1, SEPERATOR);
strcat(str1, str2);
}
else
{
printf("UNABLE TO ALLOCATE MEMORY\n");
}
}
You are reallocating str1 but not passing the value out of your function, so the potentially changed pointer is leaked, and the old value, which has been freed by realloc, is freed again by you. This causes the "double free" warning.
The problem is that while stringAppend reallocates the pointers, only stringAppend is aware of this fact. You need to modify stringAppend to take pointer-to-pointers (char **) so that the original pointers are updated.
This line in stringAppend:
str1 = realloc(str1, arrayLength);
changes the value of a local variable in stringAppend. This local variable named str1 now points to either the reallocated memory or NULL.
Meanwhile local variables in getEvent keep the values they had before, which now usually point to freed memory.
All the comments where very helpfull. Of course it makes total sense why the error was happening. I ended up solving it by making the following changes.
For both the getEvent and stringAppend I return the char pointer.
e.g.
char* stringAppend(char* str1, char* str2)
{
int arrayLength = strlen(str1) + strlen(str2) + strlen(SEPERATOR) + 1;
printf("--%i--",arrayLength);
str1 = realloc(str1, arrayLength);
if (str1 != NULL)
{
strcat(str1, SEPERATOR);
strcat(str1, str2);
}
else
{
printf("UNABLE TO ALLOCATE MEMORY\n");
}
return str1;
}
This isn't an answer to your question (and you don't need one, since the error has been pointed out), but I do have some other comments about your code:
char* events= realloc(NULL, 1);
events[0] = '\0';
You don't test that realloc successfully allocated memory.
char* timestamp= realloc(NULL, 20);
timestamp[0] = '\0';
Same problem here. In this case, you don't need realloc at all. Since this is a fixed-size buffer, you could use just:
char timestamp[20] = "";
And don't do this:
str1 = realloc(str1, arrayLength);
because if realloc fails, you'll orphan the memory that str1 was pointing to before. Instead:
char* temp = realloc(str1, arrayLength);
if (temp != NULL)
{
str1 = temp;
...
}
Note that since you're modifying stringAppend to return the new string, you should do similar checks in the calling functions.
Also, "separator" is spelled with two As, not with two Es.