Jul 26
1. 选中收件箱和发件箱


2. 菜单->操作->导出文本


3. 把导出的短信都放在一个目录下面


4. 在目录下放一个convertencoding.php,内容为:
<?php
$dir = scandir(".");
foreach($dir as $file){
    if(substr($file, -3) != "txt") continue;
    echo $file, "\n";
    $str = file_get_contents($file);
    $str = iconv("GB18030", "UTF-8", $str);
    file_put_contents($file, $str);
}
?>
然后$ php convertencoding.php 运行之。


5. 另一个php脚本,用于提取和指定的人的聊天记录
Jul 26

php数组按键排序 不指定

felix021 @ 2009-7-26 15:47 [IT » 程序设计] 评论(2) , 引用(0) , 阅读(8070) | Via 本站原创
遇到一个问题:
有一个数组,其中每个元素都包含time和content两个子元素,需要按time字段排序。

记得以前是搞过这个东西的,有个专门的函数,貌似就是array_multisort来搞。
查了一下mannual,发现例子实在太晦涩,看起来很不爽。
于是干脆自己实现一个,只需要提供一个排序函数即可。
效率可能低一些,但是用起来舒服多了。。

//调用例子(cmp函数可以自己重写):
mysort($array_name, 0, count($array_name) - 1, cmp);

function cmp($i, $j){
    return $i['time'] < $j['time'];
}

function mysort(&$arr, $s, $e, $func){
    $i = $s; $j = $e; $tmp = $arr[$s];
    if($s < $e){
        while($i != $j){
            while($i < $j && $func($tmp, $arr[$j])) $j--;
            if($i < $j){
                $arr[$i] = $arr[$j];
                $i++;
            }
            while($i < $j && $func($arr[$i], $tmp)) $i++;
            if($i < $j){
                $arr[$j] = $arr[$i];
                $j--;
            }
        }
        $arr[$i] = $tmp;
        mysort($arr, $s, $i-1, $func);
        mysort($arr, $i+1, $e, $func);
    }
}
Jul 8

ooxx的const 不指定

felix021 @ 2009-7-8 00:13 [IT » 程序设计] 评论(3) , 引用(0) , 阅读(7579) | Via 本站原创
咱们来对比一下这5个东西:
char ** a;
const char ** b;
char * const * c;
const char * const * d;
const char * const * const e;

——天哪,这都是什么东西?用5个小程序来解释一下。。或许你可以看得懂?
如果你急着和mm去约会,直接跳到文末,有比较简洁的说明。

#include <iostream>
#include <cstring>
using namespace std;

void test1(){
    char **s; //s是数组的指针;
    s = NULL;
    s = new char*[4];
    for (int i = 0; i < 4; ++i){
        s[i] = new char[10];
        strcpy(s[i], "test");
    }
    for (int i = 0; i < 4; ++i){
        printf("%s\n", s[i]);
    }
    for (int i = 0; i < 4; ++i){
        delete[] s[i];
    }
    delete[] s;
}

void test2(){
    const char **s; //s是指向字符串常量的指针
    s = NULL;
    char b[4][10] = {"a","b","c","d"};
    s = new const char*[4];
    for (int i = 0; i < 4; ++i){
        s[i] = b[i]; // OK
        //s[i][0] = 'd'; //这句要报错,因为s[i]指向的是字符串常量
                    //即使b[i]字符串本不是常量(编译期间添加的属性)
    }
    for (int i = 0; i < 4; ++i){
        printf("%s\n", s[i]);
    }
    delete[] s;
}

void test3(){
    char * const * s; //s指向常量数组,数组的每一个元素是字符指针常量。
                //数组的元素不可改,但数组元素指向的字符串可修改    
    s = NULL;// s不是常量
    char a[4][10] = {"aa", "bb", "cc", "dd"};
    char * const(b[4]) = {a[0], a[1], a[2], a[3]};
    s = b;
    for (int i = 0; i < 4; ++i){
        s[i][1] = 'd'; //OK
        //s[i] = NULL; //报错,因为s[i]是常量
        printf("%s\n", s[i]);
    }
}

void test4(){
    const char * const * s; //s指向一个常量指针数组
    //数组的每一个元素是字符指针常量,指向字符串常量(绕口令阿这是。。。)
    s = NULL;// s不是常量
    char a[4][10] = {"aa", "bb", "cc", "dd"};
    char * const(b[4]) = {a[0], a[1], a[2], a[3]};
    s = b;
    for (int i = 0; i < 4; ++i){
        //s[i][1] = 'd'; //报错,因为s[i][j]是常量
        //s[i] = NULL; //报错,因为s[i]是常量
        printf("%s\n", s[i]);
    }
}

void test5(){
    char a[4][10] = {"aa", "bb", "cc", "dd"};
    const char * const(b[4]) = {a[0], a[1], a[2], a[3]};
    const char * const * const s = b;
    //s是一个常量指针,指向一个常量指针数组
    //数组的每一个元素是字符指针常量,指向字符串常量(这才是绕口令!)
    //s = NULL; //Error, s是常量
    for (int i = 0; i < 4; ++i){
        //s[i][1] = 'd'; //报错,因为s[i][j]是常量
        //s[i] = NULL; //报错,因为s[i]是常量
        printf("%s\n", s[i]);
    }
}

int main(){
    test5();
    return 0;
}


OK,其实有一种很简单的阅读方法:从右向左读定义,结果就是——
char ** s;
s是一个指针1,指向一个指针2, 指针2指向char

const char ** s;
s是一个指针1,指向一个指针2,指针2指向char,char是常数

char * const * s;
s是一个指针1,指向一个常量1,常量1是个指针2,指针2指向char

const char * const * s;
s是一个指针1,指向一个常量1,常量1是个指针2,指针2指向char,char是常数

const char * const * const s;
s是一个常量1,常量1是一个指针1,指针1指向一个常量2,常量2是个指针2,指针2指向char,char是常数
Jul 1
本文档分析了xen启动时创建dom0的基本过程,并进行了一些简单的测试,记录了测试结果。

@ xen3.3.0/xen/arch/x86/setup.c

---- line 408 __start_xen(unsigned long mbi_p)
@ line 414, multiboot_info_t *mbi = __va(mbi_p);
mbi = multiboot_info, 类型multiboot_info_t, 位于include/xen/multiboot.h

@ line 415, modile_t *mod = (module_t *)__va(mbi->mods_addr);
module_t是一个位于multiboot.h中的struct,包含mod_start, mod_end, string, reserved等4个成员,其中mod_start, mod_end是地址, string是module [file] [para]这里的para字段(参数, 如果没有的话,就是NULL),比如kernel的参数就是这么搞出来的cmdline(大概在997行的位置)。
这个mod是一个指针,取值于mbi_p的成员mods_addr,其实就对应了一个数组,这数组的每一项应该就是顺序地对应着grub启动xen的时候,每一个module行对应的文件载入内存后的信息,包括起始和结束地址,还有附加的参数。
Jun 29
一直觉得C++做到了一件看似不可能的任务:
实现了完整的OO(甚至还有多继承),同时提供了对泛型几近完美的支持,还保证了足够的效率。

相比之下,

Java对OO的支持的确很好,但是它对泛型的支持,我觉得只能用丑陋来形容;同时它还提供了让我难以接受的效率。
Sandy在用Java开发他的手机游戏时就遇到了种种问题,
我也无法接受它"把一切都封装好只为让开发更简单"这样的Bullshit。
事实上一切都变复杂了。

C没有提供对OO的支持,也没有提供对泛型的直接支持;效率的确可观,但是用于开发,似乎很费劲。
对于开发人员,为一个安全数组写一大段基于malloc/realloc和需要强制类型的转换的代码似乎很累,而且可读性也差。
而C++的vector使用起来就相当省事,代码也更加清晰易读。

所以曾经有一段时间感到有点纳闷,为什么那么多大项目是用C开发的,而不是C++?
"历史遗留问题"似乎解释不通,比如Linux源代码是经过了几次完全的重写,其间C++已经发展得比较完善了。

回过头来想想另一件事情:
如果你经常逛一些偏开发类的论坛(比如CSDN?),并看到过那些有"纯正血统"的Java程序员的言论
你就会知道那些人如同不学无术的八旗子弟一般不堪;
尤其是他们对指针的理解,那根本就是P话,而且一点都不好笑。

这里不是想嘲笑他们有多么粗俗浅陋,毕竟没有学C不一定是他们的错。
这只是个类比,C和C++的对比,在一些方面与C/C++和Java的对比还是很相似的。

Linux之父Linus对C++嗤之以鼻,甚至因此和某人大吵一架,并毫不保留地表达了他对C++以及C++程序员的蔑视。
引用
...(Git)项目限制只用C,意味着参与的人不会捣乱,也意味着会得到许多真正懂得底层问题,而不会折腾那些白痴‘对象模型’垃圾的程序员。...所以,我很抱歉,但是对于Git这样效率是主要目标的软件,C++的所谓优点只是巨大的错误。而我们将看不到这一点的人排除在外却成了一个巨大的附加优势。...
从普通开发者的角度看来,一个提供完整OOP支持的语言不仅提高了开发效率、增加代码可读性,还为代码重用带来了极大的便利。这的确是现代大型系统开发需要的,但是它真的做到了吗?

你在学习C++的过程中可以很容易的学到如何继承一个类,可是你知道如果这个类的析构函数不是虚函数可能带来怎样的后果?你可以很容易地学到如何使用set/map,如何为它写一个简单的functor,可是你知道严格弱序化这个原则吗(Strict Weak Ordering)?

如果你不知道,没关系,这不是你的错,因为C++已经复杂到让人吃惊的地步了:STL中出现的traits和可以重载的逗号运算符都不算什么了,可是居然还能有boost这么变态的东西!甚至有人说,C++是唯一一门连语言之父都要别人教他怎么使用的语言了。

