如何反转字符串的单词,但只能反转字符和数字。例如:
this is the start!
siht si eht trats!
我已经编写了这段代码,但它反转了所有内容(也就是'!'); 我得到的输出是:
siht si eht !trats
代码:
#include<stdio.h>
void reverse(char *begin, char *end);
void reverseWords(char *s)
{
char *word_begin = s;
char *temp = s;
while(isalnum(*temp) || *temp )
{
temp++;
if (*temp == '\0')
{
reverse(word_begin, temp-1);
}
else if(*temp == ' ')
{
reverse(word_begin, temp-1);
word_begin = temp+1;
}
}
}
void reverse(char *begin, char *end)
{
char temp;
while (begin < end)
{
temp = *begin;
*begin++ = *end;
*end-- = temp;
}
}
int main()
{
char s[50];
scanf("%[^\n]",&s);
char *temp = s;
reverseWords(s);
printf("%s", s);
getchar();
return 0;
}
答案 0 :(得分:1)
您拥有的reverse()
功能是您需要的有用工具。许多传统版本依赖于仅传递文本的开头以进行反转,但是出于您的目的,将指针传递给要反转的范围的第一个和最后一个字符非常简洁。除了琐事之外我一直用它。我创建它static
因为我创建了每个函数(除了main()
)static
,除非有一个声明它的标题并且它被多个源文件使用 - 只有一个源文件这段代码。
然后,您需要做的就是确定文本中每个单词的开头和结尾。这通常最好用嵌套循环完成 - 一个在'未到达输入字符串的末尾',然后在其中,跳过非字母(非单词)字符,记录单词的开头,跳过字母(单词)字符,在开始和结束之间反转单词,并重复外循环。
这导致了这样的代码。
#include <ctype.h>
#include <stdio.h>
#include <string.h>
static void reverse(char *begin, char *end)
{
while (begin < end)
{
char temp = *begin;
*begin++ = *end;
*end-- = temp;
}
}
static void reverseWords(char *s)
{
while (*s != '\0')
{
while (*s != '\0' && !isalnum((unsigned char)*s))
s++;
char *word = s;
while (isalnum((unsigned char)*s))
s++;
reverse(word, s-1);
}
}
int main(void)
{
char s[1024];
while (fgets(s, sizeof(s), stdin) != 0)
{
s[strcspn(s, "\n")] = '\0';
printf("In: [%s]\n", s);
reverseWords(s);
printf("Out: [%s]\n", s);
}
return 0;
}
(unsigned char)
强制转换是在普通char
为签名类型的机器上正确处理单字节代码集(如ISO 8859-15)中的重音字符所必需的。
示例输出:
this is the start!
In: [this is the start!]
Out: [siht si eht trats!]
and this isn't the end.
In: [and this isn't the end.]
Out: [dna siht nsi't eht dne.]
Neither leading blanks nor trailing ones interfere
In: [ Neither leading blanks nor trailing ones interfere ]
Out: [ rehtieN gnidael sknalb ron gniliart seno erefretni ]
Lots..of=intermediate=punctuation@interruptions.com^give&no&&&trouble
In: [ Lots..of=intermediate=punctuation@interruptions.com^give&no&&&trouble ]
Out: [ stoL..fo=etaidemretni=noitautcnup@snoitpurretni.moc^evig&on&&&elbuort ]
请注意,如果您决定将撇号计为单词的一部分(因此“doesn't
”映射到"t'nseod"
而不是"nseod't"
,如上面的代码所示,您只需需要修复循环中的条件。那时,我可能会创建一个static inline
函数来完成这项工作:
static inline int is_word_char(int c)
{
return isalpha(c) || c == '\'';
}
请注意,<ctype.h>
会保留以is
(和to
)开头的单词,后跟小写字母;使用名称is_word_char()
可以避免使用此类保留字。此外,该函数被定义为采用int
,就像<ctype.h>
中的函数一样,以简单一致。
反向词功能变为:
static void reverseWords(char *s)
{
while (*s != '\0')
{
while (*s != '\0' && !is_word_char((unsigned char)*s))
s++;
char *word = s;
while (is_word_char((unsigned char)*s))
s++;
reverse(word, s-1);
}
}
甚至可以通过传递一个合适的指向函数来概括reverseWords()
:
static void reverseWords(char *s, int (*is_word)(int))
{
while (*s != '\0')
{
while (*s != '\0' && !is_word((unsigned char)*s))
s++;
char *word = s;
while (is_word((unsigned char)*s))
s++;
reverse(word, s-1);
}
}
现在你要从inline
删除is_word_char()
,因为你需要一个函数指针的实际函数,然后你可以使用:
reverseWords(s, isalnum);
reverseWords(s, is_word_char);
这种泛化程度的缺点是实际函数调用对每个字符进行分类的成本,失去了内联分类器函数的可能性。
我用reverseWords()
函数输入了这个答案的初步版本,如下所示:
static void reverseWords(char *s)
{
while (*s != '\0')
{
while (!isalnum((unsigned char)*s))
s++;
char *word = s;
while (isalnum((unsigned char)*s))
s++;
reverse(word, s-1);
}
}
区别在于!isalnum
循环 - 那里没有检查空字节。然后我意识到代码必须跳过空字节。像这样检测:
static void reverseWords(char *s)
{
while (*s != '\0')
{
while (/**s != '\0' &&*/ !isalnum((unsigned char)*s))
{
printf("= %d", *s);
s++;
}
putchar('\n');
char *word = s;
while (isalnum((unsigned char)*s))
s++;
reverse(word, s-1);
}
}
然后运行它“这是开始!”产出太多产量:
this is the start!
In: [this is the start!]
= 32
= 32
= 32
= 33= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= -49= 0= -24
= -48= 41= 96
= -122= 46
= -1= 127= 0= 0= -120= -124= 46
= -1= 127= 0= 0
…many lines omitted…
= -1= 127= 0= 0= -118= -113= 46
= -1= 127= 0= 0= -65= -113= 46
= -1= 127= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0
= 95
= 61= 46= 47
Out: [siht si eht trats!]
输出看起来很清醒 - 但代码却在各种不应该去的地方戳过。
只要空字节未通过“是字符”测试,修改后的代码就是安全的。
答案 1 :(得分:0)
我会使用ASCII表和if
函数来说:
&#39;只反转/移动数组的最后一个元素(字母){字} if
ASCII字符在65-90(大写字母),97-122(小写)和48-57之间(小数)&#39 ;.
如果你要在单词中加入符号,这可能会让你更加棘手,但我假设你不会因为你的例子永远不会有这样的符号!在一个单词的中间。
示例:
if ((int) s[i] == 33)
[特别是数组s
中的字符,位置i
碰巧是一个! (由ASCII表中的小数33表示。)]