C return value using argument to function - c

I'm trying to run function which will return two strings by passing a pointer to them:
#include <stdio.h>
void gen_str(char *str1, char *str2){
char *s1 = "abcd";
char *s2 = "defg";
str1= strdup(s1);
str2= strdup(s2);
printf("\n\r str1 %s str2 %s\n\r", str1, str2);
}
int main(void){
char *s1, *s2;
gen_str(s1, s2);
printf("\n\r s1 %s s2 %s\n\r", s1, s2);
return 0;
}
where output is:
str1 abcd str2 defg
s1 8, s2 8,
Can someone tell me, what I'm doing wrong? I thought that strdup() will alloc memory for my new strings, and return pointers filled with strings. But actual behavior is different. So I'm asking for help.

You need your function to modify the pointers s1 and s2, so you need to pass their addresses, so that the function can modify the originals, not a copy.
void gen_str(char **str1, char **str2){
char *s1 = "abcd";
char *s2 = "defg";
*str1= strdup(s1);
*str2= strdup(s2);
printf("\n\r str1 %s str2 %s\n\r", *str1, *str2);
}
int main(void){
char *s1, *s2;
gen_str(&s1, &s2);
printf("\n\r s1 %s s2 %s\n\r", s1, s2);
return 0;
}
Note also that you need to free these strings at some point, otherwise you have a memory leak.

You got your pointers confused. The basic type for a C string is already char*, and now you want a pointer to that, i.e. a char**:
void fill_me(char ** ps)
{
const char * t = "hello";
*ps = strdup(t);
}
/* elsewhere */
char * s;
fill_me(&s);
Moral: If you want a function to modify an argument passed by the caller, the caller needs to take the address-of (&) something at some point.

You're only changing the pointer inside the function. To change it outside the function, you'll need to pass the function the address of the two strings, like this:
#include <stdio.h>
void gen_str(char **str1, char **str2){
char *s1 = "abcd";
char *s2 = "defg";
*str1= strdup(s1);
*str2= strdup(s2);
printf("\n\r str1 %s str2 %s\n\r", *str1, *str2);
}
int main(void){
char *s1, *s2;
gen_str(&s1, &s2);
printf("\n\r s1 %s s2 %s\n\r", s1, s2);
return 0;
}

You can's use the value of a variable before you've initialized it!
char *s1, *s2;
gen_str(s1, s2);
The first line doesn't assign any particular values to s1 and s2. But then you pass them to gen_str. To have another function fill in the value of a variable, pass a pointer to that variable to the function, not its value.
#include <stdio.h>
#include <string.h>
void gen_str(char **str1, char **str2){
const char *s1 = "abcd";
const char *s2 = "defg";
*str1 = strdup(s1);
*str2 = strdup(s2);
printf("\n str1 %s str2 %s\n", *str1, *str2);
}
int main(void){
char *s1, *s2;
gen_str(&s1, &s2);
printf("\n s1 %s s2 %s\n", s1, s2);
free(s1);
free(s2);
return 0;
}

Related

Use of strcpy() in pointers to string in C

I'm trying to use strcpy() with pointers to strings and after a successful compilation when I run it it gives error. I don't know why this is happening.
int main()
{
char *s1="abcd";
char *s2="efgh";
strcpy(s2,s1);
printf("%s\n", s1);
printf("%s\n",s2);
getch();
}
These are string literals, you can't modify them because they're stored in read-only memory.
If you want to change this so you can modify them, use char s[]. This will store the strings on the stack:
char s1[] = "abcd";
char s2[] = "efgh";
If you want pointers to these, simply create pointers:
char *p1 = s1;
char *p2 = s2;
or you can create them with compound literals from C99:
char *p1 = (char []){"abcd"};
char *p2 = (char []){"efgh"};
A full program that puts the strings on the stack:
int main(void)
{
char s1[] = "abcd";
char s2[] = "efgh";
strcpy(s2, s1);
printf("%s\n", s1);
printf("%s\n", s2);
getchar();
}
Output:
abcd
abcd
You are trying to copy all content from first pointer string to second pointer string then I like to suggest you to use malloc
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char** argv) {
char *s1 ="abcd";
char *s2 ="efgh";
s2 = (char *) malloc(1 + strlen(s1));
strcpy(s2, s1);
printf("%s\n", s1);
printf("%s\n", s2);
return 0;
}
output -:abcd
abcd
hope this will fulfill your question

C -swap 2 chars recursively with only one pointer

