日历
网志分类
· 所有网志 (12)
· 算法 (5)
· c/c++ (2)
· 软件开发 (1)
· LabVIEW (3)
· 经验之谈 (1)
最新的评论
站内搜索
友情链接
· 我的歪酷 非非共享界
· LabVIEW虚拟仪器家园

订阅 RSS

0009697

歪酷博客

Tech Lead's Section


樱木 @ 2007-10-07 08:58

今天看了《一位同行工作6年的总结》,是一个软件工程师从业6年以后的总结。原文地址:http://programmingart.blog.51cto.com/213782/39430

谈的很实际,对我或多或少有点启发。

1。学历代表过去、能力代表现在、学习力代表未来。

学习能力的确是很重要的,这点我很认同。软件行业发展很快,很强的学习能力无疑是你的核心竞争力。对于这点我还是很有自信的。

2。要确定自己的发展方向,并为之制定切实可行的计划。是始终走技术路线,将来成为专家级人物?还是向管理方向走,成为职业经理人?还是先熟悉行业领域,将来自己开公司?还是现在行业里混混,过几年转行做点别的?这很重要,因为这将决定你近几年,甚至十年内“做什么事情才是在做正确的事情!”

除了转行基本没有可能外,其他几种都有可能。其实道理都知道,这几条线路也十分清楚,就是不确定哪一条才最适合自己。插句题外话,前几天看到bbs上说水瓶座男生找女朋友的特点是“不确定什么是自己想要的,但一定知道什么是自己不想要的”,笑笑之余感觉确实有点道理。现在职业选择也一样迷茫,感觉不是我在选择职业,而是职业在选择我。然而这种事情是别人所替代不了的,别人的经验固然可以参考,但是最适合自己的道路还是需要自己选择,毕竟最终是由自己去走完。时间不早了,该考虑起来了!

3。详细制定自己软件开发专业知识学习计划,并注意及时修正和调整(软件开发技术变化实在太快)。请牢记:“如果一个软件开发人员在1、2 年内都没有更新过自己的知识,那么,其实他已经不再属于这个行业了。”

无论将来是做职业经理人还是技术专家或是自己另辟天地,过硬的专业技术无疑都是很有帮助的。问题就在于深入学习的程度,撇开具体领域不谈,如果做技术专家,自然专业知识学习越深入、越广泛越好。但是如果准备向职业经理人发展,那么是否可以先开始准备准备一点点相关的管理、经济知识呢?毕竟时间是有限的。所以确定自己的方向是那么的重要。

4。养成总结与反思的习惯。

好吧,有空多写blog :p

5。对软件开发人员而言,有、无经验的一个显著区别是:无经验者完成任何任务时都从头开始,而有经验者往往通过重组自己的可复用模块、类库来解决问题。

有道理,以后要努力成为copy高手。




 
樱木 @ 2007-10-06 09:00

use case:需要为不同角色的用户提供登陆验证

该VI提供以下功能:

*常规
1。有两类用户:user、administrator
2。每一类中各有一个预定义好的用户即可,无需用户数据库
3。如果用户名、密码都匹配,显示消息: welcome, user/admistrator!
4。当VI启动时,用户名、密码框留空

*错误处理
1。如果用户名不存在,显示消息: user doesn't exist!
2。如果密码不正确,显示消息: wrong password!
3。若错误输入三次(包括1、2类型),VI自动停止运行

*退出
用户点击退出按钮,提供退出确认对话框

我实现的VI的界面是这样的:



它的程序框图如下



这应该是我自从学LabVIEW以来写的最复杂的一个VI了吧。这个Use case还是蛮实际的,所以有动力实现了一下。现在看来,自己动手写一个VI确实是大有裨益的啊!

一些收获:
1。event case需要放在while structure里面来捕获多种事件,当某个条件满足时,可以从event case中直接中止循环(连接到while循环的condition input terminal上)。在这种while循环中不需要添加一个timer来提高CPU利用率,因为没有忙等。

2。被捕获事件的源control(按钮)需要放在相应的event case里面,以保证按钮的行为正常。
这是一个惯例,原因尚不清楚。

