字符串复制函数无法正确复制字符串。我的代码有什么问题?
String copy function not copying string properly. What's wrong with my code?
我正在尝试编写一个函数,从字符串中删除 whitesapces 并将其转换为小写。
我下面的代码没有 return 任何东西。为什么?
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 相同的索引。一旦您删除任何 spaces,这是不正确的。因此,例如,当您复制 hello 时,索引 0 到 4 在两个字符串之间排列,但随后您跳过索引 5 处的 space 然后您想要分配 w 在 st[6] 到 s[5]。这意味着您需要一个单独的索引来跟踪您在目标字符串中的位置。所以你需要类似这段代码的东西,它清理 malloc(),添加缺失的 header 包含,并为输出字符串引入一个新索引:
#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] = '[=11=]';
return s;
}
哦,你忘记了 null-terminate 我在最后添加的输出字符串。
对于初学者来说,如果你想创建一个字符串的副本,那么函数声明应该是这样的
char * removeSpace( const char *st);
即原始字符串在函数内没有改变。
当你向函数传递一个字符串文字时
char *x = "HeLLO WOrld ";
x = removeSpace(x);
那么在函数内确实不能更改。任何更改字符串文字的尝试都会导致未定义的行为。
调用malloc
时使用的表达式
sizeof(strlen(st)+1)
等同于表达式
sizeof( size_t )
由于函数 strlen
具有 return 类型 size_t
。
所以这个表达式不会产生源字符串的长度。
此外,无需分配大小与源字符串大小相等的字符串,因为目标字符串的字符数(由于删除了 spaces)比源字符串少得多。
if语句中的赋值
if (st[x] != ' ')
{
s[x] = tolower(st[x]);
}
在表达式 s[x]
中使用了无效索引。因此,目标字符串将包含未初始化字符的间隙。
终止零字符 '[=23=]'
也没有附加到目标字符串
考虑到白色 space 字符集包括其他字符,例如制表符 '\t'
除了 space 字符 ' '
。
函数可以这样定义。
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] = '[=15=]';
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] = '[=17=]';
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
我正在尝试编写一个函数,从字符串中删除 whitesapces 并将其转换为小写。
我下面的代码没有 return 任何东西。为什么?
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 相同的索引。一旦您删除任何 spaces,这是不正确的。因此,例如,当您复制 hello 时,索引 0 到 4 在两个字符串之间排列,但随后您跳过索引 5 处的 space 然后您想要分配 w 在 st[6] 到 s[5]。这意味着您需要一个单独的索引来跟踪您在目标字符串中的位置。所以你需要类似这段代码的东西,它清理 malloc(),添加缺失的 header 包含,并为输出字符串引入一个新索引:
#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] = '[=11=]';
return s;
}
哦,你忘记了 null-terminate 我在最后添加的输出字符串。
对于初学者来说,如果你想创建一个字符串的副本,那么函数声明应该是这样的
char * removeSpace( const char *st);
即原始字符串在函数内没有改变。
当你向函数传递一个字符串文字时
char *x = "HeLLO WOrld ";
x = removeSpace(x);
那么在函数内确实不能更改。任何更改字符串文字的尝试都会导致未定义的行为。
调用malloc
时使用的表达式
sizeof(strlen(st)+1)
等同于表达式
sizeof( size_t )
由于函数 strlen
具有 return 类型 size_t
。
所以这个表达式不会产生源字符串的长度。
此外,无需分配大小与源字符串大小相等的字符串,因为目标字符串的字符数(由于删除了 spaces)比源字符串少得多。
if语句中的赋值
if (st[x] != ' ')
{
s[x] = tolower(st[x]);
}
在表达式 s[x]
中使用了无效索引。因此,目标字符串将包含未初始化字符的间隙。
终止零字符 '[=23=]'
也没有附加到目标字符串
考虑到白色 space 字符集包括其他字符,例如制表符 '\t'
除了 space 字符 ' '
。
函数可以这样定义。
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] = '[=15=]';
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] = '[=17=]';
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