反转字符串中的单词

时间:2015-09-16 17:40:27

标签: c string reverse sentence strncpy

我要反转字符串中的单词。我觉得自己正朝着正确的方向前进。但我一直得到不稳定的输出并且无法帮助,但认为它与我的strncat()函数有关。你有没有看到任何问题,我决定处理它。我对其他方法的建议持开放态度。

int main()
{
  int ch, ss=0, s=0;
  char x[3];
  char *word, string1[100], string2[100], temp[100];
  x[0]='y';

  while(x[0]=='y'||x[0]=='Y')
  {
    printf("Enter a String: ");
    fgets(string1, 100, stdin);
    if (string1[98] != '\n' && string1[99] == '\0') { while ( (ch = fgetc(stdin)) != EOF && ch != '\n'); }

    word = strtok(string1, " ");

    while(word != NULL)
    {
      s = strlen(word);
      ss=ss+s;

      strncpy(string2, word, s);
      strncat(string2, temp, ss);
      strncpy(temp, string2, ss);

      printf("string2: %s\n",string2);
      printf("temp: %s\n",temp);      
      word = strtok(NULL, " ");
    }

    printf("Run Again?(y/n):");
    fgets(x, 2, stdin);
    while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
  }

  return 0;
}

这是我的输出:

Enter a String: AAA BBB CCC DDD EEE

string2: AAA
temp: AAA

string2: BBBAAA
temp: BBBAAA

string2: CCCAAABBBAAA
temp: CCCAAABBB

string2: DDDAAABBBAAACCCAAABBB
temp: DDDAAABBBAAA

string2: EEE
AABBBAAACCCAAABBBDDDAAABBBAAA
temp: EEE
AABBBAAACCCA

3 个答案:

答案 0 :(得分:1)

您需要初始化" 至少" strcat()个参数的第一个字节,因为它希望它的参数被nul终止,所以

string2[0] = '\0';

会有所帮助,但您第一次不需要strcat(),而是可以使用strcpy()

答案 1 :(得分:0)

您未在strncpy来电中复制足够的字符。

从手册页:

  

strncpy()函数类似,但不超过n个字节   src的副本被复制。因此,如果前n个中没有空字节   src的字节,结果不会以空值终止。

由于您指定了字符串的确切长度,因此不会附加NULL终止字节。

您需要为每个添加1:

  strncpy(string2, word, s+1);
  strncat(string2, temp, ss);   // strncat always NULL terminates
  strncpy(temp, string2, ss+1);

输出:

Enter a String: aaa bbb ccc ddd eee

string2: aaa
temp: aaa
string2: bbbaaa
temp: bbbaaa
string2: cccbbbaaa
temp: cccbbbaaa
string2: dddcccbbbaaa
temp: dddcccbbbaaa
string2: eee
dddcccbbbaaa
temp: eee
dddcccbbbaaa

最后一次迭代的分割线是因为fgets将换行符留在缓冲区的末尾。您可以在分隔符列表中将\n包含到strtok

来跳过它
word = strtok(string1, " \n");
...
word = strtok(NULL, " \n");

答案 2 :(得分:0)

确定您是否真的尝试:

相当困难
  

反转字符串中的单词

反转字符串

如果你只是试图反转整个字符串,那么将字符串分成标记是没有多大意义的,当你需要做的只是以相反的顺序写原文时。

以表面值的形式提出您的请求,可能更容易简单地使用开始指针'p'和结束指针'ep'向下走,并在找到时反转两个指针之间的内容带有space的{​​{1}}。换句话说,降低原始字符串的新副本,并使用'ep'指向每个单词的开头,当'p'指向该单词末尾的空格(或字符串结尾)时,只需反转字符就地即可。这将消除所有复制和连接。

一种在原地反转字符的方法是:

'ep'

<强>输出

#include <stdio.h>
#include <string.h>

void strprev (char *begin, char *end);

int main (int argc, char **argv) {

    if (argc < 2) return 1;
    size_t len = strlen (argv[1]);

    char *p, *ep;
    char rev[len + 1]; /* a VLA is fine here   */

    strncpy (rev, argv[1], len + 1);     /* copy string to rev       */
    p = ep = rev;

    for (;;) {  /* for every char in rev */

        if (*ep && *ep != '\n') {        /* if not at end of rev, and */
            if (*ep == ' ' && ep > p) {  /* if ' ' and chars between  */
                strprev (p, ep - 1);     /* reverse between p and ep  */
                p = ep + 1;              /* advance p to next word    */
            }
        }
        else {  /* handle last word in rev */
            if (ep > p)
                strprev (p, ep - 1);
            break;
        }
        ep++;
    }

    printf ("\n string  : %s\n reverse : %s\n\n", argv[1], rev);

    return 0;
}

/** strprev - reverse string given by begin and end pointers.
*  Takes valid string and swaps src & dest each iteration.
*  The original string is not preserved.
*  If str is not valid, no action taken.
*/
void strprev (char *begin, char *end)
{
    char tmp;

    if (!begin || !end) {
        printf ("%s() error: invalid begin or end\n", __func__);
        return;
    }

    while (end > begin)
    {
        tmp = *end;
        *end-- = *begin;
        *begin++ = tmp;
    }
}

注意:如果您需要处理(跳过)单词之间的多个空格,则需要在上面的代码中指定$ ./bin/strrevex_a "ABC DEF GHI JKL MNO" string : ABC DEF GHI JKL MNO reverse : CBA FED IHG LKJ ONM 之前跳过它们。

如果你实际上试图反转整个字符串,那就容易多了。让我知道哪一个是正确的目标,如果需要,我会进一步帮助。