strcpy and strcat in Keil C compiler - c

I used this code to print some string,but it does not print any thing.What is the problem?
char* getNotFilledEncryptionParams(void)
{
char* nofilledStr;
char tmp[3];
const char * arr[]= {" P,"," Q,"," A,"," B,"," C,"," R,"," S0,","S1,","S2,","F1,","G1"};
for(i=0;i<11;i++)
{
if(filledParams[i] == 0)
{
strcpy(tmp,arr[i]);
strcat(nofilledStr,tmp);
}
}
return nofilledStr;
}
Usage:
int main(void){
char *remaining;
remaining = getNotFilledEncryptionParams();
printf("\r\n Remaining item:%s",remaining);
}
I think the problem is in const char * arr[] and I changed it,but the problem remains.

You didn't allocate any memory for noFilledStr, so its value is indeterminate and strcat(noFilledStr, tmp) is undefined.
Use malloc to allocate memory and initialize noFilledStr with the returned pointer:
char* noFilledStr = malloc(number_of_bytes);
The strings in arr are char[4], not char[3] (do not forget the null byte!). tmp is too small to hold them, so strcpy(tmp, arr[i]) writes out of bounds.

You are trying to build the string to return in the location pointed to by nofilledStr but this pointer is pointing somewhere as you do not initialize it. You could use a sufficiently large static char[] array if you do not have to deal with multiple threads. Otherwise, use malloc() and require the caller to free() the returned string when he is done with it.

Related

Returning a string (char array, char pointer etc.) from a function

I am writing a program for ESP8266 on Arduino SDK. My C knowledge is not enough to create professional project so I am training my self about C programming concepts now.
I deep dive to pointers and I tried write a function that return one float value and one string value. I used pointers to do that. For float, everything went well but I cannot return string value.
Here is the my code:
float val1;
char val2;
void returnMultiple(float *fGross, char *sGross)
{
*fGross = 50.0;
char v_str[10];
dtostrf(*fGross, 5, 2, v_str);
sprintf(v_str, "%s", v_str);
sGross = v_str;
}
What is the point that I missed? My char value null or esp8266 restarting?
An option is to directly copy into the sGross.
dtostrf(*fGross, 5, 2, sGross);
Then you have to be sure the function calling has allocated enough memory.
void main()
{
float val1;
char val2[10];
returnMultiple(&val1, val2);
}
The end result will then be
void returnMultiple(float *fGross, char *sGross)
{
*fGross = 50.0;
dtostrf(*fGross, 5, 2, sGross);
}
If you define an interface you do not only need to specify the function signature but also how to call it.
Typical questions are:
What type of memory is used for buffers
Who will allocate the memory
Who will free the memory
If you define that the caller has to provide the buffer, your code could look like this:
void returnMultiple(float *fGross, char *sGross)
{
if (fGross == NULL || sGross == NULL)
return;
*fGross = 50.0;
dtostrf(*fGross, 5, 2, sGross);
}
void callerfunc(void)
{
char buf[10];
float flt;
returnMultiple(&flt, buf);
printf("flt: %f; str: %s\n", flt, buf);
}
As no dynamic memory allocation is done, nothing needs to be freed.
You might define another return type to allow for error indications.
You assign to sGross pointer the value of local variable v_str... but that data will be destroyed as soon as the function returns (it is stored in the stack, so it will be overwritten).
What you need to do is to allocate the buffer externally. You can either
Use dynamic memory with something like char *str = malloc(10 * sizeof(char)); (remembering to free it as soon as it is no more needed).
Define externally an array of chars, like in the example below
float val1;
char val2;
void returnMultiple(float *fGross, char *sGross)
{
*fGross = 50.0;
char v_str[10];
dtostrf(*fGross, 5, 2, v_str);
/* CHANGES HERE! */
sprintf(sGross, "%s", v_str);
// No need to assign to sGross the pointer of a local variable
// sGross = v_str;
}
int main( void )
{
char testString[10];
float testFloat;
returnMultiple(&testFloat, testString);
printf("%s\n", testString);
return 0;
}
In this case I would suggest to pass not only the char pointer, but also the size of the buffer.
Another solution is allocating the char array within returnMultiple() function, returning the pointer to the char array. sGross parameter in this case would become a char ** variable.
But I suggest starting with easier solutions like the one showed in my example.
First: Your problem is with the way you return the string, not the float, so I'm reducing my example to just returning the string.
There are two ways you can implement this: Either the memory for your string is allocated by the function, or by the caller. The easy way is this:
void toString(char *str, int d) {
sprinf(str, "%d", d);
}
int main(void) {
char result[12];
toString(result, 50);
puts(result, stdout);
return 0;
}
In this case, result is a 12 byte string allocated on the stack of main. 12 bytes is big enough to store the string representation of an integer, so that's safe, if you're not sure what size the result can have, then watch out.
Second option:
void toString(char **str, int d) {
char *v_str = malloc(12);
sprintf(v_str, "%d", d);
*str = v_str;
}
int main(void) {
char *result;
toString(&result, 50);
puts(result, stdout);
free(result);
return 0;
}
In this case, we pretend that the caller doesn't know how much memory is required for the result string, and let the toString function decide. It allocates as much memory as it needs for the conversion, then returns the allocated string. The caller needs to release that memory with free. Note that we've got to pass the address &result in this situation, so toString will write the pointer to the allocated string into our result variable. Double pointers like this can seem confusing to some people who are new to C, but it's conceptually similar to how you're passing a pointer to your float variable (float *fGross).
Personally, I prefer the first version when possible, because allocating memory on the stack avoids having to manage heap memory with malloc and free, a common source of memory leaks, especially for beginners. Of course, nothing prevents you from calling that version of toString with heap-allocated memory if you need to.

