在最近翻阅《C程序设计》一书时,在6.3.7节字符串数组应用举例中我发现了一个值得学习的例子。
题目如下:输入一行字符,统计其中有多少个单词,单词之间用空格隔开
这个程序的设计思路并不难,我们对单词的特性很清楚,只要有空格说明出现了单词数量变化。而为了避免因为输入不规范出现多个空格影响单词个数判断错误,所以应该有两个判断条件共同判断。在循环中,第一次判断为此处是否为空格,如果是,就说明这个位置没有单词,单词符“word”赋0,如果不是,就说明这个地方有字母,再进行第二次判断,这次是关于”word“值的判断,如果为0说明这个位置为一个单词的开头,单词数加一。如果"word"值不为0,说明这个位置之前还有字母,在这之前为一个单词的开头,这个位置不需要再计算单词数。
代码如下:
#include <stdio.h>
int main()
{
char string[81];
int i,num=0,word=0;
char c;
gets(string);
for(i=0;(c=string[i])!='\0';i++)
{
if(c==' ')word=0;
else if(word==0)
{
word=1;
num++;
}
}
printf("There are %d words in this line.\n",num);
return 0;
}
运行结果:
程序分析:我认为这个程序设计思路的特点在于解决了利用之前循环结果来对当前循环进行处理的问题,具体体现在对"word"的赋值使用中。本程序通过第一次判断,来确定每一次循环所在位置是否有字母,有字母的更进一步意义就是这个位置有单词,word置1(这个步骤在第二个循环中),而如果是空格,说明这个位置没有单词,word置1。通过对word赋值的不断改变,我们可以“保留”上一次循环的结果,这样能完成我们对单词首字母的寻找。
对于字符串,我们想做的当然不止步于数有多少个单词,在《C程序设计》一书中,在上文所述问题之后是一个找最大字符串的问题(例6.9),这个问题很简单,在这里我就不过多赘述了,但由此延伸,我们不难想到多个字符串数组排序问题。在之前我有说过选择法对姓名排序的方法,就是对应着这个问题,这一次我将采用冒泡法处理它。
代码如下:
#include "stdio.h"
#include "string.h"
int main()
{
char str[4][10];
char h[10];
for(int i=1;i<4;i++)
{
printf("第%d个字符串为",i);
gets(str[i]);
}
for(int j=1;j<4;j++)
for(int k=1;k<4-j;k++)
{
if(strcmp(str[k],str[k+1])>0)
{
strcpy(h,str[k]);
strcpy(str[k],str[k+1]);
strcpy(str[k+1],h);
}
}
printf("由小到大排列为:");
for(int i=1;i<4;i++)
{
puts(str[i]);
}
return 0;
}
冒泡法的核心思想是逐个位置确定。具体来说对n个元素构成的数组,循环(n-1)次。第一次循环比较(n-1)次,确定第n个元素,第二次循环比较(n-2)次,确定第(n-1)个元素,依此类推,直至全部确定下来。这个过程需要用到两个循环嵌套,是较难思考的部分,上述程序中这段代码为:
for(int j=1;j<4;j++)
for(int k=1;k<4-j;k++)
{
if(strcmp(str[k],str[k+1])>0)
{
strcpy(h,str[k]);
strcpy(str[k],str[k+1]);
strcpy(str[k+1],h);
}
}
对于字符串的处理,其实只是多出了strcpy函数(因为字符串数组不能直接赋值)。总体思路难在嵌套循环的循环判别式上。
运行结果: