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

归类于程序人生 14 条评论

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命令

1
$ top -n0 -l1

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
 
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

507 views , , , , ,

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

归类于程序人生 6 条评论

首先么,这是个人风格,完全不是权威之说。
第二,记录下来只是感觉自己这样蛮舒服,分享而已。
第三,别拿某为谭姓叫兽的文章来说事情,不解释。
第四,这里的 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(a==0)
{}

然后是指针一类的,空值为 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;

56 views , , , , , , ,

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

归类于程序人生 一条评论

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*    Copyright (C) 2010  zerob13 <zerob13@gmail.com> */
#include <iostream>
#include<time.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
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;i<j;j--,i++)
	{
		ans[i]^=ans[j];
		ans[j]^=ans[i];
		ans[i]^=ans[j];
	}
}
 
int atoi2(int ans[])//输入二进制数组返回整数值 如数组ans[]={0,0,0,0,0,1,0,1},就会返回5
{
	int an=0,i;
	for(i=0;i<NUMLEN;i++)
	{
		an+=ans[i]*(1<<(NUMLEN-1-i));
	}
	return an;
}
 
void getrand(int ra[])//获取1~MAXNUM的随机初始种群 放在你输入的数组ra[]中
{
 
	srand(time(NULL));
	for(int i=0;i<STNUM;i++)
	{
		ra[i]=1+rand()%MAXNUM;
	}		
}
 
void getP(double P[])//获取0~1随机数 放在你输入的数组P[]中,作为选择概率用
{
	srand(time(NULL));
	for(int i=0;i<STNUM;i++)
	{
		P[i]=double(rand()%10000)/10000.0;
	}
 
 
}
 
int getValue(int va)//获取适应度
{
	return va*va;
}
 
double getchoseP(int va)//获取选择概率
{
	return (double)va/Fsun;
}
 
void creatAP(double P[],double AP[])//获取积累概率
{
	int i,j;
	for(i=0;i<STNUM;i++)
	{
		AP[i]=0.0;
		for(j=0;j<=i;j++)
		{
			AP[i]+=P[j];
		}
	}
	return ;
}
 
int getPcNum()//获取变异位数
{
	return (int)(PC*NUMLEN*STNUM);
}
 
void Exchange(int ans[STNUM][NUMLEN])//交叉运算
{
	int i,j,k,c;
	k=getPcNum();
	for(i=0;i<STNUM-1;i+=2)
	{
		for(j=NUMLEN-5;j<NUMLEN;j++)
		{
			ans[i][j]^=ans[i+1][j];
			ans[i+1][j]^=ans[i][j];
			ans[i][j]^=ans[i+1][j];
		}
 
 
	}
	while(k--){		
		c=rand()%(NUMLEN*STNUM);
		ans[c/NUMLEN][c%STNUM]^=1;
 
	}
 
 
	return ;
}
 
int main (int argc, char * const argv[]) {
 
	int ans[STNUM][NUMLEN];
	int ra[STNUM];
	int rb[STNUM];
	int i,j;
	double P[STNUM];
	double AP[STNUM];
	double Cp[STNUM];
	int maxx,maxn;
	int flag=0;
	memset(ans,0,sizeof(ans));
	for(Fsun=0,i=1;i<512;i++)
	{
		Fsun+=getValue(i);
	}
	maxx=0;
	maxn=0;
	getrand(ra);
	for(i=0;i<STNUM;i++){
 
		if(maxx<getValue(ra[i]))
		{
			maxx=getValue(ra[i]);
			maxn=ra[i];
		}
 
	}
 
	while(flag<AGE)
	{
		flag++;
		for(i=0;i<STNUM;i++)
		{
			Cp[i]=getchoseP(getValue(ra[i]));
		}
		creatAP(Cp,AP);
		getP(P);
		for(i=0;i<STNUM;i++)
		{
			for(j=0;j<STNUM;j++)
			{
				if(j==0)
				{
					if(P[i]<=AP[j])
					{
						rb[i]=ra[j];
						break;
					}
				}else {
					if(P[i]<=AP[j]&&P[i]>AP[j-1]){
 
							rb[i]=ra[j];
							break;
						}
				}
 
			}
			itoa(rb[i],ans[i]);
		}
 
		Exchange(ans);
		for(i=0;i<STNUM;i++)
		{
			ra[i]=atoi2(ans[i]);
 
			if(getValue(ra[i])>maxx)
			{
				flag=0;
				maxn=ra[i];
				maxx=getValue(ra[i]);
			}
		}
	}
	printf("%d\n",maxn);
 
    return 0;
}

