• C&Pointer求解wc问题


    一.Github项目地址:https://github.com/changjiang666/wordCount

    二.PSP表格

    WC问题统计C源文件中的字符,单词,行数,输出到默认文件或者指定文件中。拓展功能是实现多文件处理,文本行分类,忽略特定单词。根据需求,PSP表格如下:

    PSP2.1

    PSP阶段

    预估耗时

    (分钟)

    实际耗时

    (分钟)

    Planning

    计划

    5 10

    · Estimate

    · 估计这个任务需要多少时间

    5 10

    Development

    开发

    515 860

    · Analysis

    · 需求分析 (包括学习新技术)

    20 30

    · Design Spec

    · 生成设计文档

    10 20 

    · Design Review

    · 设计复审 (和同事审核设计文档)

    5 10

    · Coding Standard

    · 代码规范 (为目前的开发制定合适的规范)

    20  30

    · Design

    · 具体设计

    10 10 

    · Coding

    · 具体编码

    400  600 

    · Code Review

    · 代码复审

    20  100 

    · Test

    · 测试(自我测试,修改代码,提交修改)

    30  60 

    Reporting

    报告

    100  100

    · Test Report

    · 测试报告

    20 20 

    · Size Measurement

    · 计算工作量

    20  30

    · Postmortem & Process Improvement Plan

    · 事后总结, 并提出过程改进计划

    20   10
     

    合计

    620   970

    三.解题思路

    WC问题在UNIX系统的内核得以实现,骨干代码在黑皮C里面看到过,大概20行左右。刚拿到题目就没怎么在意,后来发现拓展功能也比较麻烦。整个题目的难点在于字符串的处理,文件操作不麻烦,只需要读操作就行,至于写操作只需要输出重定行即可。另一个难点在于递归处理当前路径下来的所有文件,刚开始想直接利用C进行系统调用,借助操作系统来完成这个功能(后来发现系统自动解析,白写了比较麻烦的系统调用),然而没法递归处理,GG。至于找资料,主要就是看了一下黑皮C最后面的库函数,需要用的时候在MSDN上面直接查。

    1.UNIX系统中wc程序的骨干代码

     #include <stdio.h>

      #define IN 1

      #define OUT 0

      

      int main(int argc, char const *argv[])

      {

          int c, nl, nw, nc, state;

          state = OUT;

          nl = nw = nc = 0;

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

              ++nc;       

       if (c == ' ')

               ++nl;

          if (c == ' ' || c == ' ' || c == ' ')

                state = OUT;

          else if (state == OUT) {

                 state = IN;

                 ++nw;

             }

         }

         printf("%d %d %d ", nl, nw, nc);

         return 0;

     }

    基本功能实现就是抄的这个代码,只是把字符来源改成了缓存。

    2. C的文件读操作

    static int

    filelength(FILE *fp);

    char *

    readfile(char *path);

    这个也是网上的,基本照抄。

    3. 输出重定向就是一行代码,利用了redirection

    四.程序设计实现过程

    根据功能划分,写了3个源文件。

    file.c主要是文件操作,wc.c是整个程序的核心部分,help.c是给用户提供帮助的,用户输入-help可以查看帮助和自动打开作业网页。

    1.file,h

    Readfile把文件读到缓存,processBuf从缓存中提取出停用词表,返回指向这些字符的指针的指针。为了防止程序恶意修改缓存,将其设置为const。

    getDir是递归处理所有的文件,没有用。

    2. wc.h

    先定义了一个struct,存储统计的基本信息,其实不用也行,用了只是为了方便,减少自己编程时需要记忆的内容。

    CWL是统计文本信息的,利用了CPU运行程序的思想,把所有的东西都统计出来,需要什么就输出什么,缺点是增加了运行时间,不过只是增加了常系数。

    在wc.c定义了一个外部属性限制在本文件范围的函数。

    3.help.h

    只有一个Help方法,输出帮助信息。

    这几个函数基本没有关系,分开设计就是为了高内聚低耦合,全部的调用由main函数执行。

    五.代码说明

    介绍2个比较麻烦的部分:

    1. main函数对命令行参数的解析

    #if !DEBUG

        if(1 == argc)

        {

            printf("Please Open In CMD! At CMD, Enter 'wc.exe -help' For More Help! ");

            system("pause");

            return EXIT_FAILURE;

        }

        #endif

        for(i = 1; i < argc; ++i)

        {

            p = argv[i];

            /*capture -s*/

            if(strcmp(p, "-s") == 0)

                s_state = TRUE;

            /*capture -a*/

            if(strcmp(p, "-a") == 0)

                a_state = TRUE;

            if(strcmp(p, "-c") == 0)

                c_state = TRUE;

            if(strcmp(p, "-w") == 0)

                w_state = TRUE;

            if(strcmp(p, "-l") == 0)

                l_state = TRUE;

            if(strcmp(p, "-help") ==0)

            {

                help();

                return EXIT_SUCCESS;

            }

            /*loop until p point to ''*/

            while(*++p != NULL)

                ;

            /*p go back 2 char and compare to ".c"

              in order to identify the path name*/

            if(strcmp(p - 2, ".c") == 0)

                path[j++] = argv[i];

            /*p go back 4 char and compare to ".txt", at the same time argv[i - 1]

            stores "-e", so we can identify the word_list path and check user valid input*/

            if(strcmp(p - 4, ".txt") == 0 && strcmp(argv[i - 1],"-e") == 0 )

            {

                word_list_path = argv[i];

            }

            /*p go back 4 char and compare to ".txt", at the same time argv[i + 1]

            stores null pointer, so we can identify the file name*/

            if(strcmp(p - 4, ".txt") == 0 && argv[i + 1] == '')

            {

                /*if lack of "-o" before file name, throw error information*/

                if(strcmp(argv[i - 1], "-o") == 0)

                    filename = argv[i];

                else

                {

                    if(strcmp(argv[i - 1], "-e") != 0)

                    {

                        printf("command line error. ");

                        return EXIT_FAILURE;

                    }

                }

            }

    }

    利用指针处理读取到的字符,由于要处理可能的各种输入,所以有些if嵌套比较深。到了最后感觉利用开关语句可以好一些,不想修改了,时间不够。在处理读取的每个命令行参数时,其实就是对状态变量的修改过程。如果处理一个-s, 就将s_state设置为TRUE,利用状态变量来决定最后的输出。对于处理技巧,注释基本都说了,不再赘述。

     

    2.利用DFA处理代码行/注释行/空行

     

    确定的有限自动机解题有一步是状态化简,去掉无效状态和多余状态,在整个过程中设置了5个状态,PRECODE, CODE, PRECOMMENT, COMMENT, SPACELINE,对于/* */ 多行注释的问题,最后利用状态变量influence进行纠正。时间问题,这段代码写的很丑,最后也没有优化,所有就只贴了部分进行说明。

    最后利用处理结果对相应的统计变量进行自增运算。

     

    六.测试设计过程

    1. 路径测试

        main函数中if路径比较多,将每一条路径进行测试。

    2.边界值测试

        在测试文件中敲入各种可能的注释和空行

    3.等价类划分

      同类情况只测试一次。

    #0help功能测试

    start wc.exe wc.exe -help

    #1基本功能测试

    start wc.exe wc.exe -c -w -l test.c

    #2基本功能测试---输出到指定的文件

    start wc.exe wc.exe -c -w -l test.c -o output1.txt

    #3检测用户的恶意输入(想输出全部结果但是没有输入-s)

    start wc.exe wc.exe -c *.c -o output2.txt

    #4检测用户的恶意输入(没有输入待检测的.c文件)

    start wc.exe wc.exe -w -c -l

    #5当前路径全部文件是否读取成功测试

    start wc.exe wc.exe -s -c -w -l *.c -o output3.txt

    #6检测用户输入错误的文件名

    start wc.exe wc.exe -s -c -w -l finally.c -o output4.txt

    #7复杂数据类型检测

    start wc.exe wc.exe -s -a -c -w -l *.c -o output5.txt

    #8停用词表检测

    start wc.exe wc.exe -s -c -w -l *.c -o output6.txt -e stoplist.txt

    #9检测使用停用词表命令出错

    start wc.exe wc.exe -s -c -w -l *.c -o output7.txt stoplist.txt

    #10检测输出到指定文件命令出错

    start wc.exe wc.exe -s -c -w -l *.c  output8.txt

    #11全部功能集成测试

    start wc.exe wc.exe -s -a -c -w -l *.c -o output9.txt -e stoplist.txt

    七. 参考网址

    1.https://msdn.microsoft.com/zh-cn/library/ftsafwz3.aspx

    2.http://www.cnblogs.com/berthua/p/7654892.html

  • 相关阅读:
    nyoj 202 红黑树
    nyoj 237 游戏高手的烦恼
    nyoj 203 三国志
    nyoj 118 修路方案
    nyoj 714 Card Trick
    nyoj 710 外星人的供给站
    nyoj 712探 寻 宝 藏
    nyoj 709 异 形 卵
    nyoj 711 最舒适的路线
    HTML5表格简单应用案例之[招聘需求表]
  • 原文地址:https://www.cnblogs.com/liucj-666/p/8612506.html
Copyright © 2020-2023  润新知