3。case structure的输入是所有case共享的,但不是所有case都必须使用(全部)输入。另一方面,case structure的输出不是所有case共享的,每一个case必须显式定义输出,或者use default  value,否则VI是broken的。这很make sense,因为可以有多个地方读取同一个输入源,但是若同时有多个地方写同一个输出,那么输出到底应该是什么就有二义性了(ambiguous)

4。
要实现最简单的if ***, pop up a dialog功能,现在只能用case structure,感觉很麻烦。不知道有否其他方法?

5。最后,发现system下面的control要比LabVIEW自带的control漂亮多了,嗯,因为是XP的control呵呵。



 
樱木 @ 2007-10-05 12:55

LabVIEW引入事件结构至少有两个原因。其一,事件结构可以避免VI产生忙等,提高了CPU的利用率。其二,事件队列的存在保证了每一个到达的事件都会按序进入队列,不会有任何的事件因为发生太快而被忽略。事件按照在队列中的顺序依次进行处理。

比如,要计算一个“Hit Me”按钮被单击的次数。

方法1:使用while+case结构。除了忙等,鼠标单击过快会导致该事件被忽略。



方法2:使用event结构,避免了上述两个问题。





注意:
event结构必须被包含在一个while循环中以处理多种不同的事件。

疑问:
按钮必须放在event结构的对应case里,否则按钮的机械行为会变得很奇怪(似乎与mechanical action的设置无关),不知为何?



 
樱木 @ 2007-10-03 10:31

local variable

use case 1
在LabVIEW中经常会遇到这样的情况,就是在一个VI的不同地方需要对同一个Indicator进行赋值。这时候不可能把所有的连线都连到该indicator的input terminal上,因为任何一个时刻输入只可能有一个,否则会有二义性。可以通过LabVIEW的Local variable实现这样的功能。

use case 2
Local variable的另外一个功能就是可以在control与indicator之间转换,因此可以通过它来实现对一个control或indicator加一类似的功能。这样的use case可以在LabVIEW help fundamentals中找到。

创建方式
可以有两种方式创建local variable,一种是通过function palette中structures,这是先创建后绑定的方式,绑定之前会有个问号;还有一种是通过右击control或indicator选择create,创建后就已经绑定了。

局限性
Local variable只支持在同一个VI之间传递数据。

global variable

LabVIEW的Global variable支持在同一台机器的不同VI之间进行数据传递。Global variable是以一个VI来实现的,可以把需要在不同VI中共享的各种control、indicator drag进global variable VI的front panel,当然,它是没有block diagram的。

如果在Global variable front panel创建好后在其他VI上删除了它的icon,可以select a VI来选择它,前提是global variable VI事先保存



 
樱木 @ 2007-09-24 16:16

/*
walking stairs problem: this is a n-step stairs. Every time you can walk one step or two steps, but no backward movement
is allowed. now you want to know how many ways you have to finish walking the stairs
for example: a 3-step stairs, you can finish walking using either way below:
1,1,1
1,2
2,1
so there're totally three ways.
 
solution: because we only have two choices, either walking one step or two steps at a time. finally, we can walk one step
or two steps to finish walking these n steps. combine these two cases and we get answer:
if final "step" is to walk one stair: number of walkings: f(n-1)
if final "step" is to walk two stairs: number of walkings: f(n-2)
so total number of walkings: f(n-1) + f(n-2)
 
it's actually a Fibonacci sequence start from F2
*/
 
int stairs( int n )
{//recursive function, return number of ways that you can finish walking a n-step stairs
     if( n == 1 || n == 2 )
         return n;
     return stairs( n-1 ) + stairs( n-2 );
}
 
/* complexity:
time: solve f(n)=f(n-1)+f(n-2), we get O(1.62^n)
space: stack exists, O(n)
*/



 
樱木 @ 2007-09-24 13:41

/* insertion sort:
the thought of insertion sort is very simple: if there's a sorted array A of length N and an unsorted element C, insert C into A and generate a new sorted array
of length N+1. The simplest way to do this is to compare C with each element already in A from back to front until find the correct position for C. */
 