275 views , , , ,

Opencv之摄像头捕获

归类于程序人生 2 条评论

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 功能:从摄像头中得到视频流,并输出结果。
 */
#include "cv.h"
#include "highgui.h"
#include <ctype.h>
#include <stdio.h>
 
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;
}

513 views , , , ,

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

归类于程序人生 参与评论

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//婚配问题 by 混沌的云Knight
//传入男人数n,女人数m
//男人对女人好感矩阵mtw,女人对男人好感矩阵wtm,匹配矩阵
//match1,match2 匹配成功返回1,否则返回0
//match1,match2返回一个成功婚姻匹配,未匹配顶点match值为-1
#include<string.h>
#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<n;_O[++t]=i,i++);
    while(t>=0)
    {
        h=_O[t--];
        for(M=-1,i=0;i<m;i++)
                if(!W[h][i]&&(M==-1||mtw[h][i]>mtw[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);
}

331 views , , , , , , , , , ,

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

归类于程序人生 参与评论

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include<stdio.h>
#include<stdlib.h>
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<=h1&&j<=h2)
	{
		if(a[i]<a[j])
		{
			t[k++]=a[i++];
		}else
		{
			t[k++]=a[j++];//小的放进去。。。
		}
	}
	while(i<=h1)
	{
		t[k++]=a[i++];
	}
	while(j<=h2)
		t[k++]=a[j++];//多余的数
	for(i=l1,j=0;i<=h2;i++,j++)
	{
		a[i]=t[j];//复制中间数据回去
	}
	free(t);
	return ;
}
void MergeSort(mytype *a,int low,int high)
{
	int mid=(low+high)/2;
	if(low<high)
	{
		MergeSort(a,low,mid);//最难理解的部分了吧。。。
		MergeSort(a,mid+1,high);//就是不断的递归
		add(a,low,mid,mid+1,high);//然后从最底一层排序后回溯上来。。。
 
	}
	return ;
 
}
int main()
{
 
	mytype s[100];
	int i,j,k,n;
	while(scanf("%d",&n)!=EOF)
	{
		for(i=0;i<n;i++)
		{
			scanf("%d",s+i);
		}
		MergeSort(s,0,n-1);
		for(i=0;i<n;i++)
		{
			printf("%d ",s[i]);
		}
		puts("");
	}
}

145 views , , , , , , ,

用c写了最简单的一个qsort

归类于程序人生 参与评论

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include<stdio.h>
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(low<high)
	{
		while(cmp(&a[high],&t)>0&&low<high)
			high--;
		if(low==high)
			break;
		else
		{
			a[low]=a[high];
			low++;
		}					//将比t小的数都放到t的前面
		while(cmp(&a[low],&t)<=0&&low<high)
			low++;
		if(low==high)
			break;
		else
		{
			a[high]=a[low];
			high--;				//比t大的放后面
		}
 
	}
	a[low]=t;
	return low;
}
void qsort(mtype *a,int low,int high,int (*cmp)(const void *a,const void *b))
{
	int p;
	if(low<high)
	{
		p=split(low,high,a,cmp);//取一个数进行分割
		qsort(a,low,p-1,cmp);//前部分迭代
		qsort(a,p+1,high,cmp);//后部分迭代
	}
}
int main()
{
	int a,b,i;
 
	while(scanf("%d",&b)!=EOF)
	{
		for(i=0;i<b;i++)
		{
			scanf("%d %s",&s[i].len,s[i].name);
 
		}
		qsort(s,0,b-1,cmp);
		for( i=0;i<b;i++)
		{
			printf("%s ",s[i].name);
		}
		printf("\n");
	}
}

这个qsort就是nlogn的复杂度,没有进行任何优化
每次选第一个数作为分割标准
但是已经够用了。。。

157 views , , , , ,

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

归类于程序人生 参与评论

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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;i<n;i++)
            {
                string s = Console.ReadLine();
                a.Add(s);
            }
            for(i=0;i<n;i++)
            {
                for(int j=i+1;j<n;j++)
                {
                    string k, b, temp;
                    k = a[i].ToString();
                    b = a[j].ToString();
                    if(k.CompareTo(b)>0)
                    {
                        temp = a[i].ToString();
                        a[i] = a[j];
                        a[j] = temp;
                    }
 
                }
            }
            Console.WriteLine("______");
            for(i=0;i<n;i++)
            {
                Console.WriteLine(a[i]);
            }
 
 
        }
    }
}

179 views , , , ,

顶部