我要反转字符串中的单词。我觉得我的方向是对的。但是我一直得到不稳定的输出,我忍不住想这和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] == ' ') { 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: %sn",string2);
printf("temp: %sn",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
您需要初始化"至少" strcat()
参数的第一个字节,因为它期望它的参数以nul
终止,所以
string2[0] = ' ';
会有帮助,但您第一次不需要strcat()
,您可以使用strcpy()
代替。
您在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
在缓冲区的末尾留下了换行符。您可以通过在strtok
:
n
来跳过它。word = strtok(string1, " n");
...
word = strtok(NULL, " n");
很难判断你是否真的在尝试:
反转字符串
中的单词
或反转字符串。
如果你只是想反转整个字符串,那么把字符串分成标记就没有多大意义了,因为你所需要做的就是把原来的字符串倒序写出来。
从表面上看,简单地用开始指针'p'
和结束指针'ep'
沿着字符串向下走,并在找到space
和'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 : %sn reverse : %snn", 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 endn", __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
注意:如果你需要处理(跳过)单词之间的多个空格,那么在上面的代码中分配p = ep + 1;
之前,它们需要被跳过。
如果你真的想要反转整个字符串,那就简单多了。让我知道哪一个是正确的目标,如果需要,我会进一步帮助你。