簡體   English   中英

字符串復制功能未正確復制字符串。 我的代碼有什么問題?

[英]String copy function not copying string properly. What's wrong with my code?

我正在嘗試編寫一個函數,從字符串中刪除 whitesapces 並將其轉換為小寫。

我下面的代碼不返回任何內容。 為什么?

char *removeSpace(char *st);

int main(void){
    char *x = "HeLLO WOrld ";

    x = removeSpace(x);
    printf("output: %s\n", x);

}

char *removeSpace(char *st)
{
    int c = 0;
    char *s = malloc(sizeof(strlen(st)+1));
    for (int x = 0; x < strlen(st); x++)
    {
        if (st[x] != ' ')
        {
            s[x] = tolower(st[x]);
        }
    }
    st= s;

    st= s;
    return st;
}

char *s = malloc(sizeof(strlen(st)+1));

你有幾個嵌套的表情,你的評論線程(我想這是50:50)躍升完全錯誤的方式。

  • strlen(st)是字符串st的字符數

  • strlen(st)+1是為副本分配的正確字符數

    ......到目前為止看起來不錯!

  • sizeof(strlen(st)+1)是表示該值類型所需的字節大小。 所以如果size_t是一個 4 字節的unsigned int ,這個 sizeof 表達式就是4

    此時字符串長度的值被丟棄。

現在,您想要為字符串分配足夠的字節,而不是足夠的字節來將字符串的長度保存為size_t值。 只需完全刪除sizeof

哦,還有 - st = s在這里沒有任何作用。 變量st在函數內部是局部的,不會影響外部的任何東西。 返回s就足夠了。

malloc 語句不必要地使用了 sizeof,如注釋中所述。 您在為新字符串分配字符時也有錯誤:

s[x] = tolower(st[x]);

您對新字符串 s 使用與舊字符串 st 相同的索引。 一旦刪除任何空格,這是不對的。 因此,例如,當您復制hello 時,索引 0 到 4 在兩個字符串之間排列,但隨后您跳過索引 5 處的空格,然后您想將 st[6] 處的w分配給 s[5]。 這意味着您需要一個單獨的索引來跟蹤您在目標字符串中的位置。 所以你需要像這樣的代碼,它清理 malloc(),添加缺少的頭文件,並為輸出字符串引入一個新的索引:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

char *removeSpace(char *st);

int main(void){
    char *x = "HeLLO WOrld ";

    x = removeSpace(x);
    printf("output: %s\n", x);

}

char *removeSpace(char *st)
{
    size_t len = strlen(st);
    int newStrIdx = 0;
    char *s = malloc(len+1);
    for (int x = 0; x < len; x++)
    {
        if (st[x] != ' ')
        {
            s[newStrIdx++] = tolower(st[x]);
        }
    }
    s[newStrIdx] = '\0';

    return s;
}

哦,你忘記了我在最后添加的空終止輸出字符串。

對於初學者來說,如果你想創建一個字符串的副本,那么函數聲明應該看起來像

char * removeSpace( const char *st);

即原始字符串在函數內未更改。

當你向函數傳遞一個字符串文字時

char *x = "HeLLO WOrld ";

x = removeSpace(x);

那么它確實可能不會在函數內改變。 任何更改字符串文字的嘗試都會導致未定義的行為。

malloc調用中使用的表達式

sizeof(strlen(st)+1)

等價於表達式

sizeof( size_t )

由於函數strlen具有返回類型size_t

所以這個表達式不會產生源字符串的長度。

此外,無需分配大小等於源字符串大小的字符串,因為目標字符串的字符數(由於刪除空格)可以比源字符串少得多。

if 語句中的賦值

    if (st[x] != ' ')
    {
        s[x] = tolower(st[x]);
    }

在表達式s[x]使用無效索引。 因此,目標字符串將包含未初始化字符的間隙。

此外,終止零字符'\\0'未附加到目標字符串

考慮到空白字符集包括其他字符,例如除空格字符' '之外的制表符'\\t' ' '

該函數可以通過以下方式定義。

char * removeSpace( const char *st )
{
    size_t n = 0;

    for ( const char *src = st; *src; ++src )
    {
        if ( !isspace( ( unsigned char )*src ) ) ++src;
    }

    char *result = malloc( n + 1 );
    result[n] = '\0';        
    
    for ( char *dsn = result; *st; ++st )
    {
        if ( !isspace( ( unsigned char )*st ) )
        {
            *dsn++ = tolower( ( unsigned char )*st );
        }
    }

    return result;
}

該函數可以像這樣調用

char *st = "HeLLO WOrld ";

char *dsn = removeSpace( st );

puts( dsn );

free( dsn );

這是一個演示程序。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

char * removeSpace( const char *st )
{
    size_t n = 0;

    for ( const char *src = st; *src; ++src )
    {
        if ( !isspace( ( unsigned char )*src ) ) ++src;
    }

    char *result = malloc( n + 1 );
    result[n] = '\0';        
    
    for ( char *dsn = result; *st; ++st )
    {
        if ( !isspace( ( unsigned char )*st ) )
        {
            *dsn++ = tolower( ( unsigned char )*st );
        }
    }

    return result;
}

int main(void) 
{
    char *st = "HeLLO WOrld ";

    char *dsn = removeSpace( st );

    puts( dsn );

    free( dsn );

    return 0;
}

它的輸出是

helloworld

暫無
暫無

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

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