簡體   English   中英

刪除 C 中字符串前的前導字符(概念題)

[英]delete leading characters before a string in C (concept question)

我正在學習 C,處理字符串和指針。 練習要求刪除字符串前的所有前導字符(在本例中為“X”)。 被調用的 function 必須接受一個字符串,即一個指向 char 的指針。 我通過搜索找到了多種執行此操作的方法,但我不明白為什么以下代碼不起作用......我缺少什么概念?

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

有多種方法可以從字符串中刪除字符,但不清楚您想要哪種。

C、memory內容不能“刪除”。 Memory 由字節組成,字節保存值。 當我們有一個字符串的時候,它存在於memory的某個地方,而這個字符串的字節是不能把go弄走的。

從字符串中刪除字符的三種方法是:

  • 給定字符串的起始地址,返回字符串所需部分的地址。
  • 給定一個指向字符串開頭的指針,更新指針以指向字符串的所需部分。
  • 將字符串中后面的字符移到前面。

以下是示例實現:

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

另一種選擇是制作字符串所需部分的新副本,在 memory 中,由調用者提供或由刪除例程分配。

對於初學者,function 應該聲明為

char * delChar( char *str );

function參數str是function的局部變量。所以這個賦值

str = walker;

不改變 main 中聲明的指針myStr 此指針按值傳遞給 function。 即 function 處理指針的副本。 並且賦值不會改變原始指針myStr 它僅更改由指針myStr的值的副本初始化的局部變量str

您也不能更改字符串文字。 任何更改字符串文字的嘗試都會導致未定義的行為。 但是您確實需要更改傳遞的字符串,至少要遵循您的分配

刪除 C 中字符串前的前導字符

也就是說,任務不是找到指向第一個不等於'X'的字符的指針。 您需要從字符串中刪除等於'X'前導字符。

在 main 中,您需要聲明一個字符數組而不是一個指向字符串文字的指針,例如

char myStr[] = "XXXXXXXXXXXXTest";

function本身可以通過以下方式定義

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

程序 output 是

Before function call: XXXXXXXXXXXXTest
After function call: Test

function 將更靈活,如果聲明第二個參數將指定應從字符串開頭刪除的字符。 例如

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

在這種情況下,function 被稱為

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

感謝您的周到回復和評論。 我推斷這基本上是關於指針的問題; 那是。 無需從 function 調用返回指針即可修改字符串。 為了那些可能正在學習的人的利益,我簡化了示例代碼問題,並附有評論(見下文)。 如果我不在基地,請告訴我...


    #include <stdio.h>
    #include <stdlib.h>
    
    void func(char** str) //note POINTER-TO-POINTER parameter!
    {
        printf("\nintial func str: %s", *str); //note dereference before str; prints "FULL TEXT"
        *str += 5;  //increment pointer five spaces to right to modify the string
        printf("\nafter func str: %s", *str); //note dereference before str; prints "TEXT"
    }
    
    int main()
    {
        char* myStr = "FULL TEXT"; //need to initialize string with pointer variable
        //char myStr[] = "FULL TEXT"; //initializing string as array will not work for this example!
    
        printf("\n...before MAIN func call: %s", myStr); //prints "FULL TEXT"
    
        /*pass ADDRESS of pointer variable instead of pointer variable itself, i.e. func
        parameter needs to be a pointer-to-a-pointer...this is essentially passing by REFERENCE
        instead of by VALUE (where a copy would get clobbered when returning to main)*/
    
        func(&myStr); //note ADDRESS symbol, i.e. address of pointer variable
    
        printf("\n...after MAIN func call: %s", myStr); //prints "TEXT", modified string remains after func call
        return 0;
    }

function 中的 str 變量delChar將在您傳遞的堆棧和存儲地址上創建,並在 function 返回時銷毀

 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 后仍將指向字符串的開頭。

你需要返回地址和商店

您可以使用計數器跟蹤計數並返回計數,如下所示

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM