关于输入
  先来说说关于输入的事情。其实我最一开始并没有发现输入数字之间是用逗号隔开的,所以我是当做空格隔开来写的,后来发现以后匆忙改正,利用strtok与atoi函数从字符串中提取出用逗号隔开的数字。由于作业中的要求说任何输入错误都不能使我的程序崩溃,所以所有与输入有关的地方都加了一个判断,发生错误时将对应的错误打印出来并结束程序。这是输入部分的代码:

if(fgets(buf, 256, in) == NULL){
printf("ERROR: file input error\n");
return 0;
}
h = atoi(buf);
if(h == 0 && buf[0] != '0'){
printf("ERROR: file input error\n");
return 0;
}
if(fgets(buf, 256, in) == NULL){
printf("ERROR: file input error\n");
return 0;
}
l = atoi(buf);
if(l == 0 && buf[0] != '0'){
printf("ERROR: file input error\n");
return 0;
} num = (int **)malloc(h * sizeof(int));
for(i = 0; i < h; i++)
num[i] = (int *)malloc(l * sizeof(int));
for(i = 0; i < h; i++){
if(fgets(buf, 256, in) == NULL){
printf("ERROR: file input error\n");
return 0;
}
for(j = 0; j < l; j++){
p = (j == 0 ? strtok(buf, ",") : strtok(NULL, ","));
if(p == NULL){
printf("ERROR: file input error\n");
return 0;
}
num[i][j] = atoi(p);
if(num[i][j] == 0 && p[0] != '0'){
printf("ERROR: file input error\n");
return 0;
}
}
}

关于算法
  我的算法是从之前的一维算法扩展而来的。首先我解决的是最普通情况下的二维数组,我是这样想的:首先确定一个子矩阵的上下边界,这样子的话,上下边界之间的每一列之和就可以看做一个数,然后就可以利用一维数组的方法在O(n)时间内找出此时确定的上下边界的最大子矩阵的和,关于一维算法可以查阅我的上一篇博客:链接。这样我们利用一个嵌套的循环将上下边界扫描一遍,于是通过比较就得出了整个二维数组的最大子数组的和,时间复杂度是O(n^3)。这是最初的功能代码:

	for(i = 0; i < h; i++){
for(j = i; j < (isv ? h+i : h); j++){
super = num[0][0];
for(m = 0; m < (ish ? l : 1); m++){
max = sum(h, l, i, j, m, num);
maxend = max;
tmpsum = sum(h, l, i, j, k, num);
maxend = maxend+tmpsum > tmpsum ? maxend+tmpsum : tmpsum;
max = max > maxend? max : maxend;
}
super = super > max ? super : max;
}
}

  可是/h和/v怎么办呢?我在程序中对应功能部分都增加了对应的独立的判断,以面对功能的要求。因为我将/v与/h的判断完全放在主功能代码中,而且两者完全独立互不干扰,这样就保证了当两个参数同时存在时也不需要改变代码就可以支持,而且参数的位置变化也没有影响。具体先来看/v好了,/v表示二维数组在垂直方向是首尾相连的。我的做法是在跳出循环的边界判断中增加一个判断,如果/v那么下边界一直循环到起始边界加上总行数,在计算和时如果遇到大于等于行数的数字就减去行数,这样就做到了从下边界一直从起始边界一直循环到起始边界的上一行,也就是保证了竖直方向的首尾互联。如果有/h的话在水平方向的首尾相连也使用相同的处理方法,所不同的是,原来在水平方向只要进行一次O(n)的扫描就可以了,但是如果首尾相连了,为了找出最大的值,那么需要将每一列作为起点扫描一次,也就是说水平方向的扫描需要再加一层循环也就是O(n^2)的复杂度,那么整个算法就变成了O(n^4)的复杂度。如果同时有/v与/h则不需要改变算法直接进行计算。支持/v与/h的功能代码如下:

ult = num[0][0];
for(i = 0; i < h; i++){
for(j = i; j < (isv ? h+i : h); j++){
super = num[0][0];
for(m = 0; m < (ish ? l : 1); m++){
if(!sum(&max, h, l, i, j, m, num)){
printf("ERROR: int overflow\n");
return 0;
}
maxend = max;
for(k = m+1; k < (ish ? l+m : l); k++){
if(!sum(&tmpsum, h, l, i, j, k, num)){
printf("ERROR: int overflow\n");
return 0;
}
if((maxend > 0 && tmpsum > 0 && (maxend+tmpsum <= maxend || maxend+tmpsum <= tmpsum)) || (maxend < 0 && tmpsum < 0 && (maxend+tmpsum >= maxend || maxend+tmpsum >= tmpsum))){
printf("ERROR: int overflow\n");
return 0;
}
maxend = maxend+tmpsum > tmpsum ? maxend+tmpsum : tmpsum;
max = max > maxend ? max : maxend;
}
super = max > super ? max : super;
}
ult = super > ult ? super : ult;
}
}

关于溢出

  由于需要考虑溢出,那么在程序中所有用到加法运算的地方都需要判断,那么我将sum函数改进了一下,它的返回值不再是运算结果,而是是否正确进行运算,成功则返回1,返回0表示发生了溢出,运算结果有指针传入到主函数中,同时在主函数中的运算加上了溢出判断,判断的方法是这样子的:如果相加的两数都为正并且其中至少有一个数比和还大,或者相加两数都是负数并且其中至少有一个数比和还小,那么说明发生了溢出。发生溢出之后打印出溢出错误并结束程序。改进后的sum函数如下:

int sum(int *tmpsum, int h, int l, int i, int j, int k, int **num){
int a, tmpnum, s = 0;
*tmpsum = 0;
for(a = i; a <= j; a++){
tmpnum = num[(a >= h ? a-h : a)][(k >= l ? k-l : k)];
s = *tmpsum + tmpnum;
if((*tmpsum > 0 && tmpnum > 0 && (s <= *tmpsum || s <= tmpnum)) || (*tmpsum < 0 && tmpnum < 0 && (s >= *tmpsum || s >= tmpnum)))
return 0;
*tmpsum = s;
}
return 1;
}

关于设计

  我的设计中所有功能都在同一个功能块中完成,每一种不同的功能都有对应的判断,而每一种功能之间相互独立互相不影响,这就保证了我的程序能利用一个功能块完成所有的功能,所以我在分别完成/v与/h的同时也完成了/v、/h同时存在的情况。这种结构方式虽然不清晰,但是在这种短小的程序中还是非常实用的。

关于感想

  恕我愚昧到现在为止实在是无法写出/a的算法,我思索了很久,最终还是选择了放弃,所以在现在的程序中如果在命令行中输入参数/a则会打印出错误,错误原因是程序目前不支持/a。还有关于单元测试与代码覆盖率的问题,由于我的代码完全是用C语言写的,我暂时还不知道如何利用Visual Studio 2012作C语言这种面向过程程序的单元测试,所以这部分暂时空缺,待日后弄清楚以后补上。此次作业给我最大的感想就是/a的实现真的真的真的好难啊,完全超出了我能够驾驭的范围。

完整的源码