Writing a string-concat: How to convert character array to pointer

I am learning C and I have written the following strcat function:
char * stringcat(const char* s1, const char* s2) {
int length_of_strings = strlen(s1) + strlen(s2);
char s3[length_of_strings + 1]; // add one for \0 at the end
int idx = 0;
for(int i=0; (s3[idx]=s1[i]) != 0; idx++, i++);
for(int i=0; (s3[idx]=s2[i]) != 0; idx++, i++);
s3[idx+1] = '\0';
// s3 is a character array;
// how to get a pointer to a character array?
char * s = s3;
return s;
}
That part that looks odd to me is where I have to "re-assign" the character array to a pointer, otherwise C complains that my return is a memory address. I also tried "casting" the return value to (char *) s3, but that didn't work either.
What is the most common way to do this "conversion"? Is this a common pattern in C programs?
There are many ways to handle this situation, but returning a pointer to stack-allocated memory inside the function isn't one of them (the behavior is undefined; consider this memory untouchable once the function returns).
One approach is to allocate heap memory using malloc inside the function, build the result string, then return the pointer to the newly allocated memory with the understanding that the caller is responsible for freeing the memory.
Here's an example of this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *stringcat(const char* s1, const char* s2) {
int i = 0;
int s1_len = strlen(s1);
int s2_len = strlen(s2);
char *result = malloc(s1_len + s2_len + 1);
result[s1_len+s2_len] = '\0';
for (int j = 0; j < s1_len; j++) {
result[i++] = s1[j];
}
for (int j = 0; j < s2_len; j++) {
result[i++] = s2[j];
}
return result;
}
int main(void) {
char *cat = stringcat("hello ", "world");
printf("%s\n", cat); // => hello world
free(cat);
return 0;
}
Another approach is for the caller to handle all of the memory management, which is similar to how strcat behaves:
/* Append SRC on the end of DEST. */
char *
STRCAT (char *dest, const char *src)
{
strcpy (dest + strlen (dest), src);
return dest;
}
man says:
The strcat() function appends the src string to the dest string, overwriting the terminating null byte ('\0') at the end of dest, and then adds a terminating null byte. The strings may not overlap, and the dest string must have enough space for the result. If dest is not large enough, program behavior is unpredictable; buffer overruns are a favorite avenue for attacking secure programs.
The problem isn't converting from array to pointer; that happens all the time implicitly, and it's no big deal. Your problem is you've just returned a pointer to invalid memory. The array you allocated in the function disappears when the function returns, and dereferencing a pointer to that array is undefined behavior (returning the pointer isn't technically illegal, but any good compiler warns you, because a pointer that is never dereferenced is usually pretty useless).
If you want to return a new array with the concatenated string, you must use dynamically allocated memory, e.g. from malloc/calloc; making the array static would also work (it would now be persistent global memory), but it would make your function both non-reentrant and non-threadsafe, so it's usually frowned on.
Your little trick of assigning to a pointer and returning the pointer may have fooled the compiler into thinking you weren't doing anything illegal, but it did nothing to make your code safer.
You might be used to languages with more dynamic memory handling, but your function here won't work because C strings are just a block of local memory which disappears when you return. That means that whatever you write to char s3[] will disappear after the return (the details vary and the memory can sometimes stick around long enough for you to think it worked even when it didn't).
Normally you'd want to allocate the memory before calling the function, and pass it in as a parameter, as in:
void stringcat(const char * first, const char * second, char * dest, const size_t dest_len)
Called like this:
char title[] = "Mr. ";
char last[] = "Jones";
char addressname[sizeof(title) + sizeof(last)];
stringcat(title, last, addressname, sizeof(addressname));
The other way to do it is to allocate the memory in the function using malloc(), and return that, but you have to remember to free it in the code when you're done with it.

How to dynamically allocate memory in an array of strings for some new string and copy that string into the dynamically allocated space in C?

Here is the code that I have:
void InsertStringAt(char *array[], char *s, int pos)
{
if (pos<array.size())
{
*array[pos]=(s *)malloc(sizeof(s));
strcopy(*array[pos], *s);
}
else printf("Position exceeds dimensions of array.");
}
The purpose of this function is to insert the string s into position pos of array[]. Will this code accomplish that?
No, this won't do it:
first you cast the result of malloc to (s *) but s is not a type (it is a variable). Then you allocate room the size of s but s is a pointer, so you allocate only room for a pointer.
Then array is declared as an array of pointers to characters. Now you don't need to dereference array anymore when you access a member. The compiler will do that and if you do that, then there is one dereferencing too many.
Do:
array[pos]= malloc(strlen(s)+1);
Lastly, in C there are no classes so array.size is invalid. You must pass the array size as a separate variable.
May I suggest you return an int to indicate everything was successful? E.g. no out-of-memory and pos < size?
sizeof a pointer simply gives you 8 or 4 (depending on your word size). So to get the length of a string, use strlen() from <string.h>. Also, you needn't cast the return value from malloc. So you'd get:
array[pos] = malloc(strlen(s)+1);
Notice that the dereferencing was removed, since it's already dereferenced.
Also, the function is strcpy() not strcopy(). strcpy() is declared in <string.h>. But strcpy() may lead to buffer overflows, consider making your own:
int safecpy(char *s, const char *t, size_t siz)
{
size_t i;
for (i = 1; (*s = *t) && i < siz; ++i, s++, t++)
;
s[i] = 0; /* null terminate the string */
return i;
}
C arrays do not know their own size; So pass it as a separate argument. It is recommended that sizes are represented with size_t and not int.
Finally, print error messages to stderr, so they don't get pipelined into another program or redirected into a file:
else fprintf(stderr, "Position exceeds dimensions of array.");

C - create a string "from" struct parameter

Have a
typedef struct person {
char name[20]
char surname[20]
} person_t;
I need to create a string like XXXXXX:YYYYYY with the function like
char* personToString(person_t *p). I tried to make it:
char* personToString(person_t* p) {
int n1,n2;
n1=strlen(p->name);
n2=strlen(p->surname);
char *p = (char*) malloc((n1+n2+2)*sizeof(char));
strcat(p,puser->name);
strcat(p,":");
strcat(p,puser->surname);
return p;
}
This give me a reasonable output but I have some errors testing with valgrind! I also think that there is a way more classy to write the function!
When you malloc memory for p the memory will hold garbage values. Strcat will append a string after the null character, but in an uninitialized string will hold random values.
Replace the first strcat with strcpy.
You need to
strcpy(p,puser->name);
not
strcat(p,puser->name);
malloc does not initialize the buffer to zero, so strcat is searching for a null byte in p first and probably not finding one, reading past the end of the buffer and thus crashing.
Instead of one strcpy plus two strcat you can also write one call to sprintf:
sprintf(p, "%s:%s", puser->name, puser->surname);
First you should call string copy, then strcat:
strcat(p,puser->name);
should be:
strcpy(p,puser->name);
because memory allocated with malloc function keeps values garbage, by doing strcat for first you are concatenating after garbage -- it also brings Undefined behaviour in your code.
You can use void* calloc (size_t num, size_t size); instead of malloc(), calloc function initialized allocated memory with 0 (then strcat() no problem).
Also dynamically allocated memory you should deallocate memory block using void free (void* ptr);) explicitly.
This looks good to me,
char* personToString( struct person_t *p )
{
int len = strlen(p->name) + strlen(p->surname) + 2; // holds ':' + NULL
char *str = malloc( len ); // Never cast malloc's return value in C
// Check str for NULL
if( str == NULL )
{
// we are out of memory
// handle errors
return NULL;
}
snprintf( str, len, "%s:%s", p->name, p->surname);
return str;
}
NOTE:
Never cast malloc's return value in C.
Use snprintf when multiple strcat is needed, its elegant.
free the return value str here in caller.
Fixed struct and char variables.

