趣味玩意,用Arduino开发板做CPU监视器

Arduino是什么?
不知道自己google去,简单的说就是一个给我这种嵌入式完全不懂的文盲来做机器人之流的电子小玩意的平台,开发很简单,就是类似与c语言的语法,上手极快,关键是还可以通过一定的手段和Andriod联动。
好吧,这次和Andriod无关,只是我突发奇想罢了。我一直希望有个小屏幕可以监视我的系统状态,比如CPU占用,内存占用等等。可惜最便宜的usb屏幕也要1000多块,太贵了,不实惠,于是就萌发用Arduino自己做一个。
设备很简单,就是一块Arduino的板子,一块LCD1602屏幕,一台MAC。我就只做了一个简单的CPU占用的东西,如图:

IMG_9191

先说说我的思路吧,首先从Mac上通过一个程序读取到CPU占用率,然后通过串口发送到板子上,板子上缓冲一下,再输出到LCD屏幕。流程非常简单。不过问题还是蛮多。
首先,怎么读取CPU占用率?
我先是打算用Cocoa的系统函数来调用,查了半天Mac的资料后果断放弃,太复杂了,而且我Object-c又不是很熟悉。之后的想法是打算利用shell程序来完成,通过C和shell中的top命令交互来实现。这里有个小插曲,因为Linux下面其实读取这些可以直接去/proc/这个虚拟目录下读取,但是Mac这类系统是没有这个虚拟目录的,所以只能用top,而且Mac的top函数的参数又和Linux之类的GNU的top不同。总之折腾了很久,才有了下面这句销魂的shell命令

$ top -n0 -l1

啥意思?很简单,就是不要显示进程,top执行一次就自动退出,就那么简单。至于为什么可以达到这样的效果,请有mac或者别的BSD系统的同学man top一下就好。
有了这个就方便的多了,c语言部分去掉串口通讯的就只很简单的一部分了,就是调用shell函数,返回,字符串处理,这几个问题。串口通讯的代码早就很熟悉了,最近一直开发这种东西(其实python下面串口通讯会简单的多,不过我比较熟悉C,所以还是选择了C)
关键代码如下:

FILE *fp; char a[256]; fp=popen("top -n0 -l1","r"); fgets(a,sizeof(a),fp)

之后的过程势如破竹,Arduino平台上的更加容易,就是简单的读写罢了。直接上代码就好:

#include #include LiquidCrystal_I2C lcd(0x27,16,2); byte line = 0; // track which line of the display we are on void setup(){ // set up the LCD's number of columns and rows: lcd.init(); lcd.backlight(); // initialize the serial communications: Serial.begin(9600); lcd.setCursor(0,0); lcd.clear(); } void loop() { char input; while(Serial.available() > 0) { input = Serial.read(); switch(input) { case 0: // line feed lcd.clear(); break; default: if(input>31) lcd.print(input); } } }

最后再上一个图~哈:

IMG_9194

关于一些C语言编程的一些个人想法