#include<stdio.h>
#include<stdlib.h>
#include<string.h> int sum(int *tmpsum, int h, int l, int i, int j, int k, int **num){
int a, tmpnum, s = 0;
*tmpsum = 0;
for(a = i; a <= j; a++){
tmpnum = num[(a >= h ? a-h : a)][(k >= l ? k-l : k)];
s = *tmpsum + tmpnum;
if((*tmpsum > 0 && tmpnum > 0 && (s <= *tmpsum || s <= tmpnum)) || (*tmpsum < 0 && tmpnum < 0 && (s >= *tmpsum || s >= tmpnum)))
return 0;
*tmpsum = s;
}
return 1;
} int main(int argc, char *argv[]){
int h, l, i, j, k, m, max, maxend, **num, ult, super, tmpsum, isv = 0, ish = 0;
char buf[257], *p;
FILE *in;
for(i = 1; i < argc-1; i++){
if(!strcmp(argv[i], "/v"))
isv = 1;
else if(!strcmp(argv[i], "/h"))
ish = 1;
else if(!strcmp(argv[i], "/a")){
printf("ERROR: \"/a\" not support yet\n");
return 0;
}
else{
printf("ERROR: command input error\n");
return 0;
}
}
if((in = fopen(argv[argc-1], "r")) == NULL){
printf("ERROR: file open failed\n");
return 0;
}
if(fgets(buf, 256, in) == NULL){
printf("ERROR: file input error\n");
return 0;
}
h = atoi(buf);
if(h == 0 && buf[0] != '0'){
printf("ERROR: file input error\n");
return 0;
}
if(fgets(buf, 256, in) == NULL){
printf("ERROR: file input error\n");
return 0;
}
l = atoi(buf);
if(l == 0 && buf[0] != '0'){
printf("ERROR: file input error\n");
return 0;
} num = (int **)malloc(h * sizeof(int));
for(i = 0; i < h; i++)
num[i] = (int *)malloc(l * sizeof(int));
for(i = 0; i < h; i++){
if(fgets(buf, 256, in) == NULL){
printf("ERROR: file input error\n");
return 0;
}
for(j = 0; j < l; j++){
p = (j == 0 ? strtok(buf, ",") : strtok(NULL, ","));
if(p == NULL){
printf("ERROR: file input error\n");
return 0;
}
num[i][j] = atoi(p);
if(num[i][j] == 0 && p[0] != '0'){
printf("ERROR: file input error\n");
return 0;
}
}
}
ult = num[0][0];
for(i = 0; i < h; i++){
for(j = i; j < (isv ? h+i : h); j++){
super = num[0][0];
for(m = 0; m < (ish ? l : 1); m++){
if(!sum(&max, h, l, i, j, m, num)){
printf("ERROR: int overflow\n");
return 0;
}
maxend = max;
for(k = m+1; k < (ish ? l+m : l); k++){
if(!sum(&tmpsum, h, l, i, j, k, num)){
printf("ERROR: int overflow\n");
return 0;
}
if((maxend > 0 && tmpsum > 0 && (maxend+tmpsum <= maxend || maxend+tmpsum <= tmpsum)) || (maxend < 0 && tmpsum < 0 && (maxend+tmpsum >= maxend || maxend+tmpsum >= tmpsum))){
printf("ERROR: int overflow\n");
return 0;
}
maxend = maxend+tmpsum > tmpsum ? maxend+tmpsum : tmpsum;
max = max > maxend ? max : maxend;
}
super = max > super ? max : super;
}
ult = super > ult ? super : ult;
}
}
printf("%d\n", ult);
}

  

关于这个表

 

Personal Software Process Stages

时间百分比(%)

实际花费的时间 (分钟)

原来估计的时间 (分钟)

Planning

计划

Estimate

估计这个任务需要多少时间,把工作细化并大致排序

2

20 min

10 min

Development

开发

Analysis

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

1

10 min

20 min

Design Spec

生成设计文档

0

0 min

0 min

Design Review

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

0

0 min

0 min

Coding Standard

代码规范 (制定合适的规范)

3

30 min

20 min

Design

具体设计

11

100 min

60 min

Coding

具体编码

32

300 min

200 min

Code Review

代码复审

22

200 min

150 min

·         Test

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

120 min

120 min

Reporting

总结报告

·         Test Report

测试报告

13

120 min

100 min

·         Size Measurement

计算工作量

1

10 min

10 min

·         Postmortem & Improvement Plan

事后总结, 并提出改进

1

10 min

10 min

Total

总计

100%

920min

700min

  

homework-02的更多相关文章

  1. day 02 ---class - homework

    # -*- coding: utf-8 -*-# @Time : 2018/12/20 14:34# @Author : Endless-cloud# @Site : # @File : day 02 ...

  2. 软件工程 week 02

    一.地址链接 1.作业地址:https://edu.cnblogs.com/campus/nenu/2016CS/homework/2110 2.git仓库地址:https://git.coding. ...

  3. 作业要求20181204-7 Final阶段第1周/共1周 Scrum立会报告+燃尽图 02

    作业要求参见https://edu.cnblogs.com/campus/nenu/2018fall/homework/2481 版本控制地址https://git.coding.net/lglr20 ...

  4. 20181009-3 选题 Scrum立会报告+燃尽图 02

    Scrum立会报告+燃尽图(02)选题 此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2191 一.小组介绍 组长:刘莹莹 ...

  5. Beta阶段第2周/共2周 Scrum立会报告+燃尽图 02

    此作业要求参见:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2410] 版本控制地址   https://git.coding.net ...

  6. 作业要求20181113-4 Beta阶段第1周/共2周 Scrum立会报告+燃尽图 02

    作业要求:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2384 版本控制:[https://git.coding.net/lglr201 ...

  7. Alpha阶段第2周/共2周 Scrum立会报告+燃尽图 02

    此次作业要求参见 [https://edu.cnblogs.com/campus/nenu/2018fall/homework/2285] Scrum master:祁玉 一.小组介绍 组长:王一可 ...

  8. 20181016-4 Alpha阶段第1周/共2周 Scrum立会报告+燃尽图 02

    此次作业要求参见 [https://edu.cnblogs.com/campus/nenu/2018fall/homework/2247] Scrum master:祁玉 一.小组介绍 组长:王一可 ...

  9. c语言1博客作业02

    c语言1博客作业02 这个作业属于哪个课程 C语言程序设计 这个作业的要求在哪 [作业要求](https://edu.cnblogs.com/campus/zswxy/SE2019-2/homewor ...

  10. | C语言I作业02

    C语言I博客作业02 标签: 18软件2班 李煦亮 问题 答案 这个作业属于那个课程 C语言程序设计I 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/C ...

随机推荐

  1. Python之str()与repr()的区别

    Python之str()与repr()的区别 str()一般是将数值转成字符串,主要面向用户.  repr()是将一个对象转成字符串显示,注意只是显示用,有些对象转成字符串没有直接的意思.如list, ...

  2. 创建Odoo8数据库时的“new encoding (UTF8) is incompatible with the encoding of the template database (SQL_ASCII)“问题

    Odoo8创建数据库时,显示如下错误信息: DataError: new encoding (UTF8) is incompatible with the encoding of the templa ...

  3. October 26th Week 44th Wednesday 2016

    No matter how far you may fly, never forget where you come from. 无论飞得多高,也不要忘记起飞的地方. I never forget w ...

  4. MYsql 数据库密码忘记(Linux)

    在Linux 上面装上了 Mysql 数据库,但是发现密码忘了,悲催,解决方法跟Window系统下一样的, 不管是哪个操作系统处理的思路是相同的,就是首先要把mysql的权限去掉,这样即使忘了密码,不 ...

  5. Centos7学习之静态IP设置方法介绍

      1.编辑 ifcfg-eth0 文件,vim 最小化安装时没有被安装,需要自行安装不描述. # vim /etc/sysconfig/network-scripts/ifcfg-eth0 2.修改 ...

  6. WriteableBitmap 给透明的控件截图的问题

    在WP开发中,我们经常会用到截取某一部分区域,然后分享到微博等等,Writeablebitmap 是一个很好的辅助,但是它本身也有一个限制:只有一个 SaveJpeg 方法,因此透明的区域无法保存,都 ...

  7. 当年只会C# 所以写C++就成这样了! log4cplus -> log4net

    属实C++不会. 目前帮朋友弄个小项目需要小折腾一下. c# 一直采用 log4net ,c++的呢,找找有个log4cplus  知识有限,做个通用类吧.别把精力放在这里. 动手创建个静态类. 为了 ...

  8. Python-断言

    断言: assert这个关键字称之为断言,当这个关键字后面的条件为假的时候,程序自动崩溃并抛出AssertionError的异常 例子: >>>assert 3 < 4 Tra ...

  9. Solr4.10.3安装配置

    系统环境 window版本为:windows 8.1 64位 软件环境 JDK版本:1.7 solr版本:4.10.3 tomcat版本:tomcat 7 安装过程 步骤一:将下载好的solr-4.1 ...

  10. display:inline-block的间隙问题和解决办法

    1.display:inline-block在水平方向的间隙: 代码如下: <style type="text/css"> *{margin:0; padding:0; ...