一、基础研究
写一个函数showshr(char *,...)它可以接收不定数量的char *型参数,并打印这些指针所指向的字符串。这个题目也是要实现不定长参数的函数,而我们之前研究过printf()函数的打印机制,可以发现他们的原理是一样的,只不过printf()函数是点对点打印,即通过说明符识别要打印的数据类型和要打印的数据个数,它的参数就是要打印的数据本身,而这里要求的函数没有说明符,它的参数是要打印的字符串的地址,只是在最后的参数为0以识别停止打印并返回。
那么我觉得这里有两种思路:一种是在showstr()函数内部使用输出函数函数,这样就要求我们将参数即要打印的字符串的地址转换成字符串的值,即转换成一个字符数组,这需要我们把所有参数指向的空间当作是一段空间,并将它的大小即总的字符串长度计算出来,这样才能定义字符串数组并打印。还有一种思路是直接将字符串打印到屏幕上的固定位置,即将字符串赋值到以b800为段地址的某个地址空间,这是更底层的写法。但是我希望我在运行程序时能够将将字符串打印到输入命令的下一行,即打印位置是不固定的,所以我倾向于使用第一种思路。
那么接下来可以开始写程序了,首先我们把showstr的第一个形参命名为p,首先p的值是第一个字符串的首地址,判断p是否为0,如果是则返回函数,如果不是则输出p指向的字符串,在这里我们用putchar()函数输出,因为每次只能输出一个字符,所以要循环输出。那么怎么判断字符串结束呢?我的办法是判断当前位置是否为符号,即是否为句号或感叹号,但这样做的缺点是如果字符串不以符号结尾或者是中间出现符号的话输出就会出现错误。
现在要跳到下一个参数来进行输出,怎么使p的值为下一个参数呢?我们知道形式参数是在栈里存放的,而且是紧邻的,所以如果传递的是p1、p2、p3,那么入栈顺序是p1、p2、
P3,因为他们的类型是char *型,所以p1的地址减2个字节就是p2的地址,所以我们对p取址再减2就是下一个参数的地址。
编写程序如下:
因为发现程序停不下来,所以我把while循环换成了for循环打印有限个结果。这个程序的运行结果如下:
可以发现,程序存在的问题有两个:
(1)不能调到第三条字符串,导致程序运行停不下来;
(2)打印的句号和问号有两个。
对于第二个问题,是因为判断语句里面多了一条输出语句。
在字符串的跳转语句前面加一条输出语句:
发现p只有第一次改变了:
这是因为p是在栈段中的存储第一个参数的首地址,它的地址是不变的,所以po=&p+1;是不变的,所以第一次改变后,p的值就不变了。那么把p的地址给po,让po每次加1来跳到下一个参数的首地址,再将*po赋给p,即将下一个参数所指向的字符串的首地址赋给p,这样p就指向下一个字符串。
修改后的程序如下:
这里要注意的是po是存储参数的地址,而p是存储字符串的首地址,所以po应该是int *型。运行结果为:
但是我觉得只判断最后的符号来判断字符串是否结束不是很严谨,还有别的办法判断字符串是否结束吗?查找资料可以发现字符串是以’ ’结尾的,所以我们应该可以判断*(p+i)是否为‘