在我的代码的这一部分中,我删除了string1
的空格并将结果复制到string2
。
char * remove_blank_spaces(char * string1) {
char * string2 = malloc(sizeof(string1));
int index = 0;
for (int i = 0; string1[i] != 0; i++) {
if(string1[i] != ' ') {
//printf("i: %dn", i);
//printf("c2: %cn", string1[i]);
string2[index] = string1[i];
index++;
}
}
string2[index] = ' ';
printf("string2: %sn", string2);
return string2;
}
我用以下方法检查结果:
assert(remove_blank_spaces("a b") == "ab"); // Edit: here is the error!
我收到一个错误:Assertion failed!
和Expression: remove_blank_spaces("a b") == "ab"
我比较了 Virtual-C 中的字符串,它们看起来是一样的。 为什么断言失败?
您的代码有一个错误:malloc
分配的空间不足,这会导致尝试访问未分配内存时出现未定义的行为。
断言也失败了,因为您通过==
比较指针,而不是通过strcmp
的 C 字符串。
此外,我建议进行两项更改:
- 不要混合计算和输出。返回值,不要将其
printf
在函数中。 - 使用描述性和正确的名称。这需要考虑上下文。例如,
index
通常可以是一个好名称,但在您的情况下,不清楚您指的是哪个索引,这会导致错误,其中index
用于索引到错误的变量中。至于"正确"的名称,您所说的"空格"通常称为"空格"。
为了改进第二点,我建议实际更改实现,而不是使用第二个index
变量,使用指针迭代输出。还有其他可能性,但这种可能性的优点是不可能意外使用错误的变量进行索引。
综合起来,我们得到
char *remove_whitespace(const char *str) {
char *result = malloc(strlen(str) + 1);
char *out = result;
for (size_t i = 0; str[i] != ' '; i++) {
if (str[i] != ' ') {
*out++ = str[i];
}
}
*out = ' ';
return result;
}
我们还可以取消i
循环计数器。不幸的是,结果的可读性较低,而不是更多,因为我们需要在循环结束时递增str
,这将给我们留下一个难看的for (; *str != ' '; str++)
循环结构。
对于初学者来说,这个函数声明
char * remove_blank_spaces(char * string1) {
不正确,只会使函数的用户感到困惑。如果在函数中创建一个新的字符数组,则该参数应具有限定符const
。
char * remove_blank_spaces( const char * string1) {
否则,函数应"就地"更改原始字符串。
此电话
char * string2 = malloc(sizeof(string1));
也是不正确的。我想你的意思是
char * string2 = malloc( strlen( string1 ) + 1 );
但即使这个调用也不是很好,因为结果字符串可能比原始字符串少得多。
因此,首先您应该计算结果字符串中字符的numb er,然后才分配内存。
此断言也是不正确
的assert(remove_blank_spaces("a b") == "ab");
在此表达式中,有两个字符串的比较地址:第一个是函数返回的字符串,第二个是字符串文本。
即使你会写这样的表达式
assert( "ab" == "ab");
表达式的值可以等于逻辑 true 或 false,具体取决于编译器选项,该选项指定相等的字符串文本是存储为一个字符串文本还是占用不同的内存范围。
你应该写
assert( strcmp( remove_blank_spaces("a b"), "ab" ) == 0 );
考虑到在 if 语句中考虑 trhe 制表符字符't'
也是合理的,例如
if(string1[i] != ' ' && string1[i] != 't') {
或者您可以使用标准功能isblank
.
这是一个演示程序
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
char * remove_blank_spaces( const char *s )
{
size_t n = 0;
for ( size_t i = 0; s[i] != ' '; i++ )
{
if ( !isblank( ( unsigned char )s[i] ) ) ++n;
}
char *result = malloc( n + sizeof( ( char )' ' ) );
char *p = result;
do
{
if ( !isblank( ( unsigned char )*s ) )
{
*p++ = *s;
}
} while ( *s++ != ' ' );
return result;
}
int main(void)
{
const char *s1 = "a b";
char *s2 = remove_blank_spaces( s1 );
assert( strcmp( s1, s2 ) == 0 );
puts( s2 );
free( s2 );
return 0;
}
程序输出为
ab
请注意,您应该对变量index
和i
使用类型size_t
,而不是其他答案中显示的类型int
,因为它是与字符串长度和索引以及函数 malloc 一起使用的类型。类型int
不够大,无法存储字符串的大小。
如果你确实想声明像这样的函数
char * remove_blank_spaces( char *s )
也就是说,当参数没有限定符const
则不应在函数中动态分配新的字符数组,并且函数本身看起来可以简单得多。
这是一个演示程序。
#include <stdio.h>
#include <assert.h>
#include <string.h>
char * remove_blank_spaces( char *s )
{
char *destination = s;
char *source = s;
do
{
if ( *source != ' ' && *source != 't' )
{
*destination++ = *source;
}
} while ( *source++ != ' ' );
return s;
}
int main(void)
{
char s[] = "a b";
remove_blank_spaces( s );
assert( strcmp( s, "ab" ) == 0 );
puts( s );
return 0;
}
它的输出是
ab