I have written a replacechar function which replaces an instance of a source char with a replacement char. The function works in that the string is changed as expected but when I attempt to use the return value of the function, puts just outputs a blank line.
Can someone please explain what is happening and what I would need to change in replacechar to fix.
#include <stdio.h> /* puts */
#include <string.h> /* strcpy */
#include <stdlib.h> /* malloc, free */
char* replacechar(char* s, char ch1, char ch2) {
while (*s) {
if (*s == ch1)
*s = ch2;
*s++;
}
return s;
}
int main()
{
char* s = malloc(8);
strcpy(s, "aarvark");
puts(replacechar(s, 'a', 'z')); /* prints blank line */
puts(s); /* prints zzrvzrk as expected */
free(s);
return 0;
}
Thanks for all the responses.
I have changed to this (which now works fine).
char* replacechar(char* s, char ch1, char ch2) {
char* p = s;
while (*p) {
if (*p == ch1)
*p = ch2;
p++;
}
return s;
}
It returns the value of the s pointer once it's been incremented past the end of the string. Make a local variable in replacechar(), and increment it, and return the original value of s.
Thats because the while loop in replacechar increment s until it's \0. At the end of the function you're returning the pointer, which points to \0 and printing \0 is a blank line. You should manage it like this:
char *replacechar(char *s, char ch1, char ch2) {
char *start = s;
...
return start;
}
Your issue here, with otherwise pretty nice looking code, is one of variable scope.
Use a different local char* within replacechar, like
char* replacechar(char* s, char ch1, char ch2) {
char* tmpstr;
tmpstr=s;
while (*tmpstr) {
if (*tmpstr == ch1)
*tmpstr = ch2;
tmpstr++; /* Note, no "*" here as in your code. */
}
return s; /* s has remained unchanged */
}
#include <stdio.h> /* puts */
#include <string.h> /* strcpy */
#include <stdlib.h> /* malloc, free */
char* replacechar(char* s, char ch1, char ch2) {
char* t = s;
while (*s) {
if (*s == ch1)
*s = ch2;
*s++;
}
return t;
}
int main()
{
char* s = malloc(8);
strcpy(s, "aarvark");
puts(replacechar(s, 'a', 'z')); /* prints blank line */
puts(s); /* prints zzrvzrk as expected */
free(s);
return 0;
}
Related
According to this:
strcpy vs strdup,
strcpy could be implemented with a loop, they used this while(*ptr2++ = *ptr1++). I have tried to do similar:
#include <stdio.h>
#include <stdlib.h>
int main(){
char *des = malloc(10);
for(char *src="abcdef\0";(*des++ = *src++););
printf("%s\n",des);
}
But that prints nothing, and no error. What went wrong?
Thanks a lot for answers, I have played a bit, and decided how best to design the loop to see how the copying is proceeding byte by byte. This seems the best:
#include <stdio.h>
#include <stdlib.h>
int main(){
char *des = malloc(7);
for(char *src="abcdef", *p=des; (*p++=*src++); printf("%s\n",des));
}
In this loop
for(char *src="abcdef\0";(*des++ = *src++););
the destination pointer des is being changed. So after the loop it does not point to the beginning of the copied string.
Pay attention to that the explicit terminating zero character '\0' is redundant in the string literal.
The loop can look the following way
for ( char *src = "abcdef", *p = des; (*p++ = *src++););
And then after the loop
puts( des );
and
free( des );
You could write a separate function similar to strcpy the following way
char * my_strcpy( char *des, const char *src )
{
for ( char *p = des; ( *p++ = *src++ ); );
return des;
}
And call it like
puts( my_strcpy( des, "abcdef" ) )'
free( des );
You are incrementing des so naturally at the end of the cycle it will be pointing past the end of the string, printing it amounts to undefined behavior, you have to bring it back to the beginning of des.
#include <stdio.h>
#include <stdlib.h>
int main(){
int count = 0;
char *des = malloc(10);
if(des == NULL){
return EXIT_FAILURE; //or otherwise handle the error
}
// '\0' is already added by the compiler so you don't need to do it yourself
for(char *src="abcdef";(*des++ = *src++);){
count++; //count the number of increments
}
des -= count + 1; //bring it back to the beginning
printf("%s\n",des);
free(dest); //to free the allocated memory when you're done with it
return EXIT_SUCCESS;
}
Or make a pointer to the beginning of des and print that instead.
#include <stdio.h>
#include <stdlib.h>
int main(){
char *des = malloc(10);
if(des == NULL){
return EXIT_FAILURE; //or otherwise handle the error
}
char *ptr = des;
for(char *src="abcdef";(*des++ = *src++);){} //using {} instead of ;, it's clearer
printf("%s\n",ptr);
free(ptr) // or free(dest); to free the allocated memory when you're done with it
return EXIT_SUCCESS;
}
printf("%s\n",des); is undefined behavior (UB) as it attempts to print starting beyond the end of the string written to allocated memory.
Copy the string
Save the original pointer, check it and free when done.
const char *src = "abcdef\0"; // string literal here has 2 ending `\0`,
char *dest = malloc(strlen(src) + 1); // 7
char *d = dest;
while (*d++ = *src++);
printf("%s\n", dest);
free(dest);
Copy the string literal
const char src[] = "abcdef\0"; // string literal here has 2 ending `\0`,
char *dest = malloc(sizeof src); // 8
for (size_t i = 0; i<sizeof src; i++) {
dest[i] = src[i];
}
printf("%s\n", dest);
free(dest);
You just need to remember the original allocated pointer.
Do not program in main. Use functions.
#include <stdio.h>
#include <stdlib.h>
size_t strSpaceNeedeed(const char *str)
{
const char *wrk = str;
while(*wrk++);
return wrk - str;
}
char *mystrdup(const char *str)
{
char *wrk;
char *dest = malloc(strSpaceNeedeed(str));
if(dest)
{
for(wrk = dest; *wrk++ = *str++;);
}
return dest;
}
int main(){
printf("%s\n", mystrdup("asdfgfd"));
}
or even better
size_t strSpaceNeedeed(const char *str)
{
const char *wrk = str;
while(*wrk++);
return wrk - str;
}
char *mystrcpy(char *dest, const char *src)
{
char *wrk = dest;
while((*wrk++ = *src++)) ;
return dest;
}
char *mystrdup(const char *str)
{
char *wrk;
char *dest = malloc(strSpaceNeedeed(str));
if(dest)
{
mystrcpy(dest, str);
}
return dest;
}
int main(){
printf("%s\n", mystrdup("asdfgfd"));
}
You allocate the destination buffer des and correctly copy the source string into place. But since you are incrementing des for each character you copy, you have moved des from the start of the string to the end. When you go to print the result, you are printing the last byte which is the nil termination, which is empty.
Instead, you need to keep a pointer to the start of the string, as well as having a pointer to each character you copy.
The smallest change from your original source is:
#include <stdio.h>
#include <stdlib.h>
int main(){
char *des = malloc(10);
char *p = des;
for(char *src="abcdef";(*p++ = *src++););
printf("%s\n",des);
}
So p is the pointer to the next destination character, and moves along the string. But the final string that you print is des, from the start of the allocation.
Of course, you should also allocate strlen(src)+1 worth of bytes for des. And it is not necessary to null-terminate a string literal, since that will be done for you by the compiler.
But that prints nothing, and no error. What went wrong?
des does not point to the start of the string anymore after doing (*des++ = *src++). In fact, des is pointing to one element past the NUL character, which terminates the string, thereafter.
Thus, if you want to print the string by using printf("%s\n",des) it invokes undefined behavior.
You need to store the address value of the "start" pointer (pointing at the first char object of the allocated memory chunk) into a temporary "holder" pointer. There are various ways possible.
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *des = malloc(sizeof(char) * 10);
if (!des)
{
fputs("Error at allocation!", stderr);
return 1;
}
char *tmp = des;
for (const char *src = "abcdef"; (*des++ = *src++) ; );
des = temp;
printf("%s\n",des);
free(des);
}
Alternatives:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *des = malloc(sizeof(char) * 10);
if (!des)
{
fputs("Error at allocation!", stderr);
return 1;
}
char *tmp = des;
for (const char *src = "abcdef"; (*des++ = *src++) ; );
printf("%s\n", tmp);
free(tmp);
}
or
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *des = malloc(sizeof(char) * 10);
if (!des)
{
fputs("Error at allocation!", stderr);
return 1;
}
char *tmp = des;
for (const char *src = "abcdef"; (*tmp++ = *src++) ; );
printf("%s\n", des);
free(des);
}
Side notes:
"abcdef\0" - The explicit \0 is not needed. It is appended automatically during translation. Use "abcdef".
Always check the return of memory-management function if the allocation succeeded by checking the returned for a null pointer.
Qualify pointers to string literal by const to avoid unintentional write attempts.
Use sizeof(char) * 10 instead of plain 10 in the call the malloc. This ensures the write size if the type changes.
int main (void) instead of int main (void). The first one is standard-compliant, the second not.
Always free() dynamically allocated memory, since you no longer need the allocated memory. In the example above it would be redundant, but if your program becomes larger and the example is part-focused you should free() the unneeded memory immediately.
So what i have is a string(str) that i get from fgets(str, x, stdin);.
If i write for example "Hello World" i want to be able to add a character infront of each word in the string.
To get this "Hello? World?" as an example. I think i've made it alot harder for myself by trying to solve it this way:
add(char *s, char o, char c){
int i, j = 0;
for (i = 0; s[i] != '\0'; i++) {
if (s[i] != o) {
s[j] = s[i];
}
else {
s[j] = c;
}
j++;
}
}
add(str, ' ','?');
printf("\n%s", str);
This will read out "Hello?World" without the spaces. Now the only way i see this working is if i move everything after the first "?" one to the right while also making the positon of the "W" to a space and a "?" at the end. But for much longer strings i can't see myself doing that.
You can't safely extend a string with more characters without insuring the buffer that holds the string is big enough. So let's devise a solution that counts how many additional characters are needed, allocate a buffer big enough to hold a string of that length, then do the copy loop. Then return the new string back to the caller.
char* add(const char* s, char o, char c)
{
size_t len = strlen(s);
const char* str = s;
char* result = NULL;
char* newstring = NULL;
// count how many characters are needed for the new string
while (*str)
{
len += (*str== o) ? 2 : 1;
str++;
}
// allocate a result buffer big enough to hold the new string
result = malloc(len + 1); // +1 for null char
// now copy the string and insert the "c" parameter whenever "o" is seen
newstring = result;
str = s;
while (*str)
{
*newstring++ = *str;
if (*str == o)
{
*newstring++ = c;
}
str++;
}
*newString = '\0';
return result;
}
Then your code to invoke is as follows:
char* newstring g= add(str, ' ','?');
printf("\n%s", newstring);
free(newstring);
#include <stdio.h>
#include <string.h>
int main(void) {
char text[] = "Hello World";
for(char* word = strtok(text, " .,?!"); word; word = strtok(NULL, " .,?!"))
printf("%s? ", word);
return 0;
}
Example Output
Success #stdin #stdout 0s 4228KB
Hello? World?
IDEOne Link
Knowing the amount of storage available when you reach a position where the new character will be inserted, you can check whether the new character will fit in the available storage, move from the current character through end-of-string to the right by one and insert the new character, e.g.
#include <stdio.h>
#include <string.h>
#define MAXC 1024
char *add (char *s, const char find, const char replace)
{
char *p = s; /* pointer to string */
while (*p) { /* for each char */
if (*p == find) {
size_t remain = strlen (p); /* get remaining length */
if ((p - s + remain < MAXC - 1)) { /* if space remains for char */
memmove (p + 1, p, remain + 1); /* move chars to right by 1 */
*p++ = replace; /* replace char, advance ptr */
}
else { /* warn if string full */
fputs ("error: replacement will exceed storage.\n", stderr);
break;
}
}
p++; /* advance to next char */
}
return s; /* return pointer to beginning of string */
}
...
(note: the string must be mutable, not a string-literal, and have additional storage for the inserted character. If you need to pass a string-literal or you have no additional storage in the current string, make a copy as shown by #Selbie in his answer)
Putting together a short example with a 1024-char buffer for storage, you can do something like:
#include <stdio.h>
#include <string.h>
#define MAXC 1024
char *add (char *s, const char find, const char replace)
{
char *p = s; /* pointer to string */
while (*p) { /* for each char */
if (*p == find) {
size_t remain = strlen (p); /* get remaining length */
if ((p - s + remain < MAXC - 1)) { /* if space remains for char */
memmove (p + 1, p, remain + 1); /* move chars to right by 1 */
*p++ = replace; /* replace char, advance ptr */
}
else { /* warn if string full */
fputs ("error: replacement will exceed storage.\n", stderr);
break;
}
}
p++; /* advance to next char */
}
return s; /* return pointer to beginning of string */
}
int main (void) {
char buf[MAXC];
if (!fgets (buf, MAXC, stdin))
return 1;
buf[strcspn(buf, "\n")] = 0;
puts (add (buf, ' ', '?'));
}
Example Use/Output
$ ./bin/str_replace_c
Hello World?
Hello? World?
Look things over and let me know if you have questions.
Just for fun, here's my implementation. It modifies the string in-place and in O(n) time. It assumes that the char-buffer is large enough to hold the additional characters, so it's up to the calling code to ensure that.
#include <stdio.h>
void add(char *s, char o, char c)
{
int num_words = 0;
char * p = s;
while(*p) if (*p++ == o) num_words++;
char * readFrom = p;
char * writeTo = p+num_words;
char * nulByte = writeTo;
// Insert c-chars, iterating backwards to avoid overwriting chars we have yet to read
while(readFrom >= s)
{
*writeTo = *readFrom;
if (*writeTo == o)
{
--writeTo;
*writeTo = c;
}
writeTo--;
readFrom--;
}
// If our string doesn't end in a 'c' char, append one
if ((nulByte > s)&&(*(nulByte-1) != c))
{
*nulByte++ = c;
*nulByte = '\0';
}
}
int main(int argc, char ** argv)
{
char test_string[1000] = "Hello World";
add(test_string, ' ','?');
printf("%s\n", test_string);
return 0;
}
The program's output is:
$ ./a.out
Hello? World?
I need ideas for a recursive code that deletes a specific char in a string, and move all the other sting chars together
for Example :
"the weather is cloudy"
the entered char is 'e':
result :
"th wathr is cloudy"
I really don't have any idea how to start, thanks for the help.
#include <stdio.h>
void remove_impl(char* s, char c, char* d) {
if (*s != c) {
*d++ = *s;
}
if (*s != '\0') {
remove_impl(++s, c, d);
}
}
void remove(char* s, char c) {
remove_impl(s, c, s);
}
int main() {
char s[] = "the weather is cloudy";
remove(s, 'e');
puts(s);
}
How it works? Consider remove_impl. s is the original string, c is the character to be deleted from s, d is the resulting string, into which the characters of s, not equal to c, are written. Recursively iterates through the characters of s. If the next character is not equal to c, then it is written in d. The recursion stop point is the condition of checking that the end of s is reached. Since it is necessary to modify the source string, the wrapper is implemented (remove) in which as d, the original string (s) is passed.
An easy way to do it is to loop over the string and add any letter that doesn't match the unwanted letter.
Here's a demonstration:
char *source = "the weather is cloudy";
int source_len = strlen(source);
char *target = (char *)calloc(source_len, sizeof(char));
int target_len = 0;
char to_remove = 'e';
for(int i = 0; i < source_len; i++)
{
if(source[i] != to_remove)
{
target[target_len++] = source[i];
}
}
puts(target); // Output "th wathr is cloudy" in the console
My turn to make a proposal ! I add a assert test and use existing functions (strchr and strcpy).
#include <string.h>
#include <stdio.h>
#include <assert.h>
int removeChar(char *str, char chr)
{
assert(str != 0); // Always control entry !
char *str_pnt = strchr(str, chr);
if (str_pnt) {
strcpy(str_pnt, str_pnt+1);
removeChar(str_pnt, chr);
}
}
void main (void)
{
char str[] = "the weather is cloudy";
char char_to_delete = 'e';
removeChar(str, char_to_delete);
puts(str);
}
This can be done in many ways. What i am thinking right now is store not Allowed char array which going to filter which char should show or not. Something like following..
#include <stdio.h>
#include <string.h>
// Global Scope variable declaration
int notAllowedChar[128] = {0}; // 0 for allowed , 1 for not allowed
char inputString[100];
void recursion(int pos, int len) {
if( pos >= len ) {
printf("\n"); // new line
return;
}
if( notAllowedChar[inputString[pos]]) {// not printing
recursion( pos + 1 , len );
}
else {
printf("%c", inputString[pos]);
recursion( pos + 1 , len );
}
}
int main() {
gets(inputString); // taking input String
printf("Enter not allowed chars:: "); // here we can even run a loop for all of them
char notAllowed;
scanf("%c", ¬Allowed);
notAllowedChar[notAllowed] = 1;
int len = strlen(inputString);
recursion( 0 , len );
}
How this work
Lets say we have a simple string "Hello world"
and we want l should be removed from final string, so final output will be "Heo word"
Here "Hello world" length is 11 chars
before calling recursion function we make sure 'l' index which is 108 ascii values link 1 in notAllowedChar array.
now we are calling recursion method with ( 0 , 11 ) value , In recursion method we are having mainly 2 logical if operation, first one is for base case where we will terminate our recursion call when pos is equal or more than 11. and if its not true , we will do the second logical operation if current char is printable or not. This is simply just checking where this char is in notAllowedChar list or not. Every time we increase pos value + 1 and doing a recursion call, and finally when pos is equal or more than 11 , which means we have taken all our decision about printing char or not our recursion will terminate. I tried assign variable with meaningful name. If you still not understand how this work you should go with simple recursion simulation basic ( search in youtube ) and also you should try to manually debug how value is changing in recursion local scope. This may take time but it will be worthy to understand. All the very best.
#include <stdio.h>
/**
* Returns the number of removed chars.
* Base case: if the current char is the null char (end of the string)
* If the char should be deleted return 1 + no of chars removed in the remaining string.
* If it's a some other char simply return the number of chars removed in the remaining string
*/
int removeCAfterwardsAndCount(char* s,char c){
if((*s) == '\0'){
return 0;
}
if((*s) == c){
int noOfChars = removeCAfterwardsAndCount(s+1,c);// s+1 means the remaining string
s[noOfChars] = *s; // move the current char (*s) noOfChars locations ahead
return noOfChars +1; // means this char is removed... some other char should be copied here...
}
else{
int noOfChars = removeCAfterwardsAndCount(s+1,c);
s[noOfChars ] = *s;
return noOfChars ; // means this char is intact ...
}
}
int main()
{
char s[] = "Arifullah Jan";
printf("\n%s",s);
int totalRemoved = removeCAfterwardsAndCount(s,'a');
char *newS = &s[totalRemoved]; // the start of the string should now be originalPointer + total Number of chars removed
printf("\n%s",newS);
return 0;
}
Test Code Here
To avoid moving the chars using loops. I am just moving the chars forward which creates empty space in the start of the string. newS pointer is just a new pointer of the same string to eliminate the empty/garbage string.
#include <stdio.h>
void RemoveChar(char* str, char chr) {
char *str_old = str;
char *str_new = str;
while (*str_old)
{
*str_new = *str_old++;
str_new += (*str_new != chr);
}
*str_new = '\0'; }
int main() {
char string[] = "the weather is cloudy";
RemoveChar(string, 'e');
printf("'%s'\n", string);
return 0; }
#include <stdio.h>
#include <string.h>
char *remove_char(char *str, int c)
{
char *pos;
char *wrk = str;
while((pos = strchr(wrk, c)))
{
strcpy(pos, pos + 1);
wrk = pos;
}
return str;
}
int main()
{
char str[] = "Hello World";
printf(remove_char(str, 'l'));
return 0;
}
Or faster but mode difficult to understand version:
char *remove_char(char *str, int c)
{
char *pos = str;
char *wrk = str;
while(*wrk)
{
if(*wrk == c)
{
*wrk++;
continue;
}
*pos++ = *wrk++;
}
*pos = 0;
return str;
}
Both require the string to be writable (so you cant pass the pointer to the string literal for example)
I'm having looping issues with my code. I have a method that takes in two char arrays (phrase, characters). The characters array holds characters that must be read individually and compared to the phrase. If it matches, every occurrence of the character will be removed from the phrase.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//This method has two parameters: (str, c)
//It will remove all occurences of var 'c'
//inside of 'str'
char * rmstr(char * c, char * str) {
//Declare counters and pointers
int stemp = 0;
int ctemp = 0;
char *p = str;
char *d = c;
//Retrieve str count
while(str[stemp] != '\0') {
stemp++;
}
//Retrieve c count
while(c[ctemp] != '\0') {
ctemp++;
}
//Output information
printf("String Count: %d\n",stemp);
printf("Character Count: %d\n",ctemp);
//Iterate through arrays
for (int i = 0; i != stemp; i++) {
for (int j = 0; j != ctemp; j++) {
if (c[j] != str[i]){
*p++ = str[i];
}
break;
}
printf("%s\n",str);
}
*p = 0;
return str;
}
int main()
{
char c[256] = "ema";
char input[256] = "Great message!";
char *result = rmstr(c, input);
printf("%s", result);
return 0;
}
In this case, the input would be "Great Message!" and the character I'd like to remove all occurrences of the characters: e, m, a (As specified in main).
Using the code as it is above, the output is as follows:
Grat mssag!
It is only looping through 1 iteration and removing 'e'. I would like it to loop through 'm' and 'a' as well.
After you fix your break; that was causing your inner loop to exit, it may make sense to reorder your loops and loop over the chars to remove while checking against the characters in str. This is more of a convenience allowing you to shuffle each character down by one in str if it matches a character is c. If you are using the functions in string.h like memmove to move characters down, it doesn't really matter.
A simple implementation using only pointers to manually work through str removing all chars in c could look something like the following:
#include <stdio.h>
char *rmstr (char *str, const char *chars)
{
const char *c = chars; /* set pointer to beginning of chars */
while (*c) { /* loop over all chars with c */
char *p = str; /* set pointer to str */
while (*p) { /* loop over each char in str */
if (*p == *c) { /* if char in str should be removed */
char *sp = p, /* set start pointer at p */
*ep = p + 1; /* set end pointer at p + 1 */
do
*sp++ = *ep; /* copy end to start to end of str */
while (*ep++); /* (nul-char copied on last iteration) */
}
p++; /* advance to next char in str */
}
c++; /* advance to next char in chars */
}
return str; /* return modified str */
}
int main (void) {
char c[] = "ema";
char input[] = "Great message!";
printf ("original: %s\n", input);
printf ("modified: %s\n", rmstr (input, c));
return 0;
}
(there are many ways to do this -- how is largely up to you. whether you use pointers as above, or get the lengths and use string-indexes is also a matter of choice)
Example Use/Output
$ ./bin/rmcharsinstr
original: Great message!
modified: Grt ssg!
If you did want to use memmove (to address the overlapping nature of the source and destination) to move the remaining characters in str down by one each time the character in str matches a character in c, you could leave the loops in your original order, e.g.
#include <string.h>
char *rmstr (char *str, const char *chars)
{
char *p = str; /* set pointer to str */
while (*p) { /* loop over each char in str */
const char *c = chars; /* set pointer to beginning of chars */
while (*c) { /* loop over all chars with c */
while (*c == *p) { /* while the character matches */
memmove (p, p + 1, strlen (p)); /* shuffle down by 1 */
c = chars; /* reset c = chars to check next */
}
c++; /* advance to next char in chars */
}
p++; /* advance to next char in str */
}
return str; /* return modified str */
}
(make sure you understand why you must reset c = chars; in this case)
Finally, if you really wanted the shorthand way of doing it, you could use strpbrk and memmove and reduce your function to:
#include <string.h>
char *rmstr (char *str, const char *chars)
{
/* simply loop using strpbrk removing the character found */
for (char *p = strpbrk (str, chars); p; p = strpbrk (str, chars))
memmove (p, p+1, strlen(p));
return str; /* return modified str */
}
(there is always more than one way to skin-the-cat in C)
The output is the same. Look things over here and let me know if you have further questions.
//a function that copies one string to another
copy(char *,char*);
main()
{
char one[20],two[20];
printf("enter two sentences \n\n");
gets(one);//first string
gets(two);//second string
copy(one,two);
printf("%s",two);
}
copy(char *s1,char *s2)
{
while(*s1!='\0')
{
s2=s1;
s1++;
s2++;
}
s2='\0';
}
what wrong with the above program ? why the string 'one' is not getting copied to string 'two'?please explain with the help of pointer
It's because this:
s2 = s1;
changes the pointer s2 so that it points to the content of s1.
What you want to do is copy the content:
*s2 = *s1;
A decent compiler should also have given you a warning on this line:
s2 = '\0';
since you're assigning a char to a char *. It should be:
*s2 = '\0';
Enacting those changes, the function would then be (including using some, IMNSHO, better variable names):
void copy (char *from, char *to) {
while (*from != '\0') {
*to = *from;
from++;
to++;
}
*to = '\0';
}
Or, once your brain has been warped by several decades of C use like mine :-)
void copy (char *from, char *to) {
while (*to++ = *from++);
}
#include <stdio.h>
#include <string.h> /* for strchr */
void copy(const char *, char*); /* use void to return nothing */
int main(void) /* main() is not valid */
{
char one[20], two[20];
char *ptr;
printf("enter two sentences \n\n");
/* gets is deprecated, use fgets in order to avoid overflows */
fgets(one, sizeof one, stdin);
/* fgets leaves a trailing newline, remove it */
if ((ptr = strchr(one, '\n'))) *ptr = '\0';
fgets(two, sizeof two, stdin); /* why? is gonna be replaced by one */
copy(one, two);
printf("%s\n", two);
return 0;
}
void copy(const char *s1, char *s2) /* s1 is not modified, use const */
{
while(*s1 != '\0')
{
*s2 = *s1; /* Don't assign addresses, assign values */
s1++;
s2++;
}
*s2 = '\0';
}