从某些角度来说,Java似乎做得更好:提供了丰富的类库以及完善的GC,你忘记了的东西通通交给它吧----可是你真的放心么?如果你知道Sandy仅仅因为String的问题就纠结了那么久,你就不会给出肯定答案了。我的看法是,Java只是把一切都变得复杂了(的确,我对Java有偏见,Sandy也是)。

最后回到C。不可否认,C标准库里的东西太少了,和现实不够接轨,不是类型安全的,只有指针没有引用也让代码看起来更ooxx... 但是仔细想想,其实C提供了一个足够简洁而完善的对底层的合理抽象,将控制一切的操作能力都交给你,让你能够不纠结于语言层面的复杂性,而将精力投入到功能的实现中去。

不要认为C不支持面向对象,不要认为这一点就限制了设计模式的使用----事实上,完全用C写就的Linux源代码是高度面向对象的,使用了令人惊叹的设计模式,达到了不可思议的效率和可扩展性。

做了这样的对比,不是想说C++和Java有多么不堪,至少从进化论的角度来说,他们都是成功的、优秀的。仔细思索,之所以Linus如此鄙视C++,并不是因为C++真的很差,而是因为C++的复杂性使得系统的设计变得更加复杂(特别是在要求高效率的地方,你用C++可能根本找不到效率损失于何处!),更为可怕的是,有那么多自以为是的程序员,以为学会了class a: public b就是学会了面向对象,以为学会了Observer模式的含义就真正掌握了设计模式,甚至以为学会了MFC就是学会了C++。如果这些人加入Linux内核的开发,那的的确确是一场灾难,而且极其可怕。

"的确有不少C++程序员贡献代码,但是反而需要核心的C程序员花费更多时间去修改和删除。"

最后,援引Linus的一句话作为结束:
引用
C最大的优点之一,就是它不会使你认为程序是什么高层的东西。

Jun 23
坦白说,我不确定这个东西是不是叫做败者树,因为我觉得它就是以前写过n遍的线段树的一个简单变种。
在线段树的每个节点存储v, i,分别表示该区间内最小值和最小值所在单元的索引。
建立好线段树以后,每次取出整个区间的最小值,然后将该值来源的那一路的下一个数字填充进去
如果那一路已经没有下一个数字了,就填一个max进去,然后递归地更新其所有祖先节点。
这个过程有点像heap的sift_up。

代码如下:
Jun 23

采用堆的多路归并 不指定

felix021 @ 2009-6-23 00:38 [IT » 程序设计] 评论(0) , 引用(0) , 阅读(4825) | Via 本站原创
一般数据结构上用败者树来实现,这东西我没写过,所以暂时忽略之。
改用相对比较熟悉的heap来处理,写了一个class heap。
为了方便采用一个 5 x 5 的数组来存储需要归并的数据;很容易可以扩展到不定长的不同数据组。
明天再试着写一下败者树。

代码如下:
Jun 21
话说,虽然felixoj的judge已经在几天前完工,

但是有一个地方是felix没有理解的(因为是copy的sempr大牛的hustoj的流程):

按理,当RE/OLE的时候child是会收到SIGSEGV/SIGFPE...等表示RE的信号,或者SIGXFSZ表示OLE的信号

但是在wait4以后WIFSIGNALED(status)并没有得到正确的结果。

Sempr大牛的版本是另做了一些处理:
int sig = status >> 8;
if(sig == 5);
else{
    switch(sig){
        case SIGSEGV: ...
        case SIGXFSZ: ...
        ...
    }
}

对此感到非常难以理解,于是咨询Sempr大牛。

大牛以其强悍的记忆力回忆一年前的事情,大致的回复是

  status >> 8 差不多是EXITCODE
  sig == 5 差不多是正常暂停

于是广搜资料,获得了一些更详细的信息:

WIFSIGNALED: 如果进程是被信号结束的,返回True
  WTERMSIG: 返回在上述情况下结束进程的信号

WIFSTOPPED: 如果进程在被ptrace调用监控的时候被信号暂停/停止,返回True
  WSTOPSIG: 返回在上述情况下暂停/停止进程的信号

另 psignal(int sig, char *s),进行类似perror(char *s)的操作,打印 s, 并输出信号 sig 对应的提示,其中
sig = 5 对应的是 Trace/breakpoint trap
sig = 11 对应的是 Segmentation fault
sig = 25 对应的是 File size limit exceeded

于是问题就解决了。

最后我的判断条件是:
if(WIFSIGNALED(status) ||
    (WIFSTOPPED(status) && WSTOPSIG(status) != 5))

另外用 strsignal(int sig) 函数获得 信号sig 对应的描述文字并用fprintf(stderr, "%s", 这样的语句输出。
分页: 44/103 第一页 上页 39 40 41 42 43 44 45 46 47 48 下页 最后页 [ 显示模式: 摘要 | 列表 ]