void insertion_sort( int * a, int n )
{//sort a[0..n]
     int cur;
     //a[0] is an already sorted subarray
     for( int i=1; i<=n; ++i )
     {
         if( a[i] < a[i-1] )
         {
              cur = a[i];
              int j = i - 1;
              do{
                   a[j+1] = a[j];
                   --j;
              }while( j>=0 && a[j]>cur );
              a[j+1] = cur;
         }
     }
}
 
/* complexity
time: comparision: min: n-1 max: 1+2+..+(n-1)=O(n^2)
assignment: min:0 max:1+2+...+(n-1) (max of comparisions) + 2(n-1)=O(n^2)
 
application:
1. when the size of unsorted array is very small (<10), insertion sort is highly effective, and it's very simple to implement
2. when original array is already sorted or nearly sorted, insertion sort is effective, compared with other comparision-based sort
3. among all comparision-based sort methods, insertion sort is the most effective one if orignal array is already sorted
beacuse of theorem:
to verify that n elements are already sorted needs at least n-1 comparisions.
 
feature:
1. in place sort
2. stable
*/



 
樱木 @ 2007-09-23 11:16

/*
problem: search majority element in an array
array: a[s...t]
majority element a[j]: the value of a[j] appears more than [n/2] times in array a
 
algorithm base:
1. for any array, there's at most one majority element
2. if majority element c exists, after deletion of two unequal elements in array, c will be the majority element in the remaining subarray all the same
3. if majority element doesn't exist, after deletion of two unequal elements in array, it's possible that there's a majority element in the remaining subarray
e.g, 1,2,3,3,3,4   no element appears more than three times        after deletion of 1,2     in subarray 3,3,3,4    3 will be the majority element
 
conclusion:
after deletion of two unequal elements in original array, the majority element in the remaining subarray, if exists, will only be the candidate of the majority
element of original array. So make a check by traversing original array to make sure it's really a majority element of original array.
*/
 
int candidate( int * a, int s, int t )
{ //find majority element candidate of array a[s..t], if exist, return its first index, else, return -1
 //we return index instead of value, to make difference between case i>t && count>0 and i>t && count=0
     int c = a[s];
 
     /* traverse from a[s+1] to a[t], if equal to c, increase count by one, else, decrease it by one. when count=0, search in subarray.
     if reaches the end t and count>0, then c is a candidate of majority element of original array, return it. */
     int count = 1;
 
     `
     if( i>t && count>0 )   //reach the end of array and count>0, it is a candidate
         return s;         
     else if( i>t )              //reach the end of array and count=0, it's not a candidate
         return -1;
     else                   //count=0 and before the end, call it for subarray
         return candidate( a, i, t );
}
 
int majority( int * a, int n )
{    // find real majority element of array a[0..n]
     // return index of majority element if exists. else, return -1.
     int i = candidate( a, 0, n );
     if( i == -1 )      // no candidate
         return -1;
 
     int c = a[i]; //candidate
     int count=0;
 
     // check whether this candidate is a real majority element
     for( int j=0; j<=n; ++j )
         if( a[j] == c )
              ++count;
     if( count > (n+1)/2 ) //real
         return i;
     else //fake
         return -1;
}
 
/* complexity
time: O(n)
space: O(n) can use iteration to eliminate recursion
*/



 
樱木 @ 2007-09-22 14:12

inline void swap_int(int &a, int &b)
{
     int c = a;
     a = b;
     b = c;
}
 
//mathematical induction
//1.print permutations of a[s]~a[t] with identical leading elements a[0]~a[s-1]
//2.a[s]~a[t] remain unchanged between enterance and return of this function
 
void perm(int *a, int s, int t)
{//the total array a is from a[0] to a[t]
     if( s==t )
     {
         for( int i=0; i<=t; ++i )
              cout<<a[i]<<" ";
         cout<<endl;
     }
     else
     {
         for( int i=s; i<=t; ++i )
         {
              swap_int( a[s], a[i] );
              perm( a, s+1, t );
              swap_int( a[s], a[i] );
         }
     }
}

 
//time complexity analysis
//the number of permuatations of n numbers is n!, if output of one element is a basic operation, then it needs n*n!
//the number of swaps of elements: n! permutations, at most n-1 swaps from one permutation to another, so <n*n!
//total complexity: O(n*n!)