【问题标题】:How can I reverse each word in a string?如何反转字符串中的每个单词?
【发布时间】:2019-12-04 15:16:31
【问题描述】:

我被限制不能使用来自<string.h> 的任何东西。

我想反转传递的字符串中的每个单词。

这是我目前所拥有的:

#include <stdio.h>

char * reversepPrint( char *name )
{
    char *normal = name, *reverse = name;

    while ( *reverse ) ++reverse;

    if ( normal < reverse )
    {
        for ( ; normal < --reverse; ++normal  )
        {
            char c = *normal;
            *normal = *reverse;
            *reverse  = c;
        }
    }

    return name;
}

int main( void ) 
{
    char s[] = "Simon liebt Pizza!";

    printf("%s", reversepPrint(s));

    return 0;
}

我的代码正在反转整个字符串,但我想要反转单个单词 - 所以这个例子的结果是"nomiS tbeil !azziP"

【问题讨论】:

  • 反转时,将字符保留在另一个数组中,直到找到一个空格。然后,再次反转第二个数组中的字符串以按顺序获取单词
  • 提示:link
  • 很多答案。只是为了好玩,这是我的:ideone.com/aE5MHU

标签: c string reverse


【解决方案1】:

我们需要分解成两个问题。我们已经有了一个问题的大部分解决方案(反转字符串);我们只需要让它与子字符串一起工作。我们主要通过删除找到字符串结尾的代码来做到这一点:

/* reverse substring [left, right) in-place */
void reverseSubstring(char *left, char *right)
{
    while (left < --right) {
        char c = *right;
        *right = *left;
        *left++ = c;
    }
}

问题的另一半是找到单词之间的界限。我们可以使用isspace() 将开始和结束指针定位在正确的位置,并用它们调用我们的reverseSubstring

#include <ctype.h>
char *reversepPrint(char *const name)
{
    char *start = name;
    char *end;

    while (*start) {
        while (*start && isspace(*start)) {
            ++start;
        }
        end = start;
        while (*end && !isspace(*end)) {
            ++end;
        }
        reverseSubstring(start, end);
        start = end;
    }

    return name;
}

如果你也被禁止使用&lt;ctype.h&gt;,那么为这个功能写一个你自己的简单isspace()并不难。


完整程序

/* reverse substring [left, right) in-place */
void reverse_substring(char *left, char *right)
{
    while (left < --right) {
        char c = *right;
        *right = *left;
        *left++ = c;
    }
}
    
#include <ctype.h>
/* reverse individual words in string */
/* word boundaries determined by isspace() */
char *reverse_words(char *const name)
{
    for (char *start = name, *end;  *start;  start = end) {
        while (*start && isspace(*start)) { ++start; }
        end = start;
        while (*end && !isspace(*end)) { ++end; }
        reverse_substring(start, end);
    }

    return name;
}

#include <stdio.h>
int main(void)
{
    char s[] = "Simon liebt Pizza!";
    printf("%s", reverse_words(s));
}

【讨论】:

  • 如何将所有内容放在一个我测试过的函数中,但我不能将 reverSubstring 函数放入 reversePrint();功能
  • 为什么要在一个函数中实现所有功能?那是可重复使用的,也更难理解!您可以做到这一点,但请记住,reverse_substring() 在此处获取其参数的 副本(并修改这些副本),因此如果您需要手动制作副本将其内联到reverse_words()。 IE。 char *left = start, *right = end;
【解决方案2】:

我会做以下事情:

  1. 创建一个仅反转字符串的n char 的函数
  2. 使用它来反转原始数组的单词。
  3. 单词很容易识别,因为它们是非空字符和非空格字符块。

类似下面的东西应该可以工作(注意我没有测试代码)并产生以下输出:nomiS tbeil !azziP

//this is basically your original function
char * reverse_n( char *name, const int  len )
{
    char *normal = name, *reverse = name+len;

    if ( normal < reverse )
    {
        for ( ; normal < --reverse; ++normal  )
        {
            char c = *normal;
            *normal = *reverse;
            *reverse  = c;
        }
    }

    return name;
}

char * my_reverse( char *nname)
{
    char* name=nname;
    while(*name)
    {
        char* next = name;
        int l = 0;
        //find the next word and its length
        while(*next && *next!=' '){
            next++;
            l++;
        }
        //reverse it
        reverse_n(name, l);
        name=next;
        //skip the space
        if(*name)
            name++;
    }
    return nname;
}

【讨论】:

  • 但我的问题是我不能使用 String.h 作为库。
  • 我没用过。
  • 从哪里获得 reverse_n() 函数?
  • @SimonMayrhofer 它位于代码 sn-p 的顶部。
  • 我怎样才能把所有东西都放在一个函数中,因为我必须把它放在一个函数中。最后一个问题是我如何保持大写和小写,所以当我有 Simon 并且我想将其反转为 Nomis 时!
【解决方案3】:

你的函数 reversepPrint 反转一个字符串。

由于您想按单词反转,因此您必须解析字符串才能将函数 reversepPrint 应用于每个单词。为此,您可以使用空格字符作为分隔符。

【讨论】:

    【解决方案4】:

    这是我在不使用 string.h

    的情况下对逻辑所做的一点努力
    #include <stdio.h>
    
    char * reversepPrint( char *name )
    {
    
        char *normal = name, *reverse = name;
    
        while ( *reverse ) ++reverse;
    
        if ( normal < reverse )
        {
            for ( ; normal < --reverse; ++normal  )
            {
                char c = *normal;
                *normal = *reverse;
                *reverse  = c;
            }
        }
    
        return name;
    }
    
    int main( void ) 
    {
        char s[] = "Simon liebt Pizza!";
        int i;
        int num_of_spaces = 0;
    
        int length = 0;
    
        char *temp = &s;
    
        while(*temp!='\0'){
            temp++;
        }
        length = temp - s;
    
    
        for (i = 0; i<length; i++)
        {
    
            if (s[i]==' ')
            {
                num_of_spaces++;
            }
        }
    
        char x[num_of_spaces+1][100];
        i = 0;
        int index = 0,index1 = 0, k = 0;
        for(i = 0; i < length; i++)
        {
            if(s[i]!=' ')
            {
                x[k][index] = s[index1];
                index++;
    
            }else{
    
                x[k][index] = '\0';
                index = 0;
                k++;
    
            }
            index1++;
        }
    
        i = 0;
        for(i = 0; i<=num_of_spaces; i++)
        {
            printf("%s\n",reversepPrint(x[i]));
        }
    
    
    
        return 0;
    }
    

    这就是代码的作用

    • 给定任何字符串,它会在不使用 strlen 的情况下找到它的长度
    • 然后,代码将找到字符串的总数(它们之间的空格)
    • 之后,我将创建一个维度为 [strings][100] 的二维数组(每个字符串的长度为 100)
    • 将内容分别复制到每个字符串
    • 然后循环遍历二维数组并调用该方法。

    【讨论】:

    • 当你在一个单词很长的字符串上使用它时会发生什么?每个单词似乎有 100 个字符的硬性限制,没有检查溢出。
    • 好吧,我们可以稍微修改一下以迎合这种情况。在大多数情况下,在学习阶段保持固定长度就足够了。
    【解决方案5】:

    这是一个使用一些嵌套循环的版本:

    #include <ctype.h>
    
    char * reversepPrint( char *name )
    {
        char *s = name;
    
        while (*s)
        {
            char *t = s;
    
            /* Find end of non-space character sequence. */
            while (*t && *t == (unsigned char)*t && !isspace(*t))
            {
                t++;
            }
            if (t - s > 1)
            {
                /* Got a non-space character sequence of length > 1. */
                char *e = t;
    
                /* Reverse the non-space character sequence. */
                do
                {
                    char tmp = *s;
    
                    *s++ = *--e;
                    *e = tmp;
                } while (s < e);
    
                /* Start past non-space characters for next iteration. */
                s = t;
            }
            else
            {
                /* Skip space or singleton non-space. */
                s++;
            }
        }
    
        return name;
    }
    

    变量s 用于在外部while 循环的每次迭代中前进通过name 字符串。变量t 在外部循环的每次迭代中被初始化为s,然后由内部while (*t &amp;&amp; ...) 循环推进超过任何非空格字符。在将t 推进到任何非空格字符之后,非空格字符序列的长度为t - s。 (如果*s是一个空格字符,那么这个长度将为0。)如果这个长度大于1,它使用内部do { ... } while循环来反转非空格字符的序列,然后分配s = t准备好用于外循环的下一次迭代。否则,*s 要么是空格字符,要么是单例非空格字符,因此s 在外循环的下一次迭代中前移一个字符。

    【讨论】:

    • 我怎样才能改变大写和小写,所以一个单词的第一个字母总是大写,其他的都是小写。我尝试了很多想法,但无法达到目标。
    • 我怎样才能找到单词中的第一个字符以便结果是 Nomis Tbeil Azzip!
    • @SimonMayrhofer 这可以在单独的函数中完成。它可能需要不同的规则来确定“单词”的开头和结尾(例如,使用任何非字母字符作为单词分隔符)。
    【解决方案6】:

    试试这个逻辑,将字符串中的单个单词一个一个反转,例如如果字符串是“我喜欢编程”,则在反转单个单词后字符串应该是“i ekil gnimmargorp”。

    我希望这段代码 sn-p 有帮助

    void reverse(char* begin, char* end) 
    { 
        char temp; 
        while (begin < end) { 
            temp = *begin; 
            *begin++ = *end; 
            *end-- = temp; 
        } 
    } 
    
    // Function to reverse words 
    void reverseWords(char* s) 
    { 
        char* begin = s; 
    
        char* temp = s;  
        while (*temp) { 
            temp++; 
            if (*temp == '\0') { 
                reverse(begin, temp - 1); 
            } 
            else if (*temp == ' ') { 
                reverse(begin, temp - 1); 
                begin = temp + 1; 
            } 
        } 
    } 
    

    【讨论】:

    • 但期望和预期的输出是"i ekil gnimmargorp"
    猜你喜欢
    • 1970-01-01
    • 2013-11-13
    • 1970-01-01
    • 2014-01-01
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    相关资源
    最近更新 更多