Word Count程序(C语言实现)

Word Count 程序

GitHub地址:https://github.com/MansonYe/Word-Count



一、项目简介

Word Count 是用以统计文本文件的字符数、单词数和行数的常用工具。

二、功能分析及实现情况

· 基本功能:

统计file.c的字符数(实现)

统计file.c的单词数(实现)

统计file.c的行数(实现)

· 拓展功能:

递归处理目录下符合类型的文件(实现)

显示代码行、空行和注释行的行数(实现)

支持通配符(* , ?)(实现)

· 高级功能:

支持GUI界面并显示详细信息(待实现)

· 定义:

  字符:可显示的ASCII码字符,因此不包括空格和‘\n’等控制字符

  单词:由一串连续英文字母组成,遇到英文以外为单词的分隔

  行:每行以分行符或结束符为标志,分为三种:

  空行:本行只由非显示字符组成,若有代码,则不超过一个可显示字符

  代码行:本行包括多于一个字符的代码

  注释行:本行不是代码行,且包括注释

· 例子:

如图为一个典型的C语言文本文件

所有显示的字符均为纳入字符计算中:

如2行有19个字符

以非英文字母分隔单词:

如10行单词数为3,但7行单词数为0

包含多于一个代码的行为代码行:

如10、14、21行等均为代码行

不是代码行且包含注释为注释行:

如4、5、22、24行等,6行因为在文档型注释中顾算注释行

没有显示字符或只有一个代码的行为空行:

如1、3、15行,但6行在文本注释中因此不算作空行,算作注释行

三、PSP


PSP


Personal Software Process Stages


预估耗时(分钟)


实际耗时(分钟)


Planning


计划


30


30


Estimate


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


10


10


Development


开发


480


600


Analysis


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


60


70


Design Spec


· 生成设计文档


5


5


Design Review


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


30


50


Coding Standard


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


10


10


Design


· 具体设计


60


65


Coding


· 具体编码


480


540


Code Review


· 代码复审


60


75


Test


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


60


120


Reporting


报告


120


120


Test Report


· 测试报告


30


60


Size Measurement


· 计算工作量


10


5


Postmortem & Process Improvement Plan


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


30


60

四、解题思路及功能实现:

字符统计:

遍历文档字符,通过排除非显示字符,统计显示字符数量;

单词统计:

遍历文档字符,利用变量记录字符是否为英文字母状态,统计进入该状态次数即为单词词数

行数统计:

遍历文档以行为单位的字符串,遍历次数即为行数

特殊行数统计:

遍历文档以行为单位的字符串,再利用指针遍历字符串;首先判断是否为代码行(优先级最高),其次判断是否为注释行,由于三种行互斥,顾空行数为总行数减去前两者。通过变量记录状态以判断代码行和注释行。

通过递归实现文件遍历:

利用_findfirst,_findnext,_findclose函数实现当前文件夹文件遍历,通过attrib属性确定文件夹,通过加工字符串,将新字符串作为新参数调用自身实现通过递归进入下一级目录。同时通过加工字符串在路径后加上文件名作为参数传递给统计函数从而实现每个文件的Word Count。

五、关键代码:

基本功能:

int CodeCount(char *Path) {    //计算字符个数

    FILE *file = fopen(Path, "r");
    assert(file != NULL);    //若文件不存在则报错

    char code;
    int count = 0;

    while ((code = fgetc(file)) != EOF)     //读取字符直到结束
            count+= ((code != ‘ ‘) && (code != ‘\n‘) && (code != ‘\t‘));    //判断是否是字符    

    fclose(file);

    return count;
}

int WordCount(char *Path) {    //计算单词个数

    FILE *file = fopen(Path, "r");
    assert(file != NULL);

    char word;
    int is_word = 0;    //用于记录字符是否处于单词中
    int count = 0;

    while ((word = fgetc(file)) != EOF) {
        if ((word >= ‘a‘ && word <= ‘z‘) || (word >= ‘A‘ && word <= ‘Z‘)) {    //判断是否是字母
            count += (is_word == 0);
            is_word = 1;    //记录单词状态
        }
        else
            is_word = 0;    //记录不处于单词状态
    }
    fclose(file);

    return count;
}

int LineCount(char *Path) {    //计算行数

    FILE *file = fopen(Path, "r");
    assert(file != NULL);

    char *s = (char*)malloc(200 * sizeof(char));
    int count = 0;

    for (; fgets(s, 200, file) != NULL; count++);    //逐次读行

    free(s);
    fclose(file);

    return count;
}

特殊行数统计:

void AllDetail(char *Path) {    //显示空行, 代码行,注释行

    FILE *file = fopen(Path, "r");
    assert(file != NULL);

    char *s = (char*)malloc(200 * sizeof(char));//申请空间
    int i;
    int is_codeline = 0;    //状态记录变量
    int is_annoline = 0;
    int AnnoLock = 0;
    int AnnoFileLock = 0;

    int codecount = 0;
    int annocount = 0;
    int blankcount = 0;

    while (fgets(s, 200, file) != NULL) {    //逐次取文件中的行
        for (i = 0; *(s+i) != ‘\0‘; i++) {

            if ( ( ( *(s+i) >= ‘a‘ && *(s+i) <= ‘z‘) || ( *(s+i) >= ‘A‘ && *(s+i) <= ‘Z‘) ) && AnnoFileLock == 0) {//判断是否是代码行
                codecount += (is_codeline == 0 && AnnoLock == 0);    //进入代码行的时候代码行加一
                is_codeline = 1;
            }

            if ( *(s+i) == ‘/‘ && *(s+i+1) == ‘/‘ && is_codeline == 0 && AnnoFileLock == 0){    //判断是否为注释行
                    annocount++;
                    AnnoLock = 1;
            }

            if (*(s + i) == ‘/‘ && *(s + i + 1) == ‘*‘){    //判断文档注释开始
                AnnoFileLock = 1;
                annocount -= is_codeline;    //注释在代码后不算注释行,因此减一
            }

            if (*(s + i) == ‘*‘ && *(s + i + 1) == ‘/‘) {    //判断文档注释结束
                AnnoFileLock = 0;
                annocount += (*(s + i + 2) == ‘\n‘);    //注释后换行情况
            }
        }
        annocount += AnnoFileLock;    //注释行结束时算作注释行加一

        blankcount++;    //每一行结束计数加一,并清空状态
        is_codeline = 0;
        is_annoline = 0;
        AnnoLock = 0;
    }
    free(s);
    fclose(file);

    blankcount = blankcount - codecount - annocount;
    printf("codeline:%d, annoline:%d, blankline:%d\n", codecount, annocount, blankcount);
}

通过递归实现文件遍历:

void Scan(char *Path, char Type) {
    char *FileName = NULL;
    char *FileType = NULL;
    char Temp[30];    //用于暂存改变得字符串
    long Head;
    struct _finddata_t FileData;
    int i = 0;

    FileName = Path;
    while (*(Path + i) != ‘\0‘) {    //找出文件名和文件类型的位置
        if (*(Path + i) == ‘\\‘)
            FileName = Path + i + 1;
        if (*(Path + i) == ‘.‘)
            FileType = Path + i + 1;
        i++;
    }

    strcpy(Temp, FileType);//调整字符串
    *FileType = ‘*‘;
    *(FileType + 1) = ‘\0‘;

    Head = _findfirst(Path, &FileData);

    strcpy(FileType, Temp);//恢复字符串

    do {
        if ( !strcmp(FileData.name, "..") || !strcmp(FileData.name, "."))    //去除前驱文件路径
            continue;

        if (_A_SUBDIR == FileData.attrib)    //是文件夹
        {
            strcpy(Temp, FileName);    //调整字符串
            for (i = 0; *(FileData.name + i) != ‘\0‘; i++) {
                *(FileName + i) = *(FileData.name + i);
            }
            *(FileName + i) = ‘\\‘;
            *(FileName + i + 1) = ‘\0‘;
            strcat(Path, Temp);

            Scan(Path, Type);

            strcpy(FileName, Temp);    //恢复字符串
        }
        else//是文件
        {
            for (i = 0; *(FileData.name + i) != ‘.‘; i++);
            if (!strcmp(FileData.name + i + 1, FileType)) {    //是指定类型的文件

                strcpy(Temp, FileName);
                strcpy(FileName, FileData.name); //调整字符串

                printf("%s:  ", FileData.name);
                Run(Type, NULL, Path);    //将地址及功能传到启动函数
                printf("\n");

                strcpy(FileName, Temp);//恢复字符串
            }
        }
    } while (_findnext(Head, &FileData) == 0);

    _findclose(Head);
}

启动函数:

void Run(char Type, char Type2, char *Path) {

    switch (Type) {
    case ‘c‘: printf("code count: %d\n", CodeCount(Path)); break;
    case ‘w‘: printf("word count: %d\n", WordCount(Path)); break;
    case ‘l‘: printf("line count: %d\n", LineCount(Path)); break;
    case ‘a‘: AllDetail(Path); break;
    case ‘s‘: Scan(Path, Type2); break;
    default: printf("type input error"); break;
    }
}

六、测试结果

字符数计算测试:

单词数计算测试:

行数计算测试:

多种行数计算测试:

遍历功能测试:

测试用文件:

test1:

test2:

c

test3:

word

test4:

/*this is a test file*/

/*
manson ye 

2018/09/09
*/

#include<stdio.h>
#include<string.h>

int main() //main method
{
    int i = 100 / 4;

    printf("hello world");/**/
    /*
    test
    */return 0;
}    //this is test file

//this is test file with many kinds of annotations

