I’m learning C, dealing with strings and pointers. An exercise calls for deleting all leading characters (‘X’ in this case) before a string. The called function must accept a string, i.e. a pointer to a char. I have found multiple ways of doing this by searching, but I do not understand why the following code does not work...what concept am I missing?
```
//delete all leading X characters by passing pointer to a string
#include <stdio.h>
#include <string.h>
void delChar(char* str)
{
char* walker; //declare pointer
walker = str; //point to beginning of passed string
while(*walker == 'X') walker ; //move pointer past amy leading 'X'
printf("\nwalker string is now: %s", walker); //prints "Test" as expected
str = walker; //set str pointer to walker
printf("\nstr string is now: %s", str); //prints "Test" as expected
return;
}
int main()
{
char* myStr = "XXXXXXXXXXXXTest";
printf("Before function call: %s", myStr); //prints "XXXXXXXXXXXXTest" as expected
delChar(myStr); //pass pointer to the string
printf("\nAfter function call: %s", myStr); //WHY DOES THIS print "XXXXXXXXXXXXTest" ?
return 0;
}
```
CodePudding user response:
There are multiple ways in which characters can be deleted from a string, and it is not clear which you want.
In C, memory contents cannot be “deleted.” Memory is formed of bytes, and bytes hold values. When we have a string, it exists in a certain place in memory, and the bytes of the string cannot be made to go away.
Three ways to delete characters from a string are:
- Given the start address of the string, return the address of the desired part of the string.
- Given a pointer to the start of the string, update the pointer to point to the desired part of the string.
- Move characters from later in the string to earlier.
Here are sample implementations:
#include <stdio.h>
/* Deletion method 0: Find the first character that is not an "X" and
return its address.
*/
static char *DeleteMethod0(char *string)
{
for (char *p = string; ; p)
if (*p != 'X')
return p;
}
// Deletion method 1: Update the pointer to the start of the string.
static void DeleteMethod1(char **string)
{
while (**string == 'X')
*string;
}
// Deletion method 2: Move characters.
static void DeleteMethod2(char *string)
{
// Find the point where we stop deleting.
char *source = string;
while (*source == 'X')
source;
// Copy the undeleted part of the string to the start.
while (*source)
*string = *source ;
*string = '\0';
}
int main(void)
{
char *string = "XXXXXXXXXXXXTest";
char buffer[] = "XXXXXXXXXXXXTest";
printf("The string is %s.\n", string);
printf("The buffer contains %s.\n", buffer);
char *after = DeleteMethod0(string);
printf("The string after deletion by getting new address %s.\n", after);
DeleteMethod1(&string);
printf("The string after deletion by updating the pointer is %s.\n", string);
DeleteMethod2(buffer);
printf("The buffer after deletion by moving characters is %s.\n", buffer);
}
Another option would be to make a new copy of the desired part of the string, in memory either supplied by the caller or allocated by the deletion routine.
CodePudding user response:
For starters the function should be declared like
char * delChar( char *str );
The function parameter str
is a local variable of the function. So this assignment
str = walker;
does not change the pointer myStr
declared in main. This pointer is passed to the function by value. That is the function deals with a copy of the pointer. And the assignment does not change the original pointer myStr
. It changes only its local variable str
that was initialized by a copy of the value of the pointer myStr
.
Also you may not change a string literal. Any attempt to change a string literal results in undefined behavior. But you need indeed to change the passed string as at least followed from your assignment
delete leading characters before a string in C
That is the task is not to find the pointer that points to the first character that is not equal to 'X'
. You need to remove leading characters equal to 'X'
from a string.
In main you need to declare a character array instead of a pointer to a string literal as for example
char myStr[] = "XXXXXXXXXXXXTest";
The function itself can be defined the following way
char * delChar( char *str )
{
char *walker = str;
while ( *walker == 'X' ) walker;
if ( walker != str ) memmove( str, walker, strlen( str ) 1 - ( walker - str ) );
return str;
}
And in main it is enough to write
printf("After function call: %s\n", delChar( myStr ) );
Here is a demonstration program
#include <stdio.h>
#include <string.h>
char * delChar( char *str )
{
char *walker = str;
while (*walker == 'X') walker;
if (walker != str) memmove( str, walker, strlen( str ) 1 - ( walker - str ) );
return str;
}
int main( void )
{
char myStr[] = "XXXXXXXXXXXXTest";
printf( "Before function call: %s\n", myStr );
printf( "After function call: %s\n", delChar( myStr ) );
}
The program output is
Before function call: XXXXXXXXXXXXTest
After function call: Test
The function will be more flexible if to declare a second parameter that will specify a character that should be deleted from the beginning of a string. For example
char * delChar( char *str, char c )
{
char *walker = str;
while (*walker == c) walker;
if (walker != str) memmove( str, walker, strlen( str ) 1 - ( walker - str ) );
return str;
}
In this case the function is called like
printf( "After function call: %s\n", delChar( myStr, 'X'));
CodePudding user response:
str variable in function delChar
will created over stack and store address you have passed and will be destroyed when function returns
void delChar(char* str) // str variable will created over stack and store address you have passed and will be destroyed when function returns
{
char* walker; //declare pointer
walker = str; //point to beginning of passed string
while(*walker == 'X') walker ; //move pointer past amy leading 'X'
printf("\nwalker string is now: %s", walker); //prints "Test" as expected
str = walker; //set str pointer to walker
printf("\nstr string is now: %s", str); //prints "Test" as expected
return;
}
After the return str in main will still point to start of the string.
you need to return the address and store
you can track count using counter and return the count Like below
#include<stdio.h>
int delChar(char* str)
{
int count = 0;
while(*str == 'X')
count ; // increment the count when x found
printf("\nwalker string is now: %s", str count);
return count;
}
int main()
{
char* myStr = "XXXXXXXXXXXXTest";
int count;
printf("Before function call: %s", myStr);
count = delChar(myStr);
printf("\nAfter function call: %s", myStr count);
return 0;
}