C 消除字符串中的所有多余空格

C 消除字符串中的所有多余空格,c,C,函数必须消除单词和标点符号之间的所有额外空格,但标点符号与前面的单词之间不得有任何空格 例如,我有以下字符串: Hey ,how are you today ? 我应该得到这个: Hey, how are you today? 此函数消除了此处的额外空间。但是我不知道怎么加标点符号 顺便说一句,我正在主函数中校准此函数 void space_rule(char *str[]){ printf("Enter a string: "); gets(*str);

函数必须消除单词和标点符号之间的所有额外空格,但标点符号与前面的单词之间不得有任何空格

例如,我有以下字符串:

Hey   ,how   are you today    ?
我应该得到这个:

Hey, how are you today?
此函数消除了此处的额外空间。但是我不知道怎么加标点符号

顺便说一句,我正在主函数中校准此函数

void space_rule(char *str[]){
printf("Enter a string: ");
gets(*str);
puts(*str);

char *p = strtok(*str, " ");
    while(*p!=NULL){
    printf("%s ",p);
    p=strtok(NULL, " ");
}

}
考虑:

#include <stdio.h>
#include <ctype.h>

int main()
{
    const char* input = "Hey   ,how   are you today    ?" ;
    const char* chp = input ;
    
    // While not end of input...
    while( *chp != '\0' )
    {
        
        // Print all regular characters (not space or punctuation)
        if( !(isspace( *chp ) || ispunct( *chp )) )
        {
            putchar( *chp ) ;
            chp++ ;
        }
        // Print all punctuation followed by a space (except at end)
        else if( ispunct( *chp ) )
        {
            putchar( *chp ) ;
            chp++ ;
            if( *chp != '\0' && !isspace( *chp ) )
            {
                putchar( ' ' ) ;
            }
        }
        // Is space...
        else if( isspace( *chp ) )
        {
            // Skip all space
            while( *chp != '\0' && isspace( *chp ) )
            {
                chp++ ;
            }
            
            // If not end, and not punctuation...
            if( *chp != '\0' && !ispunct( *chp ) )
            {
                // ...insert single space 
                putchar( ' ' ) ;
            }
        }
    }
    
    return 0;
}

输出为:

She said" Hello"  
这是不可能的。为此,您不仅需要为“”包含一条例外规则,还需要说明开始和结束引号,并相应地应用该规则。这是一个读者练习-如果您仍然坚持这一点,我建议您发布一个新问题

如果您有一个字符串,例如:

She said, "Hey, how are, you today?"
因为你有
在一起,对于
你需要一条规则:“除非下一个字符也是标点符号,否则在标点符号后加空格”。但是,如果
以空格分隔,那么在做出决定之前,您必须首先消除空格。老实说,我放弃了尝试找出所有排列。我建议,如果您想这样做,您可以一次应用一个规则在多个过程中执行转换,例如:

  • 将所有多个空间减少为1个空间
  • 如果标点符号后没有空格,且不是一个完整的开口(
  • 删除标点符号之间的空格
  • 如果没有空格,请在打开报价前插入空格

  • 通过使用更简单的规则(在单独的函数中执行)和多个过程,将更容易以牺牲效率为代价获得正确的结果。您还可以轻松地重新排序规则的应用程序,以获得预期的结果。例如,规则4必须在规则3之后应用。

    您想要的更改都可以表示为基于每对相邻字符类型的更改。您需要将每个字符描述为空格、字母或标点符号,并按如下方式处理成对字符:

    • :删除一个(第一个?)空格
    • :删除空格
    • :在它们之间插入空格
    • 否则:别管它
    由于这些对规则从未对对对中的第二个字符执行任何操作,因此建议执行一个简单的循环,将字符从输入缓冲区复制到输出缓冲区,同时执行这些更改:

    void copy_and_fix(char *out, const char *in) {
        while (*in) {
            if (isspace(in[0]) && isspace(in[1])) {
                // don't copy the first space
            } else if (isspace(in[0]) && ispunct(in[1])) {
                // don't copy the space
            } else if (ispunct(in[0]) && iswordchar(in[1])) {
                // keep the punct and insert a space;
                *out++ = *in;
                *out++ = ' ';
            } else {
                // just copy the character
                *out++ = *in;
            }
            ++in;
        }
        *out = '\0';  // NUL terminate the output.
    }
    

    当然,您需要注意缓冲区的大小,以确保不会溢出输出缓冲区,但这可以通过多种方式处理(确保输出缓冲区至少是输入大小的1.5倍,或者传递大小并在必要时截断输出,或者在堆上分配输出缓冲区并根据需要调整大小).

    您的示例结果显示,您还希望在
    之后添加空格。是吗?立即停止使用
    get()
    !什么是“第一部分”?这就是代码的结果——也要清楚地表明这一点。顺便说一句,你的解决方案太复杂了。你在传递什么
    str
    和一个参数?@Barmar是的。标点符号和下一个单词开头之间需要的空格。如果检索到空格,请遍历字符串并将标志设置为true。如果标志为true,则跳过当前字符,否则将其写入字符串的当前写入(!)位置。如果获得的字符不是空格,请将标志设置为false。因此,您必须处理两个索引(一个写入和一个读取),不要忘记在字符串末尾设置
    \0
    void copy_and_fix(char *out, const char *in) {
        while (*in) {
            if (isspace(in[0]) && isspace(in[1])) {
                // don't copy the first space
            } else if (isspace(in[0]) && ispunct(in[1])) {
                // don't copy the space
            } else if (ispunct(in[0]) && iswordchar(in[1])) {
                // keep the punct and insert a space;
                *out++ = *in;
                *out++ = ' ';
            } else {
                // just copy the character
                *out++ = *in;
            }
            ++in;
        }
        *out = '\0';  // NUL terminate the output.
    }