免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: pmerofc
打印 上一主题 下一主题

垃圾代码分析——C语言二维数组范例 [复制链接]

论坛徽章:
0
91 [报告]
发表于 2012-04-09 16:17 |只看该作者
OwnWaterloo 发表于 2012-04-09 15:55
回复 83# pmerofc

关键是……  与qsort扯到一起了……  那个可恶的原型: int (*cmp)(void const* a, v ...


struct封装一下其实也可以的

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
92 [报告]
发表于 2012-04-09 16:19 |只看该作者
回复 87# 陈良乔

可以吐槽的地方太多了……  都不知道从哪说起……


省略int,C89是允许的,C++是不允许的。C99忘记具体怎么说了,要么是废弃,要么是错误。
for中的作用域: C89是不允许的, C++/C99允许。
用const int 作为数组维度: C89是不允许的, C++允许。 C99也允许, 但意义与C++不同。

如果说省略int,按你的说法是复制到blog上时出错 —— 这么明显的问题你自己真没看出来?与pmerofc扯这么久最终他还是忍不住说了你才看出来? —— 那也应该是C99或者C++。
但VC对C99的支持有限……  于是只能是C++了。
最后再看文章标题《C语言二维数组范例》…… (BTW:你的blog换地方了?  记得以前是CU符号那种橙色……)


如果要解决"有效元素个数", 最常规的就是将这个信息分开存放。
即使要学NULL terminated string那种,用负数(不存在负分也算合理)也比0好吧,然后在输入的时候将负数的情况处理掉(向用户报告,要求重新输入,或者当作0处理)。
否则就只能将定长信息(有效个数)放在变长信息(每个分数)之前。 另外定义一个结构体或者将数组的0个元素作为有效个数,后面的作为分数也行。
这样qsort调用cmp,在cmp里才能获取到有效个数的信息。

不过这样也只是将程序改正确, 但也许与《二维数组范例》冲突了。


你可以换用其他例子作为二维数组的范例。 而且避免与qsort扯到一起。 所以我说你不会选材……

论坛徽章:
0
93 [报告]
发表于 2012-04-09 16:30 |只看该作者
本帖最后由 AD8018 于 2012-04-09 16:32 编辑
陈良乔 发表于 2012-04-09 15:51
是的,这里有对应用场景的一个假设,就是必须以0来表示结束

如果你非要说不输入0,那就要增加代码来 ...


这个根源,OwnWaterloo说的对,qsort那个可恶的原型。

修改可以仿效此代码的做法,数组第一个元素当长度用
http://bbs.chinaunix.net/thread-3705842-1-1.html

更简单的修改,如果不允许0,确保最后能有一个0即可。

  1.         int j;
  2.         for(j = 0; j < stnum - 1; ++j)
  3.         {
  4.             scanf("%d",&scores[i][j]);
  5.             if(0 == scores[i][j])
  6.                 break;
  7.         }
  8.         scores[i][j] = 0;
复制代码

论坛徽章:
0
94 [报告]
发表于 2012-04-09 16:37 |只看该作者
AD8018 发表于 2012-04-09 16:30
这个根源,OwnWaterloo说的对,qsort那个可恶的原型。

修改可以仿效此代码的做法,数组第一个元素当 ...


受教了,我也把问题想复杂了,竟然连struct都想出来了,数组第一个元素保存个数更简单

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
95 [报告]
发表于 2012-04-09 17:14 |只看该作者
假设某源代码文件定义了二维数组用于存储日志
#define RECORD_SIZE 32
static char s_log_http[1048576][RECORD_SIZE];
另一个源文件调用函数log_search_http()获取日志内容
那么我会这么设计
声明在某.h文件:
int log_search_http(char result[], int size[2], struct search_para *para);
调用的时候
char result[4096];
int size[2] = {4096, 64};//结果存储在4096大小的空间,最多64条
函数log_search_http在运行的时候拷贝不超过64条并且不超过4096字节的内容到result中
在函数返回前设置size[2] = {RECORD_SIZE, num};
意即:每条记录长度32字节,共计num条
将来不管那个二维数组怎么变,都不会溢出或错位,唯一影响的是result的利用率就是了

论坛徽章:
0
96 [报告]
发表于 2012-04-09 17:40 |只看该作者
回复 92# OwnWaterloo

谢谢你,受教了

省略int这个问题就不用讨论了,明显的一个复制粘贴的错误

  C++/C99允许。
用const int 作为数组维度: C99支持,我用的是这个标准

(BTW:你的blog换地方了?  记得以前是CU符号那种橙色……)
换了,blogbus不太稳定,换到http://chenlq.net了,欢迎访问交流啊


如果要解决"有效元素个数",
// 这里我选择了用0作为输入结束,你这样一提醒,我还真少了对负数的处理,谢谢你

// 你说的这些方法确实可以解决问题,但是就像我说的,他也会增加代码的复杂度,这里有一个权衡的问题
// 我想了想,觉得还是保留数组最后一个始终为0,最多只能输入stnum-1个有效数据更简单一些




你可以换用其他例子作为二维数组的范例。 而且避免与qsort扯到一起。 所以我说你不会选材……

你能提供一个更好的例子吗?


   

论坛徽章:
0
97 [报告]
发表于 2012-04-09 18:14 |只看该作者
本帖最后由 三月廿七 于 2012-04-09 18:15 编辑

回复 96# 陈良乔


    杨辉三角 是史上最经典的二维数组例程, 融 动态内存分配、变长数组、组合、动态规划、递归等重点知识于一体
二维数组 不提 杨辉三角 就是 失败 !

论坛徽章:
0
98 [报告]
发表于 2012-04-09 18:24 |只看该作者
三月廿七 发表于 2012-04-09 18:14
回复 96# 陈良乔


谢谢你,我去了解一下,以前还真不知道杨辉三角有这样的作用,以前只是知道这个名字

论坛徽章:
0
99 [报告]
发表于 2012-04-09 18:28 |只看该作者
作了一些修改,大家帮忙看看还有什么问题
#include <stdio.h>
#include <stdLib.h>
#include <memory.h>

int main()
{
        // 定义保存批量数据的二维数组,
        // 并用memset()函数完成数组的初始化
        const int classnum = 6;
        const int stnum = 100;
                // 这个定义和初始化也可以更简单地写成
        // int scores[classnum][stnum] = {0};
        int scores[classnum][stnum]];
                memset(scores,0,classnum*stnum*sizeof(intscores));
       
        // 利用for语句完成数据的输入
        // 逐个班级循环
for(int i = 0; i < classnum;++i)
        {
                printf("please input the  scores of class %d:\n",i+1);
                // 逐个学生循环
                   // 这里我们需要将数组的最后一个元素预留为0,
                // 表示数组的结束,防止数组访问越界
                // 所以输入循环的最大次数是stnum-1
for(int j = 0; j < stnum-1; ++j)
                {
                        // 将输入的数据保存到scores[i][j]
                        scanf("%d",&scores[i][j]);

                        // 判断刚刚输入的数据是否为0,
                        // 如果为0,则利用break结束本层循环
                        if(0 == scores[i][j])
                        {
                                break;
                        }
                        // 判断输入的数据是否为负数
                        // 如果是,则提示用户重新输入
                        else if(scores[i][j] < 0)
                        {
                                puts("ERROR! the score must be greater than 0.");
                                --j;  // 撤销本次输入增加的序号
                        }
                }
        }
       
// …
       
return 0;
}


// 获得一维数组的平均值
float getaver(int* st)
{
        int count = 0;
        floatint total = 0.0;
        // 只要没有遇到表示数据结束的0值,
// 就一直累加所有数据的值
while(0!=*st)
        {
                ++count;                // 数据个数加1
                total += *st;          // 累加数据
                ++st;  // 指向下一个数据
        }
       
        // 返回平均值
if( 0 == count )  // 对没有元素的情况作特殊处理
{
        return 0.0;
}
else
{
        return (float)total/count;
}
         
}

// 通过数组的平均值大小进行比较
int cmp(const void* a, const void* b)
{
        // 获得两个数组的平均值
        float avera = getaver((int*)a);
        float averb = getaver((int*)b);

        // 返回比较结果
        return avera - averb;
}
int main()
{
        // …
       
        // 利用qsort()函数对二维数组进行排序
        qsort(scores,  // 数组名,也就是数组首地址
                classnum,        // 数组元素个数
                stnum*sizeof(int),        // 每个数据元素占用的空间
                cmp);        // 比较规则函数

        return 0;
}

论坛徽章:
0
100 [报告]
发表于 2012-04-09 18:30 |只看该作者
有些该删掉的没有删掉
比如floatint之类的,见谅
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP