简体   繁体   English

反转字符串中的单词

[英]Reversing words within a string

I am to reverse the words within a string. 我要反转字符串中的单词。 I feel like I'm headed in the right direction. 我觉得自己朝着正确的方向前进。 But I keep getting wonky output and cant help but think it has to do with my strncat() function. 但是我一直在输出不稳定的输出,但我不禁认为这与我的strncat()函数有关。 Do any of you see any issues with out I've decided to handle it. 你们有没有看到我决定处理的任何问题。 I'm open to suggestion on other ways to do it. 我愿意就其他方式提出建议。

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;
}

This is my output: 这是我的输出:

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

You need to initialize " at least " the first byte of strcat() parameters, because it expects it's parameters to be nul terminated, so 您需要初始化“ 至少strcat()参数的第一个字节,因为它期望其参数以nul结尾,所以

string2[0] = '\0';

would help, but you don't need strcat() for the first time, you can use strcpy() instead. 会有所帮助,但是您第一次不需要strcat() ,可以改用strcpy()

You're not copying enough characters in your strncpy calls. 您在strncpy调用中没有复制足够的字符。

From the man pages: 从手册页:

The strncpy() function is similar, except that not more than n bytes of src are copied. strncpy()函数与之类似,只是复制的src字节数不超过n个。 Thus, if there is no null byte among the first n bytes of src, the result will not be null-terminated. 因此,如果src的前n个字节中没有空字节,则结果将不会以空值结尾。

Since you're specifying the exact length of the string, no NULL terminating byte is appended. 由于您要指定字符串的确切长度,因此不会附加NULL终止字节。

You need to add 1 to each of these: 您需要将以下各项加1:

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

Output: 输出:

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

The split line on the last iteration is because fgets leaves the newline at the end of the buffer. 上一次迭代的分割线是因为fgets将换行符留在缓冲区的末尾。 You can skip over it by including \\n in the delimiter list to strtok : 您可以通过在分隔符列表中包含\\nstrtok来跳过它:

word = strtok(string1, " \n");
...
word = strtok(NULL, " \n");

It is rather difficult to determine whether you are actually attempting to: 确定您是否实际上正在尝试:

reverse the words within a string 反转字符串中的单词

or reverse the string . 反转字符串

If you are simply trying to reverse the whole string, then it wouldn't make much sense to separate the string into tokens when all you would need to do is write the original in reverse order. 如果您只是想反转整个字符串,那么当您需要做的就是以相反的顺序写入原始字符串时,将字符串分成标记就没有多大意义。

Taking your request at face value, it may be easier to simply walk down the string with a start-pointer 'p' and end-pointer 'ep' and reverse what is between the two pointers when you find a space with 'ep' . 以您的要求为准,使用起点指针'p'和终点指针'ep'沿字符串向下移动并在找到带有'ep'space时反转两个指针之间的含义可能会更容易。 In other words step down the new copy of the original string and with 'p' pointing to the beginning of each word and when 'ep' points to the space at the end of that word (or end of string), simply reverse the characters in-place . 换句话说,下移原始字符串的新副本,并用'p'指向每个单词的开头,当'ep'指向该单词末尾(或字符串末尾)的空格时,只需反转字符就地 That would eliminate all the copying and concatenation. 这将消除所有复制和连接。

One approach to reversing the characters in-place would be something like: 一种就地反转字符的方法如下:

#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;
    }
}

Output 输出量

$ ./bin/strrevex_a "ABC DEF GHI JKL MNO"

 string  : ABC DEF GHI JKL MNO
 reverse : CBA FED IHG LKJ ONM

Note: if you need to handle (skip) multiple spaces between the word, then they would need to be skipped before you assign p = ep + 1; 注意:如果您需要处理(跳过)单词之间的多个空格,那么在分配p = ep + 1;之前,需要先跳过它们p = ep + 1; in the code above. 在上面的代码中。

If you are actually trying to reverse the entire string, that is quite a bit easier. 如果您实际上是在尝试反转整个字符串,那会容易得多。 Let me know which one is the correct goal and I'll help further if needed. 让我知道哪个是正确的目标,如有需要,我会进一步提供帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM