此帖出自编程基础论坛
最新回复
辛昕这个程序着实不短,这次我采用直接在原程序中加注的办法来挑刺,不然的话,实在不好对照/*practise 8.4*//*题目:定义一个函数,其参数是一个字符串,返回该字符串中的单词数。单词以空格或标点符号来分隔,假设字符串不含单双引号,也就是说不存在像isn't这样的词。定义第二个函数,它的第一个参数是一个字符串,第二个参数是一个数组,该函数将第一个字符串变元分割成单词,把这些单词存储在第二个数组变元中,最后返回这些单词。第三个函数,其参数是一个字符串,返回该字符串中的字母数。使用这些函数实现一个程序,从键盘读入含有文本的字符串,输出文本中的所有单词,输出顺序按照单词字母数由短到长。*//*关于 isalpha()*/#include#include#include#include#define increment 10#define WORDLEN 10int account(char *pstring); //统计词数void get_words(char pstring[],char* pwords[]); //拆分成词项,存入pwords[]int Get_length(char str[]);char** arrangement(char* pwords[],int);int main(void){int capacity = 20;int count = 0;char *pstring = NULL;char *temp = NULL;int words = 0;char **pwords = NULL;char **buffer = NULL;int position = 0;int number = 0;pstring = (char *)malloc(capacity * sizeof(char));printf(\"Enter a string:\n\");do{if(count == capacity){capacity += increment;temp = (char *)malloc(capacity * sizeof(char));if(!temp){printf(\"Allocation failed.\n\");return -1;}if(!pstring){for(int i = 0;i < count;i++)*(temp + i) = *(pstring + i);pstring = temp;free(temp);}}}while((*(pstring + count++) = getchar()) != '\n'); /*结束字符串*/*(pstring + count) = 0;/*统计词数*/words = account(pstring);/*根据词数分配数组容纳词数*/pwords = (char **)malloc(words * sizeof(char *));/*为每个词分配空间*/for(int n = 0; n < words;n++)pwords[n] = (char*)malloc(WORDLEN*sizeof(char));//当年的恶习,这个小写,我半天没看出原来是个宏//看来这个正确版本和那个错误版本都是我写的,不是参考答案get_words(pstring,pwords);pwords = arrangement(pwords,words);//圈注,这个地方也有点危险,象pwords这种由malloc赋值的指针,在free之前赋值都是隐患,尽管在这个地方是自己赋值给了自己//圈注,稳妥的写法还是 arrangement(pwords,words);/*这一部分属于一开始写程序时,一个阶段一个阶段检查已有结果时所用*//*结果最后忘了关闭测试。另外是,number先赋值为1,而在其后输出的时候*//*又用的先使用再加1,这种做法不好,所以我选择初始化为0,然后先加加再使用*/for(number = 0;number < words;number++)printf(\"%s\n\",pwords[number]);// number = 1;/*从题目出发,这一部分是没用的*//*但我忘记了打问号那一句的作用和意义*/buffer = (char **)malloc(words * sizeof(char *));buffer[0] = pwords[0];//?????for(int k = 1;k < words;k++){for(int j= 0;j <= position;j++) {if(!strcmp(buffer[j],pwords[k])) break; if(j == position && strcmp(buffer[j],pwords[k]))buffer[++position] = pwords[k]; }}/*看到这一部分,才会想起这是用来剔除重复的单词,所以上面的那个输出是用来测试是否读取正确的*//*但上述代码并未实现该功能*/for(int l = 0;l < position;l++)printf(\"%s\n\",buffer[l]);free(pwords);pwords = NULL;free(buffer);buffer = NULL;return 0;}int account(char *pstring){int count = 0;char flag = 0;int i = 0;/*for(unsigned int i = 0; i < strlen(pstring);i++) //过去我真的是干了太多这种事//圈注:象上边写的 i < strlen(pstring) ;从语法来看尽管没错,但是每判一次循环条件,就要调用一次 strlen(pstring)函数,
//大大增加了运行时的负担(尤其是对实时,嵌入式系统而言// 正确的方法是,将strlen(pstring)先赋值给某个临时变量,或者改为,for(i=strlen(pstring)-1;i>=0;)//过去,我一直以为是99和ansi的区别,但刚刚看的C和指针,//即应该把定义放在所有语句之前。//我怀疑我是不是弄错了?{if(!isalpha(*(pstring + i)) && isalpha(*(pstring + i + 1)) )count++;}if(isalpha(*(pstring)) )//????count++;*//*这种计数方法,使得这个程序弱不禁风*//*这样的输入就能让它报废:a big big, (space)de *//*合理的方法应该是按顺序遍历整个字符串,逢字母开始坐标志,隔了一个以上的非字母,再碰到字母,计数*//*充分考虑几种可能的输入情况:\" I am a big big girl\"\"I am a big big girl, in the big big world\"\"I am a big big girl.\"*/while(*(pstring + i) != '\0'){if(isalpha(*(pstring + i++))){if(!flag)flag = 1;}else{if(flag){count++;flag = 0;}}}//圈注,上边这段话明显有问题,具体分析我就不写了,下边改为正确的写法,对比一下.while(*(pstring + i) != '\0'){if(isalpha(*(pstring + i++))){if(!flag){flag = 1;count++;}}elseflag = 0;}//圈注,上边的flag=的1和0最好定义成一个有名字意义的宏,这样不容易搞错./*下面这一段居然是画蛇添足?!!*///if(isalpha(*(pstring+i)) && !flag)// count++;return count;}void get_words(char pstring[],char* pwords[]){int count = 0;int i = -1; //这里是为了配合后边的“先加再用”,让i从零开始,但是,赋值为-1是否有什么危险呢?int j = 0;/* while(pstring != '\0'){if(!isalpha(pstring)){i++;continue;}j = 0; while(isalpha(pstring))pwords[count][j++] = pstring[i++];pwords[count++][j] = '\0';}*/ /*原来的写法很蠢,其实可以while,不用if*//*改完了,花了半个小时修正,发现其实没进步多少,还是要两个循环变量*/while(pstring[++i] != '\0'){ if(isalpha(pstring))pwords[count][j++] = pstring;else if(j/*strlen(pwords[count])*/){ pwords[count++][j] = '\0';j = 0;}//printf(\"length of %d is %d\n\",count,strlen(pwords[count]));/*这里有个很奇怪的问题,为什么pwords[count]的长度总是17?????*/}}int Get_length(char str[]){int length = 0;while(str[length] != '\0')length++;return length;}char** arrangement(char* pwords[],int words){char* temp = NULL;temp = (char *)malloc(WORDLEN * sizeof(char));//圈注,上边这个temp只是用来临时交换 pwords[j] 和 pwords的指针变量,,这里却给它分配了WORDLEN字符变量的空间,简直是莫名其妙//char temp[WORDLEN];for(int i = 0;i < words;i++){for(int j = 0;j < words;j++){if(Get_length(pwords) < Get_length(pwords[j])){temp = pwords[j];//续前圈注,这里对temp赋值,把malloc分配给它的空间丢了,副作用是产生内存泄露,这也说明对temp分配空间毫无道理pwords[j] = pwords;pwords = temp;}}//free(temp);// = NULL;}//free(temp);return pwords;}
详情
回复
发表于 2012-1-10 14:48
| ||
个人签名
强者为尊,弱者,死无葬身之地 |
||
| |
|
|
此帖出自编程基础论坛
| ||
个人签名能力越大,责任越大;知道越多,未知更多
|
||
| |
个人签名
强者为尊,弱者,死无葬身之地 |
|
曾经的版主且威望大于2000,或对EEWORLD论坛有突出贡献的坛友
EEWorld Datasheet 技术支持