字符串复制功能无法正确复制字符串我的代码有什么问题?

问题描述

我正在尝试编写一个函数,该函数从字符串中删除空格,并将其转换为小写。

我下面的代码未返回任何内容。为什么?

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)是表示该值的 type 所需的字节大小。因此,如果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处分配 w [6]至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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...