代码点评及解析:习题3-2,单词的长度(Word)
2011-02-12 23:13
330 查看
收到群里一位同学的代码,忍不住点评一下。也请各位指正。
话说《算法竞赛入门经典》P50有这样一道题,我给出如下比较详细的描述说明:
依我之见,本题的解法策略不止一种。比如我给出的解法所采用的策略是:
source1.c
很遗憾,这位同学没有给出具体的解题思路说明,只是扔了一段代码(source1.c)上来,就说有错,要大家帮忙改正。说实话,他应该描述一下自己的思路,代码里面也加上一些必要的注释(上面的注释是我加上去的),说明一下为什么要这么写source1.c;这样一来,大家也好帮助他的。下面,我只好猜一猜他的思路了。
source1.c的策略是:
把用户的数据一下子都读入数组a中。int a[A]是错误的表达,应为char a[A].
原作者希望用i来表示用户输入的字符个数,可是却写出了char i=0;(第11行),这显然是错误的!正确的表达应为:int i; 这里的 i 也不必初始化为0,反正第13行都有给 i 赋值。
以y为数组的下标,从下标0开始,扫描整个数组a,分析其中的全部字母个数 tot 和单词个数 word。显然,这里的 tot 和 word 应为 int 类型。第14行到第20行的代码就是完成这项工作的。具体说来:原作者先假设所有的字符都是字母,故有第14行的 tot=i; 的假设,然后再扫描的过程中,每遇到一个空格,就将 tot 减量1。这部分是没有问题的。但是,很遗憾,原作者对于 word 的计算思路是错的:因为用户有可能输入许多连续的空格,所以不能一遇到空格,就认为增加了一个单词。那么,如何判断我们扫描到了一个新的单词呢?详见后面的叙述。
最后,原作者从第21行到第23行,用 y 来计算并输出了单词的平均长度。这里明显也存在着一个问题:y, tot, word 的类型都是 int ,这里单词的平均长度明显是存在小数的可能的。就如同计算班级学生的平均年龄一样:平均值,很多时候都是实数(带小数部分)。
要注意,isspace()函数所判断的“空白符号”指的是“空白符指空格、水平制表、垂直制表、换页、回车和换行符”这几种。注意:用户的输入其实只包含空格和字母
分析完了 source1.c 的诸多问题,让我们用原作者的思路来重写一下这部分代码吧。我给出的代码是这样的:
source2.c
关键问题说明:如何判断我们扫描到了一个新的单词呢?对应的代码是 source2.c 的第16~21行。
source2.c 的测试情况如下:
D:\temp>tcc -run test2.c
smart thanks
单词的平均长度是5.500000
D:\temp>tcc -run test2.c
smart thanks
单词的平均长度是5.500000
D:\temp>tcc -run test2.c
s mart t hanks
单词的平均长度是2.750000
D:\temp>tcc -run test2.c
没有输入任何单词
总结与反思:
解决问题之前,一定要搞懂问题本身的含义。她要我做什么?用户输入的数据是什么?我应该有怎样的输出?
用适合的数据类型来表达问题所涉及的数据。比如,用字符数组存储用户输入的字符串,用浮点类型存储平均值,用整型存储计数值…… 浮点类型和整数类型的选择,常常是初学者出错的地方。
要仔细考虑“边界情况”的处理:比如 source2.c 的第18行,就是对最开始的字符 a[0] 进行了特别的判定。请注意,数组下标从0开始,数组是没有 a[-1] 这样的元素的。
写代码的时候,一定要做好注释和说明工作。不然,自己看起来好累的,别人看起来好痛苦的!关于如何写注释,可以参考一下我的源代码。
多做测试。
至此,整个世界都清静了。
谢谢观赏!
话说《算法竞赛入门经典》P50有这样一道题,我给出如下比较详细的描述说明:
习题3-2,单词的长度(word).c
输入若干个单词,输出他们的平均长度。单词只包含大写字母和小写字母,用一个或多个空格隔开。
如题所述,意味着用户输入的字符只有2种可能:字母、或是空格——连回车都不会有。这点一定要明确。不管是竞赛,还是自己练习,读懂题目(客户)的要求是很重要的。输入若干个单词,输出他们的平均长度。单词只包含大写字母和小写字母,用一个或多个空格隔开。
依我之见,本题的解法策略不止一种。比如我给出的解法所采用的策略是:
说明:
解决本题,需要用到字符串的知识。字符串,也就是一维的字符数组。
结束输入的方法:Ctrl+Z,回车,回车。
策略:
scanf("%s",...); 遇到空格时,会自动截断。很适合用在这种环境。
strlen(); 用于计算字符串的长度
操作步骤:
1、读入一个单词;
2、计数器增量1
3、计算单词长度,累加总长度
4、总长度/计数器 ----> 平均长度
而群里面,那位同学给出的代码是这样的:解决本题,需要用到字符串的知识。字符串,也就是一维的字符数组。
结束输入的方法:Ctrl+Z,回车,回车。
策略:
scanf("%s",...); 遇到空格时,会自动截断。很适合用在这种环境。
strlen(); 用于计算字符串的长度
操作步骤:
1、读入一个单词;
2、计数器增量1
3、计算单词长度,累加总长度
4、总长度/计数器 ----> 平均长度
source1.c
0001 #include<stdio.h> 0002 #include<string.h> 0003 #include<ctype.h> 0004 #define A 100000+10 /*假定用户输入字符的最多个数*/ 0005 int a[A]; /*存储用户输入的字符数据*/ 0006 main() 0007 { 0008 int y=0, 0009 tot=0, /*用户输入的字母的总数*/ 0010 word=1; /*单词的个数(这里初始化为1是不妥的,因为用户可能什么字母也没有输入,而只是输入了空格。*/ 0011 char i=0; 0012 gets(a); 0013 i=strlen(a); 0014 tot=i; 0015 for (;y<i;y++){ 0016 if (isspace(a[y])) { /*有关isspace()函数的用法,请参见:http://www.kuqin.com/clib/ctype/isspace.html 注意:用户的输入其实只包含空格和字母*/ 0017 tot=tot-1; 0018 word=word+1; 0019 } 0020 } 0021 y=0; 0022 y=tot/word; 0023 printf("%d\n",y); 0024 return 0; 0025 }
很遗憾,这位同学没有给出具体的解题思路说明,只是扔了一段代码(source1.c)上来,就说有错,要大家帮忙改正。说实话,他应该描述一下自己的思路,代码里面也加上一些必要的注释(上面的注释是我加上去的),说明一下为什么要这么写source1.c;这样一来,大家也好帮助他的。下面,我只好猜一猜他的思路了。
source1.c的策略是:
把用户的数据一下子都读入数组a中。int a[A]是错误的表达,应为char a[A].
原作者希望用i来表示用户输入的字符个数,可是却写出了char i=0;(第11行),这显然是错误的!正确的表达应为:int i; 这里的 i 也不必初始化为0,反正第13行都有给 i 赋值。
以y为数组的下标,从下标0开始,扫描整个数组a,分析其中的全部字母个数 tot 和单词个数 word。显然,这里的 tot 和 word 应为 int 类型。第14行到第20行的代码就是完成这项工作的。具体说来:原作者先假设所有的字符都是字母,故有第14行的 tot=i; 的假设,然后再扫描的过程中,每遇到一个空格,就将 tot 减量1。这部分是没有问题的。但是,很遗憾,原作者对于 word 的计算思路是错的:因为用户有可能输入许多连续的空格,所以不能一遇到空格,就认为增加了一个单词。那么,如何判断我们扫描到了一个新的单词呢?详见后面的叙述。
最后,原作者从第21行到第23行,用 y 来计算并输出了单词的平均长度。这里明显也存在着一个问题:y, tot, word 的类型都是 int ,这里单词的平均长度明显是存在小数的可能的。就如同计算班级学生的平均年龄一样:平均值,很多时候都是实数(带小数部分)。
要注意,isspace()函数所判断的“空白符号”指的是“空白符指空格、水平制表、垂直制表、换页、回车和换行符”这几种。注意:用户的输入其实只包含空格和字母
分析完了 source1.c 的诸多问题,让我们用原作者的思路来重写一下这部分代码吧。我给出的代码是这样的:
source2.c
0001 #include<stdio.h> 0002 #include<string.h> 0003 #include<ctype.h> 0004 #define A 100000+10 /*假定用户输入字符的最多个数*/ 0005 main() 0006 { 0007 char a[A]; /*存储用户输入的字符数据*/ 0008 int y, 0009 tot=0, /*用户输入的字母的总数*/ 0010 word=0, /*单词的个数*/ 0011 i; 0012 gets(a); 0013 i=strlen(a); 0014 tot=i; 0015 for (y=0;y<i;y++){ 0016 if (isspace(a[y])) tot=tot-1; 0017 if ( 0018 (y==0 && !isspace(a[y])) /*如果数组下标为0的元素不为空格,则算找到了一个单词。(数组最开始的地方,要特别处理。)*/ 0019 || 0020 (y>0 && isspace(a[y-1]) && !isspace(a[y])) /*如果数组中某个下标比0大的元素不为空格,且该元素的前一个元素是空格,则算是找到了一个单词*/ 0021 ) word=word+1; 0022 } 0023 if (word==0) printf("没有输入任何单词"); 0024 else printf("单词的平均长度是%f",(tot*1.0)/word); 0025 return 0; 0026 }
关键问题说明:如何判断我们扫描到了一个新的单词呢?对应的代码是 source2.c 的第16~21行。
source2.c 的测试情况如下:
D:\temp>tcc -run test2.c
smart thanks
单词的平均长度是5.500000
D:\temp>tcc -run test2.c
smart thanks
单词的平均长度是5.500000
D:\temp>tcc -run test2.c
s mart t hanks
单词的平均长度是2.750000
D:\temp>tcc -run test2.c
没有输入任何单词
总结与反思:
解决问题之前,一定要搞懂问题本身的含义。她要我做什么?用户输入的数据是什么?我应该有怎样的输出?
用适合的数据类型来表达问题所涉及的数据。比如,用字符数组存储用户输入的字符串,用浮点类型存储平均值,用整型存储计数值…… 浮点类型和整数类型的选择,常常是初学者出错的地方。
要仔细考虑“边界情况”的处理:比如 source2.c 的第18行,就是对最开始的字符 a[0] 进行了特别的判定。请注意,数组下标从0开始,数组是没有 a[-1] 这样的元素的。
写代码的时候,一定要做好注释和说明工作。不然,自己看起来好累的,别人看起来好痛苦的!关于如何写注释,可以参考一下我的源代码。
多做测试。
至此,整个世界都清静了。
谢谢观赏!
相关文章推荐
- 算法竞赛入门经典 习题3-2 单词的长度(word)
- Length of Last Word --最后单词长度---如何优雅的写代码(重重)
- [LeetCode] Maximum Product of Word Lengths 单词长度的最大积
- Length of Last Word 最后一个单词的长度
- LeetCode--Length of Last Word (计算最后一个单词的长度)Python
- Java根据word模板生成word文档之后台解析和实现及部分代码(三)A
- leetCode 58.Length of Last Word (最后单词的长度) 解题思路和方法
- [LeetCode] Length of Last Word - 最后一个单词的长度
- [LeetCode] Length of Last Word 求末尾单词的长度
- [leetcode]Length of Last Word (求最后一个单词的长度 C语言实现)
- 【LeetCode-面试算法经典-Java实现】【058-Length of Last Word (最后一个单词的长度)】
- Java根据word模板生成word文档之后台解析和实现及部分代码(三)B
- leetcode 58. Length of Last Word(C语言,计算最后一个单词的长度)19
- Java根据word模板生成word文档之后台解析和实现及部分代码(三)C
- Lettcode_58_Length of Last Word_字符串最后出现单词的长度
- Mook第八周习题 单词长度(4分)(1)题
- lintcode python代码 422 最后一个单词长度
- leetCode 58.Length of Last Word (最后单词的长度) 解题思路和方法
- storm入门简介及WordCount代码解析(一)
- Reverse Word in a String(翻转字符串)&字符串最后一个单词的长度