I need to write a function:
void swap (char * s1, char * s2);
The function will replace the contents of both strings 1s and 2s.
Constraints:
In the function, there is no use of [] anywhere, but performance by working with pointers, in addition, trips must be made with the voters, meaning that they will actually move to another cell as needed, and will not remain in the same location all the time.
• No loops in the function, that is, work in recursion.
I did the function with pointer to pointer str** but must change it to only one pointer str and recursively. How can I change it?
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *str1="abc",*str2="xyz",*pRev;
swap(&str1, &str2);
printf("str1 is %s, str2 is %s", str1, str2);
getchar();
return 0;
}
//need *str NOT **str
void swap(char **str1, char **str2);
char * RevWords (char * str, int size);
void swap(char **str1, char **str2)
{
char *temp = *str1_ptr;
*str1_ptr = *str2_ptr;
*str2_ptr = temp;
}
after swap method:
str2="abc", str1="xyz"
Well this is clearly not an ideal solution but gives you something to work with.
However this will only work (as mentioned above) when you have the same length of strings (or yes, you'll have to allocate memory + you'd need to know the length of your strings). But otherwise I think this may answer your question.
This is working with recursion and depends on the fact that both strings are the same length and containing a zero character at the end of each one.
#include <stdio.h>
#include <stdlib.h>
void swap(char* str1, char* str2)
{
// if both of them are zero characters then stop
if (*str1 == '\0' && *str2 == '\0')
return;
// else swap the contents of the pointers
else
{
char tmp = *str1;
*str1 = *str2;
*str2 = tmp;
// advance both pointer and swap them too if thye are not '\0'
swap(++str1, ++str2);
}
}
int main()
{
char str1[] = "abc\0\0\0"; // padded with zeros to be the same length as str2
char str2[] = "xyz123"; // the last '\0' is automatically added
swap(str1, str2);
printf("str1 is %s, str2 is %s", str1, str2);
getchar();
return 0;
}

C - Copy contents of one char array to another using pointers

I'm trying to write a simple C function to copy the contents of one char array to another using pointer arithmetic. I can't seem to get it working, can you tell me where I'm going wrong?
#include <stdio.h>
#include <stdlib.h>
void copystr(char *, const char *);
int main()
{
char hello[6] = "hello";
const char world[6] = "world";
copystr(&hello, &world);
return 0;
}
void copystr(char *str1, const char *str2)
{
*str1 = *str2; //copy value of *str2 into *str1
printf("%s %s", *str1, *str2); //print "world" twice
}
Help appreciated, thanks.
EDIT:
Here is the working code:
#include <stdio.h>
#include <stdlib.h>
void copystr(char *, const char *);
int main()
{
char hello[6] = "hello";
const char world[6] = "world";
copystr(hello, world);
printf("%s %s", hello, world);
return 0;
}
void copystr(char *str1, const char *str2)
{
/*copy value of *str2 into *str1 character by character*/
while(*str2)
{
*str1 = *str2;
str1++;
str2++;
}
}
You are only copying the first character of the string.
void copystring(char* str1, const char* str2)
{
while(*str2)
{
*str1 = *str2; //copy value of *str2 into *str1
str1++;
str2++;
}
}
and then in main, after calling copystring
printf("%s %s", hello, world); //print "world" twice
But please don't do this! Use strncpy in real life, if working with plain C strings.

Rotated strings

