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

  1. if(fgets(buf, 256, in) == NULL){
  2. printf("ERROR: file input error\n");
  3. return 0;
  4. }
  5. h = atoi(buf);
  6. if(h == 0 && buf[0] != '0'){
  7. printf("ERROR: file input error\n");
  8. return 0;
  9. }
  10. if(fgets(buf, 256, in) == NULL){
  11. printf("ERROR: file input error\n");
  12. return 0;
  13. }
  14. l = atoi(buf);
  15. if(l == 0 && buf[0] != '0'){
  16. printf("ERROR: file input error\n");
  17. return 0;
  18. }
  19.  
  20. num = (int **)malloc(h * sizeof(int));
  21. for(i = 0; i < h; i++)
  22. num[i] = (int *)malloc(l * sizeof(int));
  23. for(i = 0; i < h; i++){
  24. if(fgets(buf, 256, in) == NULL){
  25. printf("ERROR: file input error\n");
  26. return 0;
  27. }
  28. for(j = 0; j < l; j++){
  29. p = (j == 0 ? strtok(buf, ",") : strtok(NULL, ","));
  30. if(p == NULL){
  31. printf("ERROR: file input error\n");
  32. return 0;
  33. }
  34. num[i][j] = atoi(p);
  35. if(num[i][j] == 0 && p[0] != '0'){
  36. printf("ERROR: file input error\n");
  37. return 0;
  38. }
  39. }
  40. }

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

  1. for(i = 0; i < h; i++){
  2. for(j = i; j < (isv ? h+i : h); j++){
  3. super = num[0][0];
  4. for(m = 0; m < (ish ? l : 1); m++){
  5. max = sum(h, l, i, j, m, num);
  6. maxend = max;
  7. tmpsum = sum(h, l, i, j, k, num);
  8. maxend = maxend+tmpsum > tmpsum ? maxend+tmpsum : tmpsum;
  9. max = max > maxend? max : maxend;
  10. }
  11. super = super > max ? super : max;
  12. }
  13. }

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

  1. ult = num[0][0];
  2. for(i = 0; i < h; i++){
  3. for(j = i; j < (isv ? h+i : h); j++){
  4. super = num[0][0];
  5. for(m = 0; m < (ish ? l : 1); m++){
  6. if(!sum(&max, h, l, i, j, m, num)){
  7. printf("ERROR: int overflow\n");
  8. return 0;
  9. }
  10. maxend = max;
  11. for(k = m+1; k < (ish ? l+m : l); k++){
  12. if(!sum(&tmpsum, h, l, i, j, k, num)){
  13. printf("ERROR: int overflow\n");
  14. return 0;
  15. }
  16. if((maxend > 0 && tmpsum > 0 && (maxend+tmpsum <= maxend || maxend+tmpsum <= tmpsum)) || (maxend < 0 && tmpsum < 0 && (maxend+tmpsum >= maxend || maxend+tmpsum >= tmpsum))){
  17. printf("ERROR: int overflow\n");
  18. return 0;
  19. }
  20. maxend = maxend+tmpsum > tmpsum ? maxend+tmpsum : tmpsum;
  21. max = max > maxend ? max : maxend;
  22. }
  23. super = max > super ? max : super;
  24. }
  25. ult = super > ult ? super : ult;
  26. }
  27. }

关于溢出

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

  1. int sum(int *tmpsum, int h, int l, int i, int j, int k, int **num){
  2. int a, tmpnum, s = 0;
  3. *tmpsum = 0;
  4. for(a = i; a <= j; a++){
  5. tmpnum = num[(a >= h ? a-h : a)][(k >= l ? k-l : k)];
  6. s = *tmpsum + tmpnum;
  7. if((*tmpsum > 0 && tmpnum > 0 && (s <= *tmpsum || s <= tmpnum)) || (*tmpsum < 0 && tmpnum < 0 && (s >= *tmpsum || s >= tmpnum)))
  8. return 0;
  9. *tmpsum = s;
  10. }
  11. return 1;
  12. }

关于设计

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

关于感想

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

