我尝试创建一个C函数,从字符串中删除所有不必要的空格。举个例子:
Hi my name is Leon .
在函数调用之后,它应如下所示:
Hi my name is Leon.
但是我的程序总是在最后一个单词后面留一个空格,所以它看起来像这样:
Hi my name is Leon .
有关如何修复的任何想法? 这是代码:
char *DeleteSpaces(char *str) {
int blank = 1;
char *poc, *start = str, *q;
q = str;
while (*q == ' ') q++;
poc = str;
while (*poc++ = *q++);
while (*str != '\0') {
q = str;
if (*str == ' ') {
if ((blank >= 1 && *(str-1) == ' ')) {
poc = str;
while (*poc == ' ') {
poc++;
}
q = str;
while(*poc != '\0') {
*q++ = *poc++;
}
*q = '\0';
blank = 0;
}
blank++;
}
else if (blank == 1)
blank = 0;
str++;
}
str--;
if (str == ' ') *str = '\0';
return start;
}
答案 0 :(得分:2)
从字符串中删除空格时,需要考虑许多微妙的问题。一个重要问题是保留指向原始开头的指针,因此如果原始动态分配,您不会失去free
内存的能力从而导致内存泄漏。
其次,您有三个基本的重建索引考虑因素:(1)前导空格; (2)交错空白; (3)结束后的空格。 (加上你想要构建的任何自定义案例,比如在'.'
之前修剪任何空格)。你可以在日常工作中按顺序接受它们。
虽然您现在只是查看' '
(space
)字符,但您没有理由不同时处理所有空白。 ctype.h
标头提供了isspace
函数(宏)来做到这一点。
将这些部分放在一起,您可以执行以下操作rmxws
(删除多余的空格):
char *rmxws (char *s)
{
if (!s) return NULL; /* valdiate string not NULL */
if (!*s) return s; /* handle empty string */
char *p = s, *wp = s; /* pointer and write-pointer */
while (*p) {
if (isspace(*p)) { /* test for ws */
if (wp > s) /* ignore leading ws, while */
*wp++ = *p; /* preserving 1 between words */
while (*p && isspace (*p)) /* skip remainder */
p++;
if (!*p) /* bail on end-of-string */
break;
}
if (*p == '.') /* handle space between word and '.' */
while (wp > s && isspace (*(wp - 1)))
wp--;
*wp++ = *p; /* use non-ws char */
p++;
}
while (wp > s && isspace (*(wp - 1))) /* trim trailing ws */
wp--;
*wp = 0; /* nul-terminate */
return s;
}
将它与一个简短的例子放在一起,您可以按如下方式进行测试:
#include <stdio.h>
#include <ctype.h>
char *rmxws (char *s);
int main (int argc, char **argv) {
char *s = argc > 1 ? argv[1] : (char []){ " Testing 1 2 3. . . "};
printf ("\n original : '%s'\n", s);
printf (" trimmed : '%s'\n\n", rmxws (s));
return 0;
}
char *rmxws (char *s)
{
if (!s) return NULL; /* valdiate string not NULL */
if (!*s) return s; /* handle empty string */
char *p = s, *wp = s; /* pointer and write-pointer */
while (*p) {
if (isspace(*p)) { /* test for ws */
if (wp > s) /* ignore leading ws, while */
*wp++ = *p; /* preserving 1 between words */
while (*p && isspace (*p)) /* skip remainder */
p++;
if (!*p) /* bail on end-of-string */
break;
}
if (*p == '.') /* handle space between word and '.' */
while (wp > s && isspace (*(wp - 1)))
wp--;
*wp++ = *p; /* use non-ws char */
p++;
}
while (wp > s && isspace (*(wp - 1))) /* trim trailing ws */
wp--;
*wp = 0; /* nul-terminate */
return s;
}
示例使用/输出
$ ./bin/trimxsws " Hi my name is Leon . "
original : ' Hi my name is Leon . '
trimmed : 'Hi my name is Leon.'
或只是
$ ./bin/trimxsws
original : ' Testing 1 2 3. . . '
trimmed : 'Testing 1 2 3...'
仔细看看,如果您有任何其他问题,请告诉我。
答案 1 :(得分:1)
考虑到只有当非空格字符跟在非前导空格时,才需要在dest
中保存空格。简化循环。
char *DeleteSpaces(char *str) {
char *start = str;
char *dest = str;
// skip leading spaces
while (*str == ' ') str++;
char previous = 0;
char ch;
while ((ch = *str++) != '\0') {
if (ch != ' ') {
if (previous == ' ') {
*dest++ = previous;
}
*dest++ = ch;
}
previous = ch;
}
*dest = '\0';
return start;
}
答案 2 :(得分:0)
以下代码
现在是代码
#include <ctype.h>
char *DeleteSpaces(char *str)
{
char * src = str;
char * dest = str;
int inBlank = 0;
while( *src )
{
if ( isalpha( *src ) )
{
*dest = *src;
dest++;
src++;
inBlank = 0;
}
else if( ispunct(*src) )
{
if( inBlank )
{
dest--;
}
*dest = *src;
dest++;
src++;
inBlank = 0;
}
else if( isspace( *src ) )
{
if( inBlank )
{
src++;
}
else
{
inBlank =1;
*dest = *src;
dest++;
src++;
}
}
}
*dest = '\0';
return str;
}