How do I return a variable size string from a function?

I need a working code for a function that will return a random string with a random length.
What I want to do would be better described by the following code.
char *getRandomString()
{
char word[random-length];
// ...instructions that will fill word with random characters.
return word;
}
void main()
{
char *string = getRandomString();
printf("Random string is: %s\n", string);
}
For this, I am strictly forbidden to use any other include than stdio.h.
Edit: This project will be adapted to be compiled for a PIC Microcontroller, hence I cannot use malloc() or such stuff.
The reason why I use stdio.h here, is for me to be able to inspect the output using GCC.
Currently, this code gives this error.-
“warning: function returns address of local variable [enabled by default]”
Then, I thought this could work.-
char *getRandomString(char *string)
{
char word[random-length];
// ...instructions that will fill word with random characters.
string = word;
return string;
}
void main()
{
char *string = getRandomString(string);
printf("Random string is: %s\n", string);
}
But it only prints a bunch of nonsense characters.
There are three common ways to do this.
Have the caller pass in a pointer to (the first element of) an array into which the data is to be stored, along with a length parameter. If the string to be returned is bigger than the passed-in length, it's an error; you need to decide how to deal with it. (You could truncate the result, or you could return a null pointer. Either way, the caller has to be able to deal with it.)
Return a pointer to a newly allocated object, making it the caller's responsibility to call free when done. Probably return a null pointer if malloc() fails (this is always a possibility, and you should always check for it). Since malloc and free are declared in <stdlib.h> this doesn't meet your (artificial) requirements.
Return a pointer to (the first element of) a static array. This avoids the error of returning a pointer to a locally allocated object, but it has its own drawbacks. It means that later calls will clobber the original result, and it imposes a fixed maximum size.
None if these is an ideal solution.
It points to nonsense characters because you are returning local address. char word[random-length]; is defined local to char *getRandomString(char *string)
Dynamically allocate the string with malloc, populate string, and return the returned address by malloc. This returned address is allocated from the heap and will be allocated until you do not manually free it (or the program does not terminate).
char *getRandomString(void)
{
char *word;
word = malloc (sizeof (random_length));
// ...instructions that will fill word with random characters.
return word;
}
After you have done with the allocated string, remember to free the string.
Or another thing can be done, if you cannot use malloc which is define the local string in the getRandomString as static which makes the statically declared array's lifetime as long as the program runs.
char *getRandomString(void)
{
static char word[LENGTH];
// ...instructions that will fill word with random characters.
return word;
}
Or simply make the char word[128]; global.
As I understand, malloc is not an option.
Write a couple of functions to a) get a random integer (strings length), and b)a random char.
Then use those to build your random string.
For example:
//pseudocode
static char random_string[MAX_STRING_LEN];
char *getRandomString()
{
unsigned int r = random_number();
for (i=0;i<r;i++){
random_string[i] = random_char();
}
random_string[r-1] = '\0';
}
If you are not allowed to use malloc you'll have to declare an array that can be the maximum possible size at file scope and fill it with random characters.
#define MAX_RANDOM_STRING_LENGTH 1024
char RandomStringArray[MAX_RANDOM_STRING_LENGTH];
char *getRandomString(size_t length)
{
if( length > ( MAX_RANDOM_STRING_LENGTH - 1 ) ) {
return NULL; //or handle this condition some other way
} else {
// fill 'length' bytes in RandomStringArray with random characters.
RandomStringArray[length] = '\0';
return &RandomStringArray[0];
}
}
int main()
{
char *string = getRandomString(100);
printf("Random string is: %s\n", string);
return 0;
}
Both of your examples are returning pointers to local variables - that's generally a no-no. You won't be able to create memory for your caller to use without malloc(), which isn't defined in stdio.h, so I guess your only option is to make word static or global, unless you can declare it in main() and pass the pointer to your random string function to be filled in. How are you generating random numbers with only the functions in stdio.h?

Resources