zoukankan      html  css  js  c++  java
  • 《C程序设计语言》关于单词计数的思考

    代码分析

    源代码来源于Brian W. KernighanDennis M. Ritchie 共同编著的书籍 《The C Program Language》 中1.5.4节中的单词计数

    中文版原文:这里对单词的定义比较宽裕,它是任何其中不含空格、制表符或换行符的字符序列,下面这段程序是UNIX系统中wc程序的骨干部分。

    #include<stdio.h>
    
    #define IN 1    /* 单词内 */
    #define IN 0    /* 单词外 */
    
    main()
    {
        int c, nl, nw, nc, state;
    
        state = OUT;    /* 未有任何字符被读必定为单词外 */
        nl = nw = nc = 0;
        while ((c = getchar()) != EOF) { 
            ++nc;
            if (c == '
    ') 
                ++nc;
            if ( c != ' ' && c != '
    ' && c !='	' )
                state = OUT;
            else if (state == OUT){
                state = IN;
                ++nw;
            }
        }
        printf("%d %d %d
    ", nl, nw, nc);
    }
    

    以下为我的头脑风暴过程。

    • 逻辑是什么?
      • 读 字符
        • 从标准输入流依次读取
        • 在屏幕从左至右依次写入
      • 判断 字符
        • 单词和非单词
          • 区分概念 (人脑逻辑)
            • 单词内
            • 单词外
              • 无任何字符被读
              • 非单词
          • 区分标志 (使人脑逻辑映射到机器)
            • 标志
              • IN
              • OUT

    因为是依次从标准输入流读取字符,写入到屏幕显示出来的字符也是有顺序性。
    我们的问题是模拟顺序的字符流移动过程中提取单词数。源代码中state变量用作区分标志,state = INstate = OUT代表 单词内单词外 ($单词外 eq 非单词 $)。有了区分标志,该如何模拟单词内->单词外这种顺序的跨界过程?

    标志变化 意义 编号
    OUT --> IN 新单词 1
    IN --> IN 单词内 2
    IN --> OUT 新非单词 3
    OUT --> OUT 非新非单词->非单词 4

    但随之产生了一个新的问题,OUT具有二象性。
    IN情况下结果是唯一的,不用管。1逻辑也就是新单词计数逻辑不需要考虑OUT情况,因为他们都是成立的。

    3、4逻辑则必须考虑OUT的二象性。要想让上面3、4逻辑成立,需要额外条件约束,必须读入字符。这是个隐形条件,除了首次读取字符为非单词的特殊情况,OUT(无输入字符)-->OUT(有输入字符),其他的OUT情况都是处在有输入字符的情况中。

    state =  OUT; /* OUT(无输入字符) */
    /*...省略....*/
    if ( c != ' ' && c != '
    ' && c !='	' ) /* OUT(有输入字符) */
                state = OUT;
    

    上述代码则是描述了 OUT(无输入字符)-->OUT(有输入字符) 这一特殊情况。
    在这之后所有的OUT都被限定为有OUT(有输入字符),通过如下循环限制。

    while ((c = getchar()) != EOF){}
    

    至此所有逻辑分析完毕,随之而然也可以得到 非单词计数的逻辑,从而写出代码。下面是我的代码并经过实验验证。

    int main(int argc, char *argv[]) {
    	
    	int c, nl, nw, nc, state;
    	nl = nw = nc = 0; /* 各计数器初始化 */
    	state = OUT; /* 无输入时必定在单词外 */ 
    	
    	while ( (c = getchar()) != EOF )
    	{
    		++nc;
    		if ( c == '
    ')
    			++nl;
    		if (c != ' ' && c != '
    ' && c !='	')
    		{
    			state = IN;								
    		} 
    		else if ( state == IN )  /* 首个非单词 */
    		{
    			state = OUT; 
    			++nw;
    		}
    		else if ( state == OUT ) /* 非首个非单词 */ 
    		{
    			state = OUT;    
    			++nw; 
    		}
    	}
    	
    	printf("%d %d %d", nl, nw, nc);
    	 
    	return 0;
    }
    
    

    除去逻辑,仅仅说编程风格上,if语句条件,改成常量在左,变量在右,更科学。《C编程专家》中有提到过。C语言规定常量不可以被赋值,如果少写了个=号,编译的时候也会发现。而反之是不会提示的,因为语法上是没有错误的,但在我们逻辑上错误了。

    else if( OUT == state )
    

    另外对于新手来说,就是else if(){} 的逻辑问题了,else后面整个if语句是其执行语句

    else
    {
        if(){
    
        }
    }
    

    代码很简单,但却有许多值得思考的地方,也略窥大师的深厚功底,假设咱们坚持这样的10000小时理论,大家包括我都可以成为这个行业的专家。加油吧,与大家共勉。

    本文由作者原创,如需转载注明出处!
  • 相关阅读:
    Cookie和Session的区别
    CSRF攻击与防御(写得非常好)
    AcWing397 逃不掉的路(边双)
    CF1345D Monopole Magnets(构造)
    AcWing1175 最大半连通子图(tarjan)
    西安邮电大学第五届ACM-ICPC校赛 C题 异或生成树(树形dp)
    AcWing368 银河(差分约束)
    AcWing401 从u到v还是从v到u? (tarjan)
    牛客 位数差(二分)
    AcWing367 学校网络(tarjan)
  • 原文地址:https://www.cnblogs.com/Fsiswo/p/11145999.html
Copyright © 2011-2022 走看看