在C语言中,最简单、最有效的去除字符串空格的方法是什么?
最容易和最有效往往不会同时发生...
这里有一个可能的原地删除解决方案:
void remove_spaces(char* s) {
char* d = s;
do {
while (*d == ' ') {
++d;
}
} while (*s++ = *d++);
}
RemoveSpaces("blah");
而不是 char a[] = "blah"; RemoveSpaces(a);
,那么这将产生未定义的行为。但这并不是代码的问题。不建议将只读字符串传递给文档记录为修改传递给它的字符串(例如删除空格)的函数。;-) - Steve Jessop从发布的答案中可以看出,这并不是一个微不足道的任务。面对这样的任务,许多程序员似乎选择抛弃常识,以产生他们可能想得出的最隐晦的代码片段。
需要考虑的事情:
' '
。我会做什么:
void remove_spaces (char* restrict str_trimmed, const char* restrict str_untrimmed)
{
while (*str_untrimmed != '\0')
{
if(!isspace(*str_untrimmed))
{
*str_trimmed = *str_untrimmed;
str_trimmed++;
}
str_untrimmed++;
}
*str_trimmed = '\0';
}
在这段代码中,“str_untrimmed”源字符串没有被修改,这是通过适当的常量性保证的。如果源字符串仅包含空终止符,则不会崩溃。它总是将目标字符串以空终止。
内存分配留给调用方。算法应该只关注它的预期工作。它会删除所有的空格。
代码中没有微妙的技巧。它不会尝试在单行上挤入尽可能多的操作符。它将成为IOCCC的一个非常糟糕的候选者。然而它将产生几乎与更晦涩的单行版本相同的机器代码。
当复制某些东西时,你可以通过将两个指针声明为“restrict”,从而进行一些优化。这是程序员和编译器之间的契约,程序员保证目标和源不是同一地址。这样更有效率的优化,因为编译器可以直接从源复制到目标,而不需要中间的临时内存。
restrict
关键字?你完全可以将同一个指针作为源和目的地进行传递,而且你的代码也支持这样做。 - chqrliestr_untrimmed
替换为 scattered
,将 str_trimmed
替换为 condensed
。 - Wolf以下是一个非常简洁但完全正确的版本:
do while(isspace(*s)) s++; while(*d++ = *s++);
以下是一些我自己为了好玩而缩短的代码,它们并不完全正确,会引起评论者的不满。
如果你可以冒一些未定义行为的风险,并且永远没有空字符串,那么你可以省略掉函数体:
while(*(d+=!isspace(*s++)) = *s);
天啊,如果您说的“space”只是指空格字符:
while(*(d+=*s++!=' ')=*s);
不要在生产环境中使用那个 :)
char *str = strdup(" a b c ");
char *write = str, *read = str;
do {
if (*read != ' ')
*write++ = *read;
} while (*read++);
printf("%s\n", str);
其他字符串是只读的,例如在代码中声明的字符串。您需要将这些字符串复制到新分配的内存区域,并通过跳过空格来填充副本:
char *oldstr = " a b c ";
char *newstr = malloc(strlen(oldstr)+1);
char *np = newstr, *op = oldstr;
do {
if (*op != ' ')
*np++ = *op;
} while (*op++);
printf("%s\n", newstr);
while (*(op++))
而不是 while (*(++op))
。 - Andomar#include <ctype>
char * remove_spaces(char * source, char * target)
{
while(*source++ && *target)
{
if (!isspace(*source))
*target++ = *source;
}
return target;
}
注意事项;
isspace
的值转换为 unsigned char
,因为该函数被定义为接受在 unsigned char
范围内或 EOF 值。 - caftarget
的第一个元素包含'\0'调用它将失败(我不明白检查其内容的目的是什么)。将while(*source++ && *target) {...}
更改为do {...} while(*source++);
似乎可以正常工作。 - mMontuctype.h
? - Spikatrixreturn target;
返回目标; - BLUEPIXYvoid removeSpaces(char *str1)
{
char *str2;
str2=str1;
while (*str2==' ') str2++;
if (str2!=str1) memmove(str1,str2,strlen(str2)+1);
}
#include <stdio.h>
int main(void) {
for (;;) {
int c = getchar();
if (c == EOF) { break; }
if (c == ' ') { continue; }
putchar(c);
}
}
#include<stdio.h>
#include<string.h>
main()
{
int i=0,n;
int j=0;
char str[]=" Nar ayan singh ";
char *ptr,*ptr1;
printf("sizeof str:%ld\n",strlen(str));
while(str[i]==' ')
{
memcpy (str,str+1,strlen(str)+1);
}
printf("sizeof str:%ld\n",strlen(str));
n=strlen(str);
while(str[n]==' ' || str[n]=='\0')
n--;
str[n+1]='\0';
printf("str:%s ",str);
printf("sizeof str:%ld\n",strlen(str));
}
strlen
函数返回size_t
类型的值。因此请使用%zu
而不是%ld
。同时,请使用int main()
作为程序入口,并在结尾处加上return 0;
语句。 - Spikatrixmemcpy
不适用于复制重叠的内存区域。请使用 memmove
。 - autistic/* Function to remove all spaces from a given string.
https://www.geeksforgeeks.org/remove-spaces-from-a-given-string/
*/
void remove_spaces(char *str)
{
int count = 0;
for (int i = 0; str[i]; i++)
if (str[i] != ' ')
str[count++] = str[i];
str[count] = '\0';
}
count
和 i
的类型更改为 size_t
,您将拥有一个干净且稳健的解决方案。 - chqrlie代码取自zString库
/* search for character 's' */
int zstring_search_chr(char *token,char s){
if (!token || s=='\0')
return 0;
for (;*token; token++)
if (*token == s)
return 1;
return 0;
}
char *zstring_remove_chr(char *str,const char *bad) {
char *src = str , *dst = str;
/* validate input */
if (!(str && bad))
return NULL;
while(*src)
if(zstring_search_chr(bad,*src))
src++;
else
*dst++ = *src++; /* assign first, then incement */
*dst='\0';
return str;
}
代码示例
Exmaple Usage
char s[]="this is a trial string to test the function.";
char *d=" .";
printf("%s\n",zstring_remove_chr(s,d));
Example Output
thisisatrialstringtotestthefunction
看一下 zString 代码,你可能会发现它很有用 https://github.com/fnoyanisi/zString
strpbrk
而是使用自己编写的版本呢?而且,常量正确性在哪里呢? - Lundinif
语句可以被移除,检查可以在 for
循环的逻辑测试部分中完成,谢谢你的建议,我会研究一下......>> 为什么不使用标准的 strpbrk
而要使用自己编写的版本?只是为了好玩而编写了这个代码(整个 zString 的东西),并尽量不使用标准函数。所以,可以说这是一个 _有趣的项目_,但这当然不应该阻止任何人贡献代码。 - fnisizstring_search_chr
不会返回 chr 的索引,它的 char*
参数应该是 const
限定的。函数 zstring_remove_chr
效率相当低下。 - chqrliezstring_remove_chr()
函数的注释和代码。我很想看到你更高效的版本或者一些建议。谢谢。 - fnisi