首先么,这是个人风格,完全不是权威之说。
第二,记录下来只是感觉自己这样蛮舒服,分享而已。
第三,别拿某为谭姓叫兽的文章来说事情,不解释。
第四,这里的 C 语言不是狭义的指 C 这门语言,也包括 C++,object-c,甚至 Java 等类似与 C语法的语言
────────────────────────────────
好了,下面进入正文。比较琐碎,所以就想到什么讲什么了。
先说说一个判断 0 的问题吧,或者称为判断空值。一般空值常规的来思考分那么几种,NULL,0,0.0 以及 false(可能还有别的,但是常规就这些了,所以就讲这些)。那么这些分别有什么区别呢?
首先说说,写判 0 的风格是为了什么,因为 C 语言可以直接用这么一句话来表示几乎所有的空值
if(!a){}
那么,我要把判 0 的语句分开写,就是为了区别变量的类型,方便阅读代码
倒过来讲,先解释 false 的变量,一般这个变量都是布尔型的变量,那么这个变量就两个值,真或者假。所以我一般选择上面那种
if(!a){}
的方式来表示这个变量为假的时候执行什么。理由吧,个人偏好,也有一点认为,!作为一个逻辑运算符,而布尔是逻辑变量,所以凑在一起刚刚好。
然后是 0.0,这一般指 float 或者 double 的变量,这种变量的一个特点就是不精确。如果你直接用
if(a==0.0){}
之类的方法来表述,可能会出现不可意料的问题。所以这里我也选择一种比较流行的处理方法,就是让一个实型变量和一个极小的误差值 EPS 做比较。比如如下代码:
```

define EPS 1e-9

if(fabs(a-0.0)


就是这种方式,对于一个实型变量,最好把相等的比较转化成为大于小于的比较,原因么,不赘述了,学过组成原理就知道了。

整数变量不多说,最常规的方法



if(a0)


{}



然后是指针一类的,空值为 NULL 的,大家都知道 NULL 就是 0,但是书写的时候,还是最好把 NULL 写上了,这样可读性大大的增加。例:



if(a
NULL)


{}



判断0的问题大约就想到那么一些,然后说说几个小点。

第一个是一个规范问题,一般很多人都喜欢把函数声明和实现都放在一起。特别是类的成员函数,别的函数也一样。其实这个习惯不是很好,C语言也好,C++ 也好,都分为 .h 和 .c(.cpp) 两种文件,一般 .h 文件里面放声明,.c 文件里面放实现,包括成员函数。这个主要是方便别的利用你代码的人方便,不需要繁杂的翻看你的整个实现,只要看 .h 文件就可以对你的函数如何使用一目了然。

第二个是一个小细节,就是 void 参数的使用,这里说的不是



void main()




个人是很反对这种写法的,因为 main() 函数作为系统直接调用的函数,你如果不返回一个值给系统,系统怎么知道你的程序是正常还是不正常的结束的?个人感觉,我很反感用 void 来声明 main() 函数。

那么,这里的 void 指什么呢?就是指没有参数表的函数,希望在函数的参数表里面填写一个 void 原因吧,难说,这样写的确我说不上特别的好处,但是感觉会舒服很多,可能就是一个个人偏好吧。,原因是,加了void后,这个函数就被限制成为不能传入任何参数的函数了,如果你强行传入参数,编译会失败。如果不加在 C语言会认为这个函数可以传入任何参数的函数,区别还是很大的。(感谢蔡大牛提醒)。



int GetOne(void)


{

return 1;

}



第三点 就是解释一下 char* strcpy(char,char); 这个函数的返回值,然后抛砖引玉的来说说返回值的重要性。这里也许有些朋友会费解,明明 strcpy 的返回值已经给了第一个参数了,为什么还要最后 return 回来?这个不是“脱了裤子放屁──多此一举”么。其实不然,我们看如下代码就明白为什么了。



int length =strlen (strcpy(str,"zerob13"));




这个返回值就是为了这样的灵活性而考虑设计的,所以设计一个好的返回值对于一个好的函数也是非常重要的。

第四点,也是介绍一个神气的东西,叫做空循环。也许很多人学了c语言后一直不理解,为什么还要有个 do-while 循环,感觉有 while 不是已经够了么,这个东西似乎有点多此一举,其实不然。大家都知道,C语言是为了系统而出现的语言,这个 do-while 也自然和这个挂钩了。比如,你总是能够在 linux 的内核里面看到类似如下的宏。



define DUMP_WRITE(addr,nr) do{memcpy(bufp,addr,nr);bufp+=nr;}while(0)



总所周知,do-while 是先执行后判断循环,这里的while(0)也就是这个代码等价于:



define DUMP_WRITE(addr,nr) memcpy(bufp,addr,nr);bufp+=nr;



那么,我们为什么要套上这么一个 do-while 空循环呢?显然不行,一个小例子就可以说明,比如这个



if(OK)


DUMP_WRITE(addr,nr);

else


break;



如果,没有空循环,代码会变成这样子。



if(OK)


memcpy(bufp,addr,nr);

bufp+=nr;;

else


break;



然后,就悲剧了。但是,当你加上了 do-while 空循环的时候,整个循环被当作单独的一句语句,这样就可以达到正确的效果,如下:



if(OK)


do{


memcpy(bufp,addr,nr);

bufp+=nr;

}while(0);

else


break;

```

简单写的遗传算法求极大值

新手,比较简单,凑合看看~

/* Copyright (C) 2010 zerob13 */ #include #include #include #include #include using namespace std; #define MAXNUM 1023;//种群范围 #define NUMLEN 10//种群编码长度 #define STNUM 200//种群个体数目 #define PC 0.007//变异率 #define AGE 100//迭代种群代数 double Fsun;//储存所有值的和 void itoa(int a,int ans[])//输入整数a,和数组ans,然后,a的二进制会存放在ans里。(当然你也可以直接用系统自带的itoa) { int i,j; int co=0; while(a!=1&&a){ ans[co++]=a%2; a/=2; } if(a) { ans[co++]=1; } for(i=0,j=NUMLEN-1;iAP[j-1]){ rb[i]=ra[j]; break; } } } itoa(rb[i],ans[i]); } Exchange(ans); for(i=0;imaxx) { flag=0; maxn=ra[i]; maxx=getValue(ra[i]); } } } printf("%d\n",maxn); return 0; }