test5:

another test file

asasas

七、小结

自己比较少按正常的顺序进行项目的开发。这次的机会令我再次认识到做好事前分析和安排的重要性,根据安排进行开发,有效地提高了开发过程中的可见性。

一开始准备的时候考虑过使用其他语言,但设计到了分辨注释行的时候,由于指针能发挥巨大作用最终还事选择了C语言

写程序的中途我学到了不少新知识,特别是在文件遍历这一方面,并得到了一定程度的实践经验。

同时我也认识到自己关于测试方法知识的匮乏,虽然这次早早地就写完了程序,但是为了搞测试项目,花了很多时间但最后还是只能手动测试,还接近了时间限制,因此眼下应该先学会如何测试项目的正确使用方法。

经过这次作业,我认为只有通过不断地实践与学习,才能够结合知识与实践,进一步提升自己的能力。

ps:第一次写博客,不知道原来能直接用html写,下次应该会呈现得更好!

原文地址:https://www.cnblogs.com/mansonye/p/9649663.html

时间: 2024-08-10 01:12:45

Word Count程序(C语言实现)的相关文章

word count程序,以及困扰人的宽字符与字符

一个Word Count程序,由c++完成,有行数.词数.能完成路径下文件的遍历. 遍历文件部分的代码如下: void FindeFile(wchar_t *pFilePath) { CFileFind finder; CString Finddir; Finddir.Format(pFilePath); BOOL ret = finder.FindFile(Finddir); while (ret) { ret = finder.FindNextFile(); CString strPath

软件工程第三个程序:“WC项目” —— 文件信息统计(Word Count ) 命令行程序

软件工程第三个程序:“WC项目” —— 文件信息统计(Word Count ) 命令行程序 格式:wc.exe [parameter][filename] 在[parameter]中,用户通过输入参数与程序交互,需实现的功能如下: 1.基本功能 支持 -c 统计文件字符数支持 -w 统计文件单词数支持 -l 统计文件总行数 2.拓展功能 支持 -a 返回高级选项(代码行 空行 注释行)支持 -s 递归处理符合条件的文件 3.高级功能 支持 -x 程序以图形界面与用户交互 [filename] 是

c语言简单实现word count功能

c语言简单实现word count功能 一:源码参考  参考地址:https://home.cnblogs.com/u/sunbuqiao/ 二:阅读               代码主要思路是先选定文件,将文件中的字符读入数组,利用for循环分别统计字符数.单词数.空格数.行数.实现过程使用了fseek函数判断指针用于判断数据总长度,根据转移字符判断行数. 三:代码上传                    地址:https://github.com/meinumber1

Hadoop AWS Word Count 样例

在AWS里用Elastic Map Reduce 开一个Cluster 然后登陆master node并编译下面程序: import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import o

通过简单的Word Count讲解MapReduce原理以及Java实现

MapReduce原理: MapReduce采用"分而治之"的思想,把对大规模数据集的操作,分发给一个主节点管理下的各个分节点共同完成,然后通过整合各个节点的中间结果,得到最终结果.简单地说,MapReduce就是"任务的分解与结果的汇总". 在Hadoop中,用于执行MapReduce任务的机器角色有两个:一个是JobTracker:另一个是TaskTracker,JobTracker是用于调度工作的,TaskTracker是用于执行工作的.一个Hadoop集群中

Hadoop AWS Word Count 例子

在AWS里用Elastic Map Reduce 开一个Cluster 然后登陆master node并编译以下程序: import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import o

Spark的word count

word count 1 package com.spark.app 2 3 import org.apache.spark.{SparkContext, SparkConf} 4 5 /** 6 * Created by Administrator on 2016/7/24 0024. 7 */ 8 object WordCount { 9 def main(args: Array[String]) { 10 /** 11 * 第1步:创建Spark的配置对象SparkConf,设置Spark

课堂练习 Word count

1. 团队介绍 团队成员:席梦寒,胡琦 2. 项目计划 我们选第一.二个功能点进行编程. 具体计划: (1).首先爬取网站内容及网页长度: (2).对爬取的文件内容进行word count操作: (3).对选定词语出现频率进行统计. 3. 环境配置 编程语言:python 代码规范: 一.命名规约 1.[强制]所有编程相关命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束.反例: _name / __name / $Object / name_ / name$ / Object$ 2

wc.exe命令行程序——c语言实现

1 /* 2 * 没能实现的功能:wc.exe -s递归处理目录下符合条件的文件 3 * wc.exe -x 显示图形界面 4 * 5 * 6 * 实现的功能: wc.exe -c显示文件的字符数. 7 * wc.exe -l行数. 8 * wc.exe -w单词. 9 * wc.exe -a空行数.代码行数.注释行数的统计测试 10 *` 11 * 12 */ 13 14 #include"iostream" 15 using namespace std; 16 void CharC