源统计程序

源统计程序(WordCount)

GitHub地址:https://github.com/CloudDawnSun/WC

一.项目要求

1. wc.exe 是一个常见的工具,它能统计文本文件的字符数、单词数和行数。这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某程序设计语言源文件的字符数、单词数和行数。

2. 实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。
具体功能要求:
程序处理用户需求的模式为:

wc.exe [parameter] [file_name]

二.解题思路

  本来我打算用新学的Java来实现功能,经过尝试过后放弃了,因为我对Java的接口调用和文件操作太不熟悉了。

  统计字符数和行数直接就通过fgetc()函数获取标志字符进行判断,而单词我则将英语字符串定义为单词

三.代码

#include<stdio.h>
#include<string.h>
#include<io.h>
#include<stdlib.h>
#define MAXSIZE 1024
//统计字符数
void countchar(char* filename)
{
    char c;
    int charnum = 0;
    FILE* fp;
    fp = fopen(filename, "r");
    if (fp == NULL)
        {
       printf("打开文件失败或文件不存在
");
    }
    else
    {
        c = fgetc(fp);
        while (c != EOF)
        {
                charnum++;
            c = getc(fp);
            }
        printf("字符数:%d
", charnum);
        fclose(fp);
    }
}
 1 //统计文件行数
 2 void countline(char* filename)
 3 {
 4     FILE* fp;
 5     int linenum = 0;
 6     char c;
 7     fp = fopen(filename, "r");
 8     if (fp == NULL)
 9     {
10         printf("打开文件失败或文件不存在");
11         return;
12     }
13     c = fgetc(fp);
14     if (c != EOF) linenum++;
15     while (c != EOF)
16     {
17         if (c == '
' || c == '
')
18             linenum++;
19         c = fgetc(fp);
20     }
21     printf("行数:%d
", linenum);
22     fclose(fp);
23 }
//统计词数,一个字母算作一个单词
void countword(char* filename)
{
    int wordnum = 0;
    char c;
    int judge = 0;
    FILE* fp;
    fp = fopen(filename, "r");
    if (fp == NULL)
    {
        printf("打开文件失败或文件不存在");
        return;
    }
    c = fgetc(fp);
    while (c != EOF)
    {
        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
        {
            judge = 1;        //记录前一个字符是不是字母
        }
        else
            judge = 0;
        c = fgetc(fp);
        if (c == EOF) break;
        if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
            if (judge == 1)
                wordnum++;
    }
    if (judge == 1)
        wordnum++;
    printf("词数:%d
", wordnum);

    fclose(fp);
}
//统计空行和代码行
void countSline(char* filename)
{
    int spaceline = 0;        //空行
    int codeline = 0;        //代码行
    char c;
    int jnull=1;        //标志此行是不是空行
    FILE* fp;
    fp = fopen(filename, "r");
    if (fp == NULL)
    {
        printf("文件打开失败或文件不存在");
        return;
    }
    do
    {
        c = fgetc(fp);
        if (c == '
')
        {
            if (jnull == 1) spaceline++;
            else codeline++;
            jnull = 1;                //每一行开始时默认为空行
        }
        if (c != ' ' && c != '
' && c != '
'&&c!=-1)  //不是空格或换行或文件末尾,则不是空行
            jnull = 0;
    } while (!feof(fp));
    if (jnull == 1) spaceline++;    //最后一行判断(没有换行符要独立判断)
    else codeline++;
    printf("代码行:%d
", codeline);
    printf("空行:%d
", spaceline);
    fclose(fp);
}
//输入 目录时调用此函数处理目录下文件
void findFiles(char* Path, char* choose[], int argc)
{
    intptr_t judgePath;    //文件句柄,相当与文件指针fp,用于判断是否路径是否存在
    _finddata_t File;

    int i = 1;
    FILE* fp;                        //用于判断是否是统计对象
    char strfind[MAXSIZE];            //用于加通配符,寻找文件
    char str[MAXSIZE];                //用于记录文件路径
    strcpy(strfind, Path);
    strcat(strfind, "\");
    strcat(strfind, "*.*");        // 在要遍历的目录后加上通配符
    judgePath = _findfirst(strfind, &File);    // 查找目录中的第一个文件
    if (judgePath == -1)
    {
        printf("文件路径错误或不存在
");
        return;
    }
    do
    {
        if (File.attrib & _A_SUBDIR
            && strcmp(File.name, ".") == 0
            && strcmp(File.name, "..") == 0
            );
        else
        {
            strcpy(str, Path);
            strcat(str, "\");
            strcat(str, File.name);
            if ((fp = fopen(str, "r")) != NULL)
            {
                printf("%s
", str);
                for (i = 1; i < argc - 1; i++)
                {
                    if (strcmp(choose[i], "-c") == 0)
                        countchar(str);
                    if (strcmp(choose[i], "-l") == 0)
                        countline(str);
                    if (strcmp(choose[i], "-w") == 0)
                        countword(str);
                }
            }
        }


    } while (_findnext(judgePath, &File) == 0);    // 查找下一个文件

    _findclose(judgePath);    // 关闭句柄
}
int main(int argc, char* argv[])
{
    int i = 1;
    FILE* fp;
    fp = fopen(argv[argc - 1], "r");
    if (fp == NULL)
    {
        findFiles(argv[argc - 1], argv, argc);
    }
    else
    {
        for (i = 1; i < argc - 1; i++)
        {
            if (strcmp(argv[i], "-c") == 0)
                countchar(argv[argc - 1]);
            if (strcmp(argv[i], "-l") == 0)
                countline(argv[argc - 1]);
            if (strcmp(argv[i], "-w") == 0)
                countword(argv[argc - 1]);
            if (strcmp(argv[i], "-a") == 0)
            {
                countSline(argv[argc - 1]);
                countnoteline(argv[argc - 1]);
            }
        }
        fclose(fp);
    }

    return 0;
}

四. 运行结果

 

 

 

五. PSP

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

60

 60

· Estimate

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

300

 400

Development

开发

 200

 300

· Analysis

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

 100

 200

· Design Spec

· 生成设计文档

 20

 20

· Design Review

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

 15

 15

· Coding Standard

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

 20

 20

· Design

· 具体设计

 60

 65

· Coding

· 具体编码

120

200

· Code Review

· 代码复审

 20

 20

· Test

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

20

 30

Reporting

报告

30

 50

· Test Report

· 测试报告

 20

 30

· Size Measurement

· 计算工作量

 20

 20

· Postmortem & Process Improvement Plan

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

20

 30

合计

1025

1460

 

六. 总结

   刚看到这个题目的时候,我以为会很难,毕竟我对文件操作有了一些不好的印象,在理解过后,发现并不是很难。在写扩展功能的时候,因为对于题目要求没有理解正确,在写完功能后发现题目的要求并非如此,这给了我一个教训,以后需求分析要仔细。且自己对于函数的调用做得不是很好,在寻找目录下文件的函数中强行在进行一次指令判断,我觉得应该可以做的更好,但暂时没想出来。

原文地址:https://www.cnblogs.com/CloudDawnSun/p/12534782.html