我试图改变句子中单词的顺序,例如:
这句话是相反的。
变为
反转。是单词句子这个
这是我到目前为止所做的,几乎可以工作: 我使用strrev函数来反转字符串,然后使用inprev函数将每个单词单独发送到strrev函数,将它们反转回原始方向,但顺序相反。 发送指向strrev函数的开始和结束的指针可能看起来有点傻,但它允许在inprev()中使用相同的函数,发送指向单个单词的开头和结尾的指针。
#include <stdio.h>
#include <string.h>
void strrev(char * start, char * end);
void inprev(char * start);
int main(void)
{
char str[] = "Foobar my friends, foobar";
char * end = (str + strlen(str) -1);
puts(str);
strrev(str, end);
puts(str);
inprev(str);
puts(str);
return 0;
}
void strrev(char * start, char * end)
{
char temp;
while (end > start)
{
temp = *start;
*start = *end;
*end = temp;
start++;
end--;
}
}
void inprev(char * start)
{
char * first = start;
char * spcpnt = start;
while (*spcpnt)
{
while (*spcpnt != ' ' && *spcpnt)
spcpnt++;
strrev(start, spcpnt-1); // removing the -1 sends the space on the
start = spcpnt++; // other side to be reversed, doesn't stop
// the problem.
}
}
这是输出:
Foobar我的朋友,foobar
raboof,sdneirf ym rabooF
foobarfriends,我的Foobar
问题是在最后一个单词的末尾缺少最后一个空格意味着该单词与最后一个单词中的前一个单词之间缺少一个空格,而是被抛到最后一个单词的末尾,这是原始字符串中的第一个单词。发送单词另一侧的空格只会将问题移到其他地方。有谁能看到解决方案?
答案 0 :(得分:5)
您只需移动start
函数中的inprev
指针即可跳过单词之间的空格。因为这似乎是家庭作业(如果我错了,请纠正我)我只是说你需要做的就是移动一个操作员的位置。
但是,这会产生一个问题,即inprev
执行缓冲区溢出,因为搜索没有正确终止。更好的方法是:
while not end of string
search for start of word
start = start of word
search for end of word
strrev (start, end)
这也将照顾多个空间。此外,U + 0020(ASCII 32,空格)不是唯一的空格字符。有标准的库函数来测试字符。它们位于&lt; ctype.h&gt;并以is...
开头,例如isspace
。
答案 1 :(得分:1)
如果您不使用指针而是偏移,有时事情会变得更容易。 strspn()和strcspn()函数函数或多或少地强迫你使用偏移量, 并且非常好地处理字符串结束条件。
#include <stdio.h>
#include <string.h>
size_t revword(char *str);
void revmem(void *ptr, size_t len);
size_t revword(char *str) {
size_t pos,len;
for (pos=len=0; str[pos]; pos += len) {
len = strspn( str+pos, " \t\n\r");
if (len) continue;
len = strcspn( str+pos, " \t\n\r");
if (!len) continue;
revmem( str+pos, len );
}
revmem( str, pos );
return len;
}
void revmem(void *ptr, size_t len)
{
size_t idx;
char *str = (char*) ptr;
if (len-- < 2) return;
for (idx = 0; idx < len; idx++,len--) {
char tmp = str[idx];
str[idx] = str[len];
str[len] = tmp;
}
}
int main (int argc, char **argv)
{
if (!argv[1]) return 0;
revword(argv[1] );
printf("'%s'\n", argv[1] );
return 0;
}
答案 2 :(得分:0)
找出解决方案;这是我修改后的功能正常工作。
void inprev(char * str)
{
_Bool inword = 0;
char * wordend;
char * wordstart;
while(*str)
{
if(!isspace(*str) && (inword == 0))
{
wordstart = str;
inword = 1;
}
else if (isspace(*str) && (inword == 1))
{
wordend = str-1;
inword = 0;
strrev(wordstart, wordend);
}
str++;
}
if (*str == '\0')
strrev(wordstart, str-1);
}
char * wordend是不成功的,因为你可以将str-1传递给strrev函数,但是它会更清楚地说明发生了什么。
答案 3 :(得分:0)
以下算法就地并以两个步骤运行。首先它反转整个字符串。然后它反转每个单词。
#include <stdio.h>
void reverse(char *str, int len)
{
char *p = str;
char *e = str + len - 1;
while (p != e) {
*p ^= *e ^= *p ^= *e;
p++;
e--;
}
}
void reverse_words(char *str)
{
char *p;
// First, reverse the entire string
reverse(str, strlen(str));
// Then, reverse each word
p = str;
while (*p) {
char *e = p;
while (*e != ' ' && *e != '\0') {
e++;
}
reverse(p, e - p);
printf("%.*s%c", e - p, p, *e);
if (*e == '\0')
break;
else
p = e + 1;
}
}
int main(void) {
char buf[] = "Bob likes Alice";
reverse_words(buf);
return 0;
}
答案 4 :(得分:0)
void reverse_str(char* const p, int i, int j) // helper to reverse string p from index i to j
{
char t;
for(; i < j ; i++, j--)
t=p[i], p[i]=p[j], p[j]=t;
}
void reverse_word_order(char* const p) // reverse order of words in string p
{
int i, j, len = strlen(p); // use i, j for start, end indices of each word
reverse_str(p, 0, len-1); // first reverse the whole string p
for(i = j = 0; i < len; i = j) // now reverse chars in each word of string p
{
for(; p[i] && isspace(p[i]);) // advance i to word begin
i++;
for(j = i; p[j] && !isspace(p[j]);) // advance j to past word end
j++;
reverse_str(p, i, j-1); // reverse chars in word between i, j-1
}
}