光辉's profile胡言乱语PhotosBlogListsMore ![]() | Help |
|
|
9/1/2008 返回函数指针的函数第一次看到 void(*signal(int sig, void(*func)(int)))(int)时,半天没有反应过来这是个什么东西。其实这是Linux中系统函数signal的函数声明,也就是说signal是个函数。signal的两个参数分别为int sig和void (*func)(int),第二个参数是一个函数指针。如果将signal(int sig, void(*func)(int))看做一个整体,使用SIGNAL代表它,那么原表达式可以化为void(*SIGNAL)(int),这时可以清晰地看出SIGNAL是一个与参数func类型相同的函数指针,也就是说函数signal(int sig, void(*func)(int))的返回值是一个函数指针void(*)(int)。
7/18/2008 设置Ubuntu的本地环境Ubuntu的locale命令
在Ubuntu中输入locale命令可以查看系统的本地环境设置。在我的机器上运行locale命令,结果如下:
LANG=zh_CN.GBK
LANGUAGE=zh_CN:zh LC_CTYPE="zh_CN.GBK" LC_NUMERIC="zh_CN.GBK" LC_TIME="zh_CN.GBK" LC_COLLATE="zh_CN.GBK" LC_MONETARY="zh_CN.GBK" LC_MESSAGES="zh_CN.GBK" LC_PAPER="zh_CN.GBK" LC_NAME="zh_CN.GBK" LC_ADDRESS="zh_CN.GBK" LC_TELEPHONE="zh_CN.GBK" LC_MEASUREMENT="zh_CN.GBK" LC_IDENTIFICATION="zh_CN.GBK" LC_ALL= 可以通过以下方式修改Ubuntu的本地环境:
1) cd /etc/default/ 可以看到这个目录下有一个locale文件。
2) vim locale 在我的Ubuntu上打开locale文件,可以看到下面的内容:
LANG="zh_CN.GBK"
LANGUAGE="zh_CN:zh" 3) 可以通过修改LANG和LANGUAGE的值来修改本地环境。假设修改为UTF-8编码的英文:
LANG="en_US.UTF-8"
LANGUAGE="en_US:en" 4) 退出系统重新登录并运行locale命令,可以看到本地环境已经改变。
注意:如果在第三步中将locale文件的内容全部删除,使其成为空文件,那么在第四步中将看到本地环境被设置为POSIX。 Ubuntu的locale-gen命令 local-gen用来生成一系列的locale定义文件,Ubuntu正是根据这些文件来确定相应的locale格式。locale-gen会根据目录/var/lib/locales/supported.d/下的local文件生成相应的一系列locale文件。生成的文件默认存放在/usr/lib/locale/目录下。 在我的机器上/var/lib/locales/supported.d/local这个文件的内容为下: 如果想让我的Ubuntu支持zh_CN.UTF-8,那么需要按照以下步骤进行操作: Ubuntu支持的所有locale 文件/usr/share/i18n/SUPPORTED中列出了Ubuntu支持的所有locale。如果要使用这个文件中列出的某个locale,必须先通过locale-gen生成相应的一系列定义文件。 应用 由于windwos的命令行工具cmd只支持GBK的编码方式,而Ubuntu的默认安装一般支持的是UTF-8的编码方式,所以在cmd中使用telnet登录Ubuntu就会产生部分乱码问题。可以通过上面介绍的命令将Ubuntu的locale设置为zh_CN.GBK,从而解决乱码问题。 小结 主要的几个文件和目录: 有关locale和locale-gen的更多信息,请直接man。
7/12/2008 对PHP的一点想法目前的web开发基本都是使用基于MVC模式的开发框架。作为web开发中的主力军,PHP也有着各种不同的开发框架。特别是在Rails出现以后,出现了不少的PHP开发框架,有完全模仿rails的CakePHP,有官方开发的ZendFramework,还有国内的FleaPHP等等。
PHP的设计初衷就是为了方便web开发,针对web开发中的各种常见的需求PHP都有内置的函数帮助我们实现。而使用MVC模式进行开发已经成为了一种web开发中的常见需求,所以考虑是否可以直接在PHP语言中支持MVC模式的开发,而不是通过各种框架来支持MVC。
大概说来,需要内至于PHP语言中的有Model和Controller两个模块,至于View就是直接使用PHP实现的页面。这样带来的好处就是程序员无需学习掌握各种复杂繁琐的框架,直接内至于PHP语言中的Model和Controller也会有更好的性能表现。但是,这样也会带来灵活性上的限制。
忽然想到:其实浏览器中可以内在地支持人机交互,不要再编写复杂的javascript代码来搞人机交互了。可以提供一种类似于HTML,CSS这样的语言来设置用户的动作以及响应。 11/13/2007 JavaScript关闭Excel使用JavaScript的ActiveXObject打开Excel以后,即使你调用了Excel.Quit()方法,Excel也会一直运行,直到你关闭了当前IE窗口或者在当前窗口中打开另一个页面。 JavaScript是带有垃圾收集(Garbage Collection)功能的语言,它会在适当的时候收集那些不再使用的变量,而不是在你把一个变量设置为NULL的时候。所以,当你调用Excel.Quit()方法,并把指向Excel的引用(Reference)赋值为NULL时,JavaScript不见得会真正释放Excel。当你关闭当前窗口或者在当前窗口打开另外的页面时,JavaScript会强制进行垃圾收集,这时,Excel才会真正的关闭。 为了解决这个问题,你可以调用函数CollectGarbage来强制立即进行垃圾收集,这就会释放指向Excel的引用。下面的代码简单说明了如何使用该函数: <HTML>
<BODY>
<INPUT type="button" value="Automate Excel" name=AutomateExcel onclick="StartExcel()">
<SCRIPT LANGUAGE=Javascript>
var idTmr = "";
function StartExcel() {
var oExcel;
oExcel = new ActiveXObject("Excel.Application");
oExcel.Quit();
oExcel = null;
idTmr = window.setInterval("Cleanup();",1);
}
function Cleanup() {
window.clearInterval(idTmr);
CollectGarbage();
}
</SCRIPT>
</BODY>
</HTML> 注意:1)不能在调用Excel.Quit()之后立即调用CollectGarbage,需要等待一小段时间; 2)CollectGarbage不是ECMA-262标准,在将来的版本中有可能不能使用;3)强制使用CollectGarbage可能会对程序性能带来一定影响。 3/29/2007 变态的C语言声明请问以下每个A声明的是什么东西?
int (*A)[5];
int *(*A)[5];
int (*A[5])();
char (*(*A())[])();
char (*(*A[5])())[12];
答案如下:
int (*A)[5];
A是一个指向长度为5的 int 型数组的指针。
int *(*A)[5];
A是一个指向长度为5的 int* 型数组的指针。 int (*A[5])();
A是一个长度为5的数组 ,该数组中的项为返回 int 型的函数指针。
char (*(*A())[])();
char(*(*A())[])(); 首先 A与它右边的()结合形成A(),可以确定A是一个函数;
令F=A(),也就是说F是函数A()的返回值,原式变为char(*(*F)[])();
可以看出F是一个指针,令L=*F,那么L就是F指向的对象,原式变为char(*L[])();
可以看出L是一个数组,令P=L[],那么P就是数组L中的元素的类型,原式变为char(*P)();
可以看出P是一个函数指针。
从上面的分析可以看出:A是一个函数,这个函数没有任何参数,它的返回值是一个指针,这个指针指向一个数组,而这个数组的元素是char(*)()类型的函数指针。
char (*(*A[5])())[12];
首先A与它右边的[5]结合形成A[5],可以确定A是一个长度为5的数组;
令E=A[5],也就是说数组A[5]中的元素为E,原式变为char(*(*E)())[12],可以看出E是一个指针;
令P=*E,也就是说指针E指向P,原式变为char(*P())[12],可以看出P是一个函数;
令F=P(),也就是说函数P的返回值为F,原式变为char(*F)[12],可以看出F是一个指针;
令L=*F,也就是说指针F指向L,原式变为char L[12],很显然L是一个长度为12的char型数组。
从上面的分析可以看出:A是一个长度为5的数组,它的元素是函数指针,这个函数指针指向的函数没有参数并返回一个长度为12的char型数组。
3/17/2007 1,3,4,6如何运算得到24?如何通过加减乘除运算使得1,3,4,6得到24?
6/(1-(3/4))
还有变态的题目:四个0如何运算得到24?
(0!+0!+0!+0!)! = 24
从一副扑克牌中任意取出四张牌,如何通过加减乘除运算使得其结果为24?
能否通过编程实现,输出所有的可能情况?
11/24/2006 子序列求和问题:已知一个整数数组A,求一个最小的正整数M,使得M等于数组A的一个子序列的和。
第一步:
设数组A的长度为n,令数组sum[1..n]为以下值:
sum[1] = A[1];
sum[2] = A[1] + A[2] = sum[1] + A[2];
......
sum[i] = A[1] + A[2] + ... + A[i] = sum[i-1] + A[i];
......
sum[n] = A[1] + A[2] + ... + A[n] = sum[n-1] + A[n];
这一步的时间复杂度为O(n)。
第二步:
对数组sum[1..n]进行快速排序,使该数组按升序排列。
如果sum[a] == sum[b], 按以下规则排序:
如果 a < b,则 sum[b] 排在 sum[a] 前面。反之,sum[a] 排在 sum[b] 前面。
这一步的时间复杂度为O(nlogn)。
第三步:
设排序后的sum数组为:
sum[a1], sum[a2], ...... sum[an]
按如下方式遍历该数组:
i = [1..n]。
1) 如果 sum[ai] > 0 并且 sum[ai] < min, 令 min = sum[ai]。
2) 如果 0 < sum[a(i+1)] - sum[ai] < min 并且 a(i+1) > ai,令 min = sum[a(i+1)] - sum[ai]。
注意边界情况。
最后求得的min为该问题的解。
这一步的时间复杂度为O(n)。
//
该算法总的时间复杂度为O(nlogn)。
//
详细代码:
struct subsum
{ int value; int length; }; int minsubsum(int A[], int length) { int i; int min = 0; struct subsum *sum = new struct subsum[length+1]; sum[0].value = 0; sum[0].length = length+1; for(i=1; i<=length; i++) { sum[i].value = sum[i-1].value + A[i-1]; sum[i].length = i; } qsort(sum+1, length, sizeof(struct subsum), compare); for(i=1; i<=length; i++) { if (sum[i].value > 0) { if (min == 0) min = sum[i].value; else if (sum[i].value < min) min = sum[i].value; } if (sum[i].value != sum[i-1].value && sum[i].length > sum[i-1].length) { if (min == 0) min = sum[i].value - sum[i-1].value; else if (sum[i].value-sum[i-1].value < min) min = sum[i].value - sum[i-1].value; } } delete [] sum; return min; } int compare(const void *a, const void *b) { if (((struct subsum*)a)->value == ((struct subsum*)b)->value) return ((struct subsum*)b)->length - ((struct subsum*)a)->length; else return ((struct subsum*)a)->value - ((struct subsum*)b)->value; } 10/28/2006 常数附加空间的非递归方法遍历二叉树class TreeNode
{
TreeNode* leftchild; TreeNode* rightchild;
TreeNode* parent;
T data;
}
//前序遍历
PreOrder(TreeNode* root)
{
TreeNode* t = root;
while(1)
{
visit(t);
if (null != t->leftchild) {
t = t->leftchild;
} else if (null != t->rightchild) {
t = t->rightchild;
} else {
while (t->parent && ( null == t->parent->rightchild || t == t->parent->rightchild) )
t = t->parent;
if (null == t->parent)
break;
else
t = t->parent->rightchild;
}
}
}
如果要遍历的树有n个节点,则运行时间的上界为3n。
这是因为对于树中的每个节点,最多有3个指针指向它(父节点的指针以及两个孩子的父指针),
所以对于某个给定的节点,最多经过3次。所以对于有n个节点的树来说,遍历时间的上界为3n。
由于根节点和叶子节点的存在,事实上不可能达到3n。
10/14/2006 C++中结构的内存结构1) 无数据成员的结构 10/11/2006 C++中浮点变量与零值的比较今天下午参加了一个笔试,考的题目就是《高质量C/C++编程指南》后面附带的试题。当时感觉还不错,回来后看了一下答案,发现还是很有差距。
其中第一题问道:写出 float x 与 “零值”比较的 if 语句。我当下就写下了 if ( 0.0 == x ),可答案是:
const float EPSINON = 0.00001;
if ( (x >= -EPSINON) && (x <= EPSINON ) )
看完后还不明所以!
再看《高质量C/C++编程指南》,有如下解释:
【规则4-3-3】不可将浮点变量用“==”或“!=”与任何数字比较。
千万要留意,无论是float 还是double 类型的变量,都有精度限制。所以一定要避 免将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”形式。 假设浮点变量的名字为x,应当将 if (x == 0.0) // 隐含错误的比较 转化为 if ((x>=-EPSINON) && (x<=EPSINON)) 其中EPSINON 是允许的误差(即精度)。 |
|
|