c语言中的一道题,请帮帮解释一下sprintf(b,"%s%c",s+1,*s);为何意?

#define N 81
fun(char *s)
{
char b[N];
sprintf(b,"%s%c",s+1,*s);
strcpy(s,b);
}
main()
{
char a[N];
printf("Enter a string:");gets(a);
printf("The original string is:");puts(a);
fun(a);
printf("The string after modified:");
puts(a);
}


sprintf跟printf的功能和用法比较相似,都是格式化打印,不过printf是打印到屏幕,sprintf是打到一个字符数组里。
sprintf(b,"%s%c",s+1,*s);就是将一串字符内容存到字符数组b中,那么这串字符内容是什么?"%s"表示将要打印一个字符串,而与之对应的变量是s+1,已经知道s是字符串,那么这里s+1就是去掉了s中首字符的子字符串。比如:s的内容是“abcde”,那么s+1就是“bcde”。接着后面的"%c"表示打印单个字符,也就是*s,它代表字符串s中的第一个字符。
所以,这句代码的意思是:将字符串s中的第一个字符移到末尾,并将重新排列后的字符串保存到字符数组b中。

上面的解释可能比较容易理解,但不是很可靠。下面是更详细的说明。先看看字符串。C风格的字符串由两个特点:一是地址连续,二是以0作为结束符。满足这两个条件的字符组合都可以作为字符串。现在反过来想想,如果我们要得到一个字符串的内容,需要什么信息?是首地址。因为字符串是地址连续的,而且我们已经知道结尾的位置是0,所以只要有了首地址,我们就可以一个字符一个字符的读取整个字符串。
现在可以理解,为什么c语言中对字符串只认首地址。这同时也带来了一些便利(当然麻烦也不少,不然就不会有string这一类东西了)。例如:有一个字符数组s1,内容是“HelloWorld”。现在我们要调用一个跟字符串有关的函数,并且希望将s1中的后部分“World”传递进去。那我们是不是需要新声明一个字符数组s2,赋值为“World”,然后再把s2传进去呢?当然不用。其实这里s1本身是“HelloWorld”中第一个字符的地址(相信所有C系语言教程都会讲这一点)。那么s1+1、s1+2...呢?当然还是地址,不过不是第一个字符的,而是第二个、第三个...的地址。现在想想,我们要调用的函数只会把我们传给它的地址当作是字符串的首地址,如果我们把“HelloWorld”中“W”的地址传给它,它只会顺着“W”向后读,而不会知道其实“W”前面还有字符,所以如果我们希望传入“World”的话,只需要将s1+5作为参数传递进去就可以了。上面程序中sprintf(b,"%s%c",s+1,*s);用到的就是这种方法。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2007-03-14
sprintf()函数的用法是:
往缓冲区(如这里的b)中按指定格式输出参数,指定格式(如"%s%c")用法同printf()函数相同;
所以这里的意思是:
%S表示字符串输出的格式,即输出以s+1为首地址的字符串到b;
%c表示字符的输出格式,即输出*s这个字符到指定的空间
所以
printf("The string after modified:");
puts(a);
输出的结果是从输入字符的第二个字符开始打印,一直打印到输入的字符末,最后一个字符是输入的第一个字符(即是将第一个字符放到了最后).

例如:
输入:
abcdefg

最后输出是:
The original string is:abcdefg
The string after modified:bcdefga (把a放到了最后)