Write code to check if s2 is rotation of s1 using only one call to isSubString (ie. waterbottle is a rotation of erbottlewat).
I write program for this but i can't able to get the desired output. Please guide me where I am going wrong.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int isRotated(char *s1, char *s2);
int isSubstring(char *s1, char *s2);
int isRotated(char *s1, char *s2)
{
int r;
char s[100];
if(strlen(s1) == strlen(s2))
strcpy(s, s1);
r = isSubstring(s, s2);
strcat(s, s1);
return r;
}
int isSubstring(char *s1, char *s2){
if(strstr(s1, s2))
return 1;
else
return 0;
}
int main(void) {
char s1[100], s2[100];
printf("Enter the first String\n");
scanf("%s", s1);
printf("Enter the second String\n");
scanf("%s", s2);
if(isRotated(s1, s2)==1)
printf("%s and %s are rotated string\n", s1, s2);
else
printf("%s and %s are not rotated string\n", s1, s2);
return 0;
}
To check if s2 is rotation of s1, you may want to concentrate two s1s, and try finding s2 in the new string.
It is necessary to check the length of s1 and s2. For example, s1 is "ABCD", s2 is "CDA". Then s is "ABCDABCD". strstr(s, s2) == 1, but obviously, s2 isn't rotation of s1.
Also, I'd want to call strcmp() first, because I consider a "ABCD" as rotation of "ABCD" itself. However, this is only a matter of definition.
int isRotated(char *s1, char *s2)
{
char s[199];
if(strlen(s1) != strlen(s2))
return 0;
else if(strcmp(s1, s2) == 0)
return 1;
else
strcpy(s, s1);
strcat(s, s1);
return isSubString(s, s2);
}
BTW: "substring" is one word, so it might be better changing isSubString() to isSubstring()
If you do the comparison with strstr() you are searching a substring in the rotated string. So what you are doing is to find for example the string s1 ABCD in an other string s2 CDAB. So in fact s2 has no substring s1 in it and your function int isSubString(char *s1,char *s2) will always return false.
A simple solution for this would be not to compare s1 with s2 directly. You have to compare s2 to a doubled copy of s1: CDABCDAC, there you can see that this string contains a substring ABCD and your function will return true.
This would mean for your function:
int isRotated(char *s1,char *s2)
{
char s[200];
strcpy(s,s1); // Copy content of s1 to s
strcat(s,s1); // Append s again with the content of s1
if(strstr(s,s2))
return 1;
else
return 0;
}
How about this, using the concatenate-and-look-for-substring approach:
int isRotated(const char *s1, const char *s2)
{
const size_t l1 = strlen(s1);
const size_t l2 = strlen(s2);
if(l1 != l2)
return 0;
char joined[2 * l1 + 1];
memcpy(joined, s1, l1);
memcpy(joined + l1, s1, l1);
joined[2 * l1] = '\0';
return strstr(joined, s2) != NULL;
}
Basically uses more const, variable-length array to handle varying lengths, and memcpy() when we know the length we're copying.

What is wrong with my 'append' algorithm or code?

2 strings are given, second word will be append to first one and 3rd variable will store this. For example;
char *str1 = "abc";
char *str2 = "def";
char *str3 = "abcdef"; //should be
Here is my code, I get runtime error:
#include <stdio.h>
#include <malloc.h>
void append(char *str1, char *str2, char *str3, int size1, int size2)
{
int i=0;
str3 = (char*) malloc(size1+size2+1);
str3 = str1;
while (str2[i] != '\0') {
str3[i+size1] = str2[i];
i++;
}
str3[size1+size2] = '\0';
}
int main()
{
char *str1 = "abc";
char *str2 = "def";
char *str3;
append(str1, str2, str3, 3, 3);
return 0;
}
str3 = (char*) malloc(size1+size2+1);
str3 = str1;
Here's your problem. Doing this replaces the pointer to the correct amount of space from malloc to the pointer where str1 is contained. Keeping with your loop design, change this to:
str3 = malloc(size1+size2+1);
for (int j = 0; str1[j] != '\0'; j++)
str3[j] = str1[j];
Also, see this question/answer about casting the result of malloc in C:
Do I cast the result of malloc?
There is another issue with the code. You pass pointer by value. So any malloc inside a function will do only local changes. After function ends your pointer will still point to the old value. You should pass a pointer to pointer if you want to change it. See an example:
#include <stdio.h>
char *c = "Second";
void assign(char *s) { s = c; }
int main()
{
char *str = "First";
assign(str);
printf("String after assign: %s\n", str);
return 0;
}
After running the program you will see 'First' in you console. The correct code is:
#include <stdio.h>
char *c = "Second";
void assign(char **s) { *s = c; }
int main()
{
char *str = "First";
assign(&str);
printf("String after assign: %s\n", str);
return 0;
}
#include <stdio.h>
#include <stdlib.h> //to standard
#include <string.h>
char *append(const char *str1, const char *str2, int size1, int size2){
//parameter char *str3 is local variable.
//It is not possible to change the pointer of the original.
//str3 = str1;//<<-- memory leak
//str3[i+size1] = str2[i];//<<-- write to after str1(can't write!)
char *str3 = (char*) malloc(size1+size2+1);
memcpy(str3, str1, size1);//copy to alloc'd memory.
memcpy(str3 + size1, str2, size2);//copy to after str1
str3[size1+size2] = '\0';
return str3;
}
int main(){
char *str1 = "abc";
char *str2 = "def";
char *str3;
str3 = append(str1, str2, 3, 3);
printf("%s\n", str3);
return 0;
}

Resources