Opencv之摄像头捕获

今天试着写了写摄像头捕获的代码,运行成功,很好。
之后就要试试实质性的东西了

/* 功能:从摄像头中得到视频流,并输出结果。 / #include "cv.h" #include "highgui.h" #include #include int main( int argc, char* argv ) { CvCapture* capture = 0; // 下面的语句说明在命令行执行程序时,如果指定AVI文件,那么处理从 // AVI文件读取的视频流,如果不指定输入变量,那么处理从摄像头获取 // 的视频流 capture = cvCaptureFromCAM(0); if( !capture ) { fprintf(stderr,"Could not initialize capturing...\n"); return -1; } cvNamedWindow( "Laplacian", 0 ); // 循环捕捉,直到用户按键跳出循环体 for(;;) { IplImage* frame = 0; frame = cvQueryFrame( capture ); if( !frame ) break; cvShowImage("Laplacian", frame); if( cvWaitKey(10) >= 0 ) break; } cvReleaseCapture( &capture ); cvDestroyWindow("Laplacian"); return 0; }

自己写的稳定婚姻匹配模板,测试过,可靠

以前写的婚配模板,测试了多个题目,挺可靠的,于是发出来共享~

//婚配问题 by 混沌的云Knight //传入男人数n,女人数m //男人对女人好感矩阵mtw,女人对男人好感矩阵wtm,匹配矩阵 //match1,match2 匹配成功返回1,否则返回0 //match1,match2返回一个成功婚姻匹配,未匹配顶点match值为-1 #include #define MAXN 502 #define clr(x) memset(x,0xff,sizeof(int)*MAXN) char W[MAXN][MAXN]; int _O[MAXN]; int marry(int n,int m,int mtw[][MAXN],int wtm[][MAXN],int *match1,int *match2) { int i=0,j,h,M,t=-1,s1=n,s2=m; memset(W,0,sizeof(W)); for(clr(match1),clr(match2);i=0) { h=O[t--]; for(M=-1,i=0;imtw[h][M])) M=i; W[h][M]=1; if(match2[M]==-1) { match1[h]=M; match2[M]=h; s1--;s2--; }else if(wtm[M][h]>wtm[M][match2[M]]) { match1[match2[M]]=-1; _O[++t]=match2[M]; match1[h]=M; match2[M]=h; }else _O[++t]=h; } return (!s1)||(!s2); }

归并排序,比较好理解的一种排序

所谓的归并排序,就是递归“把数组从中间分开,分成两段,然后分别排序,最后合并”这个过程。

比较好理解,所以很快敲出了代码。

比快排好理解。。。个人感觉。。。

#include #include typedef int mytype; void add(mytype a,int l1,int h1,int l2,int h2) { mytype *t; int i,j,k; i=l1; j=l2; k=0; t=(mytype)malloc((h2-l1+1)*sizeof(mytype)); //申请空间存放中间数据 while(i

用c写了最简单的一个qsort

       突然发现,自己系统的qsort调用的很溜,可是却连个qsort怎么实现的都不知道。。。实在惭愧。。。于是从新学习排序,然后用c语言写了个比较简陋的qsort

#include struct man{ int len; char name[100]; }; typedef struct man mtype; mtype s[100]; int cmp(const void a, const void *b) { return ((mtype)a)->len-((mtype)b)->len; } int split(int low, int high,mtype *a,int (cmp)(const void *a,const void *b)) { mtype t; t=a[low]; while(low0&&low 这个qsort就是nlogn的复杂度,没有进行任何优化
每次选第一个数作为分割标准
但是已经够用了。。。

c#代码测试。。。也是本人人生第一个c#程序

   一个很简单的排序。。。大牛无视。。。

using System; using System.Collections.Generic; using System.Collections; using System.Linq; using System.Text; using System.IO; namespace qsort { class Program { static void Main(string[] args) { ArrayList a = new ArrayList(); int i; int n; string t=Console.ReadLine(); n = Convert.ToInt32(t); for(i=0;i0) { temp = a[i].ToString(); a[i] = a[j]; a[j] = temp; } } } Console.WriteLine("______"); for(i=0;i