完整的源码

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4.  
  5. int sum(int *tmpsum, int h, int l, int i, int j, int k, int **num){
  6. int a, tmpnum, s = 0;
  7. *tmpsum = 0;
  8. for(a = i; a <= j; a++){
  9. tmpnum = num[(a >= h ? a-h : a)][(k >= l ? k-l : k)];
  10. s = *tmpsum + tmpnum;
  11. if((*tmpsum > 0 && tmpnum > 0 && (s <= *tmpsum || s <= tmpnum)) || (*tmpsum < 0 && tmpnum < 0 && (s >= *tmpsum || s >= tmpnum)))
  12. return 0;
  13. *tmpsum = s;
  14. }
  15. return 1;
  16. }
  17.  
  18. int main(int argc, char *argv[]){
  19. int h, l, i, j, k, m, max, maxend, **num, ult, super, tmpsum, isv = 0, ish = 0;
  20. char buf[257], *p;
  21. FILE *in;
  22. for(i = 1; i < argc-1; i++){
  23. if(!strcmp(argv[i], "/v"))
  24. isv = 1;
  25. else if(!strcmp(argv[i], "/h"))
  26. ish = 1;
  27. else if(!strcmp(argv[i], "/a")){
  28. printf("ERROR: \"/a\" not support yet\n");
  29. return 0;
  30. }
  31. else{
  32. printf("ERROR: command input error\n");
  33. return 0;
  34. }
  35. }
  36. if((in = fopen(argv[argc-1], "r")) == NULL){
  37. printf("ERROR: file open failed\n");
  38. return 0;
  39. }
  40. if(fgets(buf, 256, in) == NULL){
  41. printf("ERROR: file input error\n");
  42. return 0;
  43. }
  44. h = atoi(buf);
  45. if(h == 0 && buf[0] != '0'){
  46. printf("ERROR: file input error\n");
  47. return 0;
  48. }
  49. if(fgets(buf, 256, in) == NULL){
  50. printf("ERROR: file input error\n");
  51. return 0;
  52. }
  53. l = atoi(buf);
  54. if(l == 0 && buf[0] != '0'){
  55. printf("ERROR: file input error\n");
  56. return 0;
  57. }
  58.  
  59. num = (int **)malloc(h * sizeof(int));
  60. for(i = 0; i < h; i++)
  61. num[i] = (int *)malloc(l * sizeof(int));
  62. for(i = 0; i < h; i++){
  63. if(fgets(buf, 256, in) == NULL){
  64. printf("ERROR: file input error\n");
  65. return 0;
  66. }
  67. for(j = 0; j < l; j++){
  68. p = (j == 0 ? strtok(buf, ",") : strtok(NULL, ","));
  69. if(p == NULL){
  70. printf("ERROR: file input error\n");
  71. return 0;
  72. }
  73. num[i][j] = atoi(p);
  74. if(num[i][j] == 0 && p[0] != '0'){
  75. printf("ERROR: file input error\n");
  76. return 0;
  77. }
  78. }
  79. }
  80. ult = num[0][0];
  81. for(i = 0; i < h; i++){
  82. for(j = i; j < (isv ? h+i : h); j++){
  83. super = num[0][0];
  84. for(m = 0; m < (ish ? l : 1); m++){
  85. if(!sum(&max, h, l, i, j, m, num)){
  86. printf("ERROR: int overflow\n");
  87. return 0;
  88. }
  89. maxend = max;
  90. for(k = m+1; k < (ish ? l+m : l); k++){
  91. if(!sum(&tmpsum, h, l, i, j, k, num)){
  92. printf("ERROR: int overflow\n");
  93. return 0;
  94. }
  95. if((maxend > 0 && tmpsum > 0 && (maxend+tmpsum <= maxend || maxend+tmpsum <= tmpsum)) || (maxend < 0 && tmpsum < 0 && (maxend+tmpsum >= maxend || maxend+tmpsum >= tmpsum))){
  96. printf("ERROR: int overflow\n");
  97. return 0;
  98. }
  99. maxend = maxend+tmpsum > tmpsum ? maxend+tmpsum : tmpsum;
  100. max = max > maxend ? max : maxend;
  101. }
  102. super = max > super ? max : super;
  103. }
  104. ult = super > ult ? super : ult;
  105. }
  106. }
  107. printf("%d\n", ult);
  108. }

  

关于这个表

 

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. VC++ : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall std::basic_string<wchar_t,struct std::char_traits<wchar_t>

    最近学习Google Breakpad,将其用在了自己的项目中,编译的版本为VS2010,没有什么问题.但是为了和之前的程序兼容,需要使用VS2008版本的程序,于是又编译了VS2008版本的代码,但 ...

  2. 泛型T的类型获取

    T.getClass()或者T.class都是非法的,因为T是泛型变量. 由于一个类的类型是什么是在编译期处理的,故不能在运行时直接在Base里得到T的实际类型. /** * 可以在service层直 ...

  3. php 导出excle的.csv格式的数据时乱码问题

    1.header('Content-Encoding: XXXX'); 有可能是编码问题:可以尝试UTF-8,GBK,GB2312,等编码格式 2.有可能是文件编码问题,虽然UTF-8不建议带BOM, ...

  4. 从APP跳转到WI-FI

    之前以为,苹果不支持直接从应用跳到系统设置里的WiFi界面.后来发现,这个小功能是可以实现的,而且实现起来并不麻烦.让我们一起来看看吧! 需求 从应用跳到系统设置里的WiFi界面有这个需求存在吗?答案 ...

  5. Lattice FIFO 使用之FIFO_DC输入输出宽度不同时 的一个注意事项

    在使用FIFO_DC的时候,我们知道这个FIFO的一个功能是可以输入输出的数据宽度不一样,比如: 输入数据为128bit,输出数据为16bit,FIFO内部可以实现这样的转换,但是输出的时候是先送出一 ...

  6. httpclient 使用方式介绍

    第一:Get方式请求 package com.hct; import java.io.BufferedReader; import java.io.IOException; import java.i ...

  7. pem转换成der

    openssl x509 -in xxxxx.pem -inform PEM -out xxxx.der -outform DER [root@NB Desktop]# file xxxx.der

  8. JavaScript通过id获取不到元素是什么原因阿?

    s代码 JavaScript code   ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function show_more_mess() {     $(&qu ...

  9. python学习笔记-进程线程

    1.什么是进程(process)? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述 ...

  10. 用python实现一个不排序的列表功能

    #!/usr/bin/env python # -*- coding: utf-8 -*- # learn <<Problem Solving with Algorithms and Da ...