• 结对编程


    合作者:201631062505+201631062302

    码云地址:https://gitee.com/SC_looker/wc.exe15.git

    另一个队友的博客地址:https://www.cnblogs.com/zjx123456/p/9800829.html

    本次作业要求地址链接:https://edu.cnblogs.com/campus/xnsy/2018Systemanalysisanddesign/homework/2188

    制定c/c++编程规范

    命名约定

    类(结构)名

    • 类名必须是名词,类名必须明确表示这个类代表了什么。
    • 如果类名超过3个单词,说明这个类有可能需要拆分了。
    • 不要把父类的名字带到子类中。
    • 类名加上后缀也是一种选择。如下载代理类,可以写为DownloadProxy。
    • 类名首字母大写;用大写字母分隔单词,除单词的首字母外,全部小写;类名中不要出现下划线“_”。

    类(结构)属性名

    • 属性由成员前缀”m_“属性,属性名采用匈牙利命名规范。

    方法

    • 方法与函数执行一个任务,因此应当用动词来命名。比方说,DumpDataToFile()就要好于DataFile()。
    • 方法名首字母大写;用大写字母分隔单词,除单词的首字母外,全部小写,方法名中不要出现下划线。

    函数

    • 方法与函数执行一个任务,因此应当用动词来命名。
    • 函数名全部小写,单词之间用下划线分隔。

    方法与函数参数名

    • 首字母小写。
    • 除了第一个单词,所有单词的首字母大写。
    • 名称中不应出现”_”。

    类库名

    • 如果使用C书写类库,或在C++不使用namespace书写类库,为了避免命名冲突,需要在类名,结构名,函数名前加上类库名前缀。类库名应当简洁、明确。 如:
      ImEgg* ImEgg_new();   
      

    变量名

    • 变量名使用匈牙利命名规则。
    • 全部小写字母。
    • 使用”_”作为分隔符。
    • 唯一能违反以上命名规则的,是一些循环中需要用到的自增变量。 如:

    格式 

      1、行宽原则上不超过80列,把22寸的显示屏都占完,怎么也说不过去;

      2、尽量不使用非ASCII字符,如果使用的话,参考 UTF-8 格式(尤其是 UNIX/Linux 下,Windows 下可以考虑宽字符),尽量不将字符串常量耦合到代码中,比如独立出资源文件,返不仅仅是风格问题了;

      3、UNIX/Linux下无条件使用空格,MSVC的话使用 Tab 也无可厚非; (我没用过Linux,不懂为什么在Linux下无条件使用空格)

      4、函数参数、逻辑条件、初始化列表:要么所有参数和函数名放在同一行,要么所有参数并排分行;

      5、除函数定义的左大括号可以置于行首外,包括函数/类/结极体/枚举声明、各种语句的左大括号置于行尾,所有右大括号独立成行;

      6、./->操作符前后丌留空格,*/&不要前后都留,一个就可,靠左靠右依各人喜好;

      7、预处理指令/命名空间不使用额外缩进,类/结构体/枚举/函数/语句使用缩进;

      8、初始化用=还是()依个人喜好,统一就好;

      9、return不要加();

      10、水平/垂直留白不要滥用,怎么易读怎么来。 

    函数注释

    所有的参数都应该有文档说明(param),所有的返回代码都应该有文档说明(return),所有的例外都应该有文档说明(exception)。可以使用(see)引用有关的开发资源。

    注释属性

    一些自动文档工具定义的属性可以包含在文档中,常用的有:

    n  前提条件 (pre)
    定义调用这个函数的前提条件

    n  警告说明 (warning)
    定义一些关于这个函数必须知道的事情。

    n  备注说明 (remarks)
    定义一些关于这个函数的备注信息。

    n  将要完成的工作 (todo)
    说明哪些事情将在不久以后完成

    n  使用例子说明 (example)
    一个图片能表达100句话,一个好的例子能解答1000个问题。

    一、功能分析及实现情况

    · 基本功能:

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

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

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

    · 拓展功能:

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

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

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

    · 高级功能:

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

    原因:对于这个模块,还不是很熟悉,出现了很多bug,visualC++6.0运用不熟练,搜索了百度依然没有找到解决方法,但是时间来不及了,我们只有把这个模块放在之后完成。

    二、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

    总结:开发的时间远远超出自己所规划的时间,复审也超出了自己预计的时间,事后总结虽然自己规定的时间是那么多,但是两个人的意见不一样,所以时间也超出了

    ,就这次的设计而言,我还是有些不满意的,对于时间上的规划没有预计好,下次一定会有进步的。

     

     三、代码审核

               代码自审

    代码互审

    代码评价

    合并代码

    根据共同的编码规范我们各自审查了自己的代码,总结了以下不足:

    1.检查函数名,函数名称不规范,没有让人看出函数的功能。

    2.检查注释,注释太少,没有具体的描述

    3.检查规格,没有在该留空格的时候打上空格。

    4.检查头文件,头文件命名有问题

    根据共同的编码规范我审查了伙伴的代码,总结了以下不足和好处:

    1.检查函数名,函数名称规范,还写出了必要的注释。

    2.检查注释,有些地方没有注释。

    3.检查规格,格式规范,{}都是单行,函数之间也有空行。

    4.检查头文件,头文件没有问题。

    总体来说代码很清晰,有简单的注释,就是在命名方面还不够严谨。 合并代码时,我们统一了命名,在必要的地方加上了注释,规定了代码字体大小。

    四.关键代码

    1.基本功能

    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 != '
    ') && (code != '	'));	//判断是否是字符	
    
    	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;
    }
    int Orrid(char *Path)
    {
    	/*FILE *file = fopen(Path, "r");
        assert(file != NULL);
    	printf("code count: %d
    ", CodeCount(Path)); 
    	printf("word count: %d
    ", WordCount(Path));
        printf("line count: %d
    ", LineCount(Path));*/
    	int a,b,c;
    	FILE *fp1=fopen(Path,"w");
    	printf("字符数,单词数,行数:
    ");
        scanf("%d %d %d",&a,&b,&c);
    	fprintf(fp1,"该文本文件的字符数为:%d
    ",a);
        fprintf(fp1,"该文本文件的单词数为:%d
    ",b);
        fprintf(fp1,"该文本文件的行数为:%d
    ",c);
        fclose(fp1);
    	return 0;
    

      

     2.特殊行数计算

    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) != ''; 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) == '
    ');	//注释后换行情况
    			}
    		}		
    		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
    ", codecount, annocount, blankcount);
    }
    

      3.通过递归实现文件遍历:

    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) != '') {	//找出文件名和文件类型的位置
    		if (*(Path + i) == '\')
    			FileName = Path + i + 1;
    		if (*(Path + i) == '.')
    			FileType = Path + i + 1;
    		i++;
    	}
    	
    	strcpy(Temp, FileType);//调整字符串
    	*FileType = '*';
    	*(FileType + 1) = '';
    	
    	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) != ''; i++) {
    				*(FileName + i) = *(FileData.name + i);
    			}
    			*(FileName + i) = '\';
    			*(FileName + i + 1) = '';
    			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("
    ");
    
    				strcpy(FileName, Temp);//恢复字符串
    			}
    		}
    	} while (_findnext(Head, &FileData) == 0);
    
    	_findclose(Head);	
    }
    

      4.启动他们的函数

    void Run(char Type, char Type2, char *Path) {
    	
    	switch (Type) {
    	case 'c': printf("code count: %d
    ", CodeCount(Path)); break;
    	case 'w': printf("word count: %d
    ", WordCount(Path)); break;
    	case 'l': printf("line count: %d
    ", LineCount(Path)); break;
    	case 'a': AllDetail(Path); break;
    	case 's': Scan(Path, Type2); break;
        case 'o':Orrid(Path);break;
    	default: printf("type input error"); break;
    	}
    }
    

    五.测试结果

    1.测试行数

    2.测试字符数

    3.测试单词数

    4.多种行数计算测试

    5.遍历文件

    测试所用的文件

    1.c

    该文本文件的字符数为:64
    该文本文件的单词数为:0
    该文本文件的行数为:3
    

    2.c

    hhhhhhhhhh
    jjj
    hhh
    qqq
    kkk
    

    3.c

    mmm
    #include<stdio.h>
    int main()
    {
    
      printf("hello");
      return 0;
    }
    

    4.c

    ddd
    
    come on
    baby
    !!!
    

    5.c

    hhhhhhhhhhhhh
    
    hhhhh
    hhhh
    hhh

    六 总结

    对于这个结对编程,在过程中,我们遇见了很多的问题,其中一些被我们解决了,但仍然存在问题,在这个过程中,两个人之间遇见了很多不同的意见,我们需要磨合。也需要熟悉各自之间的编程模式。

      

  • 相关阅读:
    个人项目(零)
    个人项目
    H5页面键盘弹出,遮挡输入框问题(转文)
    UEditor 使用setContent()遇到的奇葩问题
    限制textarea每行输入N个字符串
    权限管理简易实现
    使用git上传github遇到的问题
    跟随鼠标移动的遮罩层
    Web字体大揭秘
    @media的使用
  • 原文地址:https://www.cnblogs.com/best-future/p/9798802.html
Copyright © 2020-2023  润新知