删除C中字符串前的前导字符(概念问题)

toe95027  于 2023-01-16  发布在  其他
关注(0)|答案(3)|浏览(178)

我正在学习C语言,处理字符串和指针。一个练习要求删除字符串前面的所有前导字符(在本例中为“X”)。被调用的函数必须接受字符串,即字符的指针。我通过搜索找到了多种方法来做到这一点,但我不明白为什么下面的代码不起作用......我错过了什么概念?

//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;
     }
rslzwgfq

rslzwgfq1#

有多种方法可以从字符串中删除字符,但不清楚您需要哪种方法。
在C语言中,内存内容不能被“删除”。内存是由字节组成的,字节保存值。当我们有一个字符串时,它存在于内存中的某个地方,字符串的字节不能被删除。
从字符串中删除字符的三种方法是:

  • 给定字符串的起始地址,返回字符串所需部分的地址。
  • 给定一个指向字符串开头的指针,更新该指针以指向字符串的所需部分。
  • 将字符从字符串中较后的位置移到较前的位置。

以下是示例实现:

#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);
}

另一种选择是在调用者提供的内存中或删除例程分配的内存中,为字符串的所需部分创建一个新副本。

piwo6bdm

piwo6bdm2#

对于初学者,函数应声明为

char * delChar( char *str );

函数参数str是函数的局部变量,所以这个赋值

str = walker;

不改变main中声明的指针myStr。这个指针是按值传递给函数的。也就是说,函数处理指针的副本。并且赋值不改变原始指针myStr。它只改变它的局部变量str,该变量是由指针myStr的值的副本初始化的。
你也不能改变字符串。任何改变字符串的尝试都会导致未定义的行为。但是你确实需要改变传递的字符串,至少要跟在你的赋值语句后面
在C中删除字符串前的前导字符
也就是说,任务不是找到指向第一个不等于'X'的字符的指针,而是需要从字符串中删除等于'X'的前导字符。
在main中,你需要声明一个字符数组,而不是一个指向字符串的指针,例如

char myStr[] = "XXXXXXXXXXXXTest";

函数本身可以通过以下方式定义

char * delChar( char *str )
{
    char *walker = str;

    while ( *walker == 'X' ) ++walker;

    if ( walker != str ) memmove( str, walker, strlen( str ) + 1 - ( walker - str ) );

    return str;
}

总的来说,这足以说明

printf("After function call: %s\n", delChar( myStr ) );

这是一个演示程序

#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 ) );
}

程序输出为

Before function call: XXXXXXXXXXXXTest
After function call: Test

如果声明第二个参数来指定应该从字符串开头删除的字符,那么函数将更加灵活。

char * delChar( char *str, char c )
{
    if ( c != '\0' )
    {
        char *walker = str;

        while (*walker == c) ++walker;

        if (walker != str) memmove( str, walker, strlen( str ) + 1 - ( walker - str ) );
    }

    return str;
}

在这种情况下,函数的调用如下所示

printf( "After function call: %s\n", delChar( myStr, 'X'));
0aydgbwb

0aydgbwb3#

函数delChar中字符串变量将在堆栈上创建,并存储您传递的地址,并将在函数返回时销毁

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;
}

在main中返回str后,它仍然指向字符串的开头.

您需要返回地址并存储

你可以使用counter跟踪计数并返回如下计数

#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;
}

相关问题