• 2009-01-11

    [不会停止]idea’s blog 即将停止了…

    Views: 10692 | 6 Comments

    2009年4月5日更新: 不会停止!

    时间飞逝, 从"idea's web正式成形了"到现在已经3年了. 事实上我的网站开始的时间还要再早3个月 -- 2005年10月. 如今, 我决定停止它了. 我当时在那篇日志里提到的要学习的技术, 现在都可以随心应手地使用了. 当初的眼光太低, 设定的目标太小, 到如今突然感觉技术已经停步不前了. 大学四年是人生的一个阶段, 我已经结束了这个阶段, 却没有紧接着找到一个新的阶段.

    这些天我在痛苦的思索着, 但是没有一点头绪, 成了心灵上无家可归的孤儿. 下周就回家过年了, 也许回到家乡, 看到父母, 看到兄弟姐妹, 看到亲戚的小孩, 吃到熟悉的食物, 能给我一些灵感.

    等到我把未来2-3年的人生规划想好的那一天, 就是一个新的"idea's web"的诞生的时间, 也将是我人生旅程的又一个新的开始.

    Posted by ideawu at 2009-01-11 21:16:11
  • 2008-11-21

    MySQL 查询使用 Group By 的注意点

    Views: 9139 | No Comments
    • If you use GROUP BY, output rows are sorted according to the GROUP BY columns as if you had an ORDER BY for the same columns. To avoid the overhead of sorting that GROUP BY produces, add ORDER BY NULL:

      SELECT a, COUNT(b) FROM test_table GROUP BY a ORDER BY NULL;

    -- 载自 MySQL 手册.

    上面说的是, group by 默认会排序, 如果不想这么做, 必须显式声明.

    Posted by ideawu at 2008-11-21 19:55:32
  • 2008-10-22

    我也做招聘工作

    Views: 6638 | No Comments

    一年前, 我是一个求职者, 投简历, 忐忑不安地等待面试通知. 这些天, 我竟然干起了筛选简历的工作. 这角色的转换让我还有点不适应. 我就说说我对简历的要求吧:

    1. 简历要美观, 整齐, 简洁, Word文档在两页即可.
    2. 教育经历从大学本科, 不需要写高中, 更不需要写小学.
    3. 要从字里行间体现出求职者积极的态度, 而不是漫不经心.
    4. 主要写所求职位要求的技能, 不相关了写一两句即可. 不要在求职意向是一个C语言开发的职位时, 写了一大堆自己如何帮同学安装系统的经验.

    最后, 我要补充的是, 简历筛选者的主观意见真的很强烈, 有时求职者在自身能力的基础上, 还得靠一些运气.

    Posted by ideawu at 2008-10-22 10:25:26
  • 2008-06-15

    小巧且强大的集成开发环境(IDE) – Code::Blocks

    Views: 8315 | No Comments

    偶然得知一个小巧的集成开发环境 Code::Blocks(CodeBlocks), 试用了一把, 感觉非常不错.

    我认为, 一个开发环境首先必须拥有一个非常顺手的文本编辑器. EditPlus 我认为是最好的文本编辑器之一. 之前, 我一直使用 EditPlus 来写简单的程序,  并且配置了自定义工具, 可以一个按钮编译源码并执行, 相当于 IDE 中的 "Build and Run". Code::Blocks 的文本编辑功能和 EditPlus 已经不相上下. 而且还增加了代码折叠, 输入提示(如输入 re, 会提示 return 等)等 EditPlus 没有的功能.

    另外, Code::Blocks 还集成了不少调试工具如查看 CPU 寄存器, 线程等.

    更重要的是, Code:Blocks 是开源和免费的. 试用一下 Code::Block 吧, 你不会感到失望的!


    补充: 对于只有一二十个源文件的项目, Code::Blocks确实小巧, 但是对于像Linux源码这样的大型项目, 它就显得太慢太庞大了, 因为它使用内存的方式没有优化.

     

    Posted by ideawu at 2008-06-15 11:33:38
  • 2008-05-13

    给四川地震灾区捐款帮助受灾的人

    Views: 7084 | No Comments

    四川省汶川县在 5 月 12 日发生的地震已经造成至少 9000 人死亡, 由于这只是目前的统计数据, 所以死亡人数可能会高很多. 有一个学校的上课学生全被压在废墟下, 死了 300 多人.

    地震的中心在山区, 再加上大雨, 交通几乎完全中断. 所以, 对于我们这些离灾区很远的人, 目前帮助他们最好的方法是捐款, 以便能更好的组织救灾行动. 大家可以访问红十字会的网站 http://www.redcross.org.cn/, 获取捐款方式, 然后给灾区的人捐款. 注意, 可能有骗子会在这时候骗取好心人的钱, 所以大家一定要通过正规的渠道进行捐款.

    2008年5月18日更新: 根据权威媒体报道, 死亡人数已经增至28000多人.
    2008年5月26日更新: 超过 62000 名同胞遇难.

    Posted by ideawu at 2008-05-13 14:24:44
  • 2008-04-02

    C# 中实现 FIFO 缓冲区–ArrayBuffer

    Views: 10427 | No Comments

    .Net 似乎没有 FIFO 的内存缓冲类, 所以我实现了这样的一个类 ArrayBuffer. 该类把一个定长的数组(可重新分配)作为环形队列.

    使用实例:

    class Test
    {
        // 缓冲的容量为 7 个单位.
        private static ArrayBuffer<byte> ab = new ArrayBuffer<byte>(7);
    
        private static Random rand = new Random();
    
        public static void Main(string[] args){
            Thread t = new Thread(Reader);
            t.IsBackground = true;
            t.Start();
    
            for(int i=0; i<12; i++){
                byte[] data = Encoding.UTF8.GetBytes(i + ", ");
                ab.Write(data);
                Console.WriteLine("Write: " + i + ",");
                Thread.Sleep(rand.Next(200));
            }
        }
    
        private static void Reader(){
            byte[] readBuf = new byte[512];
            int n_read = 0;
            while(true){
                n_read = ab.Read(readBuf);
                string s = Encoding.UTF8.GetString(readBuf, 0, n_read);
                Console.WriteLine("Read: " + s);
                Thread.Sleep(rand.Next(300));
            }
        }
    }
    
    /*
    打印出下面类似的信息:
    Write: 0,
    Read: 0,
    Write: 1,
    Read: 1,
    Write: 2,
    Write: 3,
    Read: 2, 3,
    Write: 4,
    */
    

    ArrayBuffer 完整源码:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    
    namespace Ideawu.Utils
    {
        /**
         * 缓冲区的可能状态:
         * <code>
         * (1)
         * ----====== data ======-----rspace----
         *     |                 |             |
         *     rd_nxt            wr_nxt        capacity-1
         *(2)
         * ==ldata==-------------==== rdata ====
         *          |            |             |
         *          wr_nxt       rd_nxt        capacity-1
         * (3)
         * ===ldata=============rdata===========(full of data)
         *             |
         *             wr_nxt(rd_nxt)
         * (4)
         * -------------------------------------(empty)
         *           |
         *           wr_nxt(rd_nxt)
         * </code>
         */
    
        /// <summary>
        /// 使用字节数组来实现的缓冲区. 该缓冲区把该数组看作是一个环,
        /// 支持在一块固定的数组上的无限次读和写, 数组的大小不会自动变化.
        /// </summary>
        /// <typeparam name="T">所缓冲的数据类型.</typeparam>
        public class ArrayBuffer<T>
        {
            /// <summary>
            /// 默认大小.
            /// </summary>
            private const int DFLT_SIZE = 512 * 1024;
    
            /// <summary>
            /// 缓冲区还能容纳的元素数目.
            /// </summary>
            private int space = 0;
    
            /// <summary>
            /// 缓冲区中的数据元素数目.
            /// </summary>
            private int available = 0;
    
            /// <summary>
            /// 缓冲区的容量.
            /// </summary>
            private int capacity = DFLT_SIZE;
            // 注意 capacity 和 buf.Length 可以不相同, 前者小于或者等于后者.
    
            /// <summary>
            /// 下一次要将数据写入缓冲区的开始下标.
            /// </summary>
            private int wr_nxt = 0;
    
            /// <summary>
            /// 下一次读取接收缓冲区的开始下标.
            /// </summary>
            private int rd_nxt = 0;
    
            private int readTimeout = -1;
    
            private int writeTimeout = -1;
    
            private Semaphore writeSemaphore = new Semaphore(1, 1);
    
            /// <summary>
            /// 缓冲区所使用的数组.
            /// </summary>
            private T[] dataBuf;
    
            private object bufLock = new object();
    
            /// <summary>
            /// 如果当前缓冲区中有数据可读, 它将会被设置.
            /// </summary>
            private Semaphore readSemaphore = new Semaphore(0, 1);
    
            /// <summary>
            /// 创建一个具体默认容量的缓冲区.
            /// </summary>
            public ArrayBuffer()
                : this(DFLT_SIZE) {
            }
    
            /// <summary>
            /// 创建一个指定容量的缓冲区.
            /// </summary>
            /// <param name="capacity">缓冲区的容量.</param>
            public ArrayBuffer(int capacity)
                : this(new T[capacity]) {
            }
    
            /// <summary>
            /// 使用指定的数组来创建一个缓冲区.
            /// </summary>
            /// <param name="buf">缓冲区将要使用的数组.</param>
            public ArrayBuffer(T[] buf)
                : this(buf, 0, 0) {
            }
    
            /// <summary>
            /// 使用指定的数组来创建一个缓冲区, 且该数组已经包含数据.
            /// </summary>
            /// <param name="buf">缓冲区将要使用的数组.</param>
            /// <param name="offset">数据在数组中的偏移.</param>
            /// <param name="size">数据的字节数.</param>
            public ArrayBuffer(T[] buf, int offset, int size) {
                this.dataBuf = buf;
                capacity = buf.Length;
                available = size;
                space = capacity - available;
                rd_nxt = offset;
                wr_nxt = offset + size;
            }
    
            /// <summary>
            /// 缓冲区还能容纳的元素数目.
            /// </summary>
            public int Space {
                get {
                    return space;
                }
            }
    
            /// <summary>
            /// 缓冲区中可供读取的数据的元素数目
            /// </summary>
            public int Available {
                get {
                    return available;
                }
            }
    
            /// <summary>
            /// get, set 接收缓冲区的大小(元素数目). 默认值为 512K.
            /// Capacity 不能设置为小于 Available 的值(实现会忽略这样的值).
            /// </summary>
            public int Capacity {
                get {
                    return capacity;
                }
                set {
                    lock (bufLock) {
                        if (value < available || value == 0) {
                            return;
                            //throw new ApplicationException("Capacity must be larger than Available.");
                        }
                        if (value == capacity) {
                            return;
                        }
                        if (value > capacity && space ==0) {
                            // 可写空间变为非空, 释放可写信号.
                            writeSemaphore.Release();
                        }
    
                        T[] buf = new T[value];
                        if (available > 0) {
                            available = ReadData(buf, 0, buf.Length);
                            // 下面的用法是错误的!
                            //available = Read(buf, 0, buf.Length);
                        }
                        dataBuf = buf;
                        capacity = value;
                        space = capacity - available;
                        rd_nxt = 0;
                        // 当容量缩小时, 可能导致变化后可写空间为0, 这时wr_nxt=0.
                        wr_nxt = (space == 0) ? 0 : available;
                    }
                }
            }
    
            /// <summary>
            /// Read 方法的超时时间(单位毫秒). 默认为 -1, 表示无限长.
            /// </summary>
            public int ReadTimeout {
                get {
                    return readTimeout;
                }
                set {
                    readTimeout = value;
                }
            }
    
            /// <summary>
            /// Write 方法的超时时间(单位毫秒). 默认为 -1, 表示无限长.
            /// </summary>
            public int WriteTimeout {
                get {
                    return writeTimeout;
                }
                set {
                    writeTimeout = value;
                }
            }
    
            /// <summary>
            /// 清空本缓冲区.
            /// </summary>
            public void Clear() {
                lock (bufLock) {
                    available = 0;
                    space = capacity;
                    rd_nxt = 0;
                    wr_nxt = 0;
                }
            }
    
            /*
            /// <summary>
            /// 将读指针向前移动 num 个单元. 如果 num 大于 Avalable,
            /// 将抛出异常.
            /// </summary>
            /// <param name="num">读指针要向前的单元个数.</param>
            /// <exception cref="ApplicationException">num 大于 Avalable.</exception>
            public void Seek(int num) {
            }
            */
    
            /// <summary>
            /// 未实现.
            /// </summary>
            /// <returns></returns>
            public T ReadOne() {
                throw new Exception("Not supported.");
            }
    
            /// <summary>
            /// 从缓冲区中读取数据. 读取的字节数一定是 buf.Length 和 Available 的较小者.
            /// </summary>
            /// <param name="buf">存储接收到的数据的缓冲区.</param>
            /// <returns>已经读取的字节数. 一定是 size 和 Available 的较小者.</returns>
            public int Read(T[] buf) {
                return Read(buf, 0, buf.Length);
            }
    
            /// <summary>
            /// 从缓冲区中读取数据. 读取的字节数一定是 size 和 Available 的较小者.
            /// 本方法是线程安全的.
            /// </summary>
            /// <param name="buf">存储接收到的数据的缓冲区.</param>
            /// <param name="offset">buf 中存储所接收数据的位置.</param>
            /// <param name="size">要读取的字节数.</param>
            /// <returns>已经读取的字节数. 一定是 size 和 Available 的较小者.</returns>
            public int Read(T[] buf, int offset, int size) {
                if (!readSemaphore.WaitOne(readTimeout, false)) {
                    throw new ApplicationException("Read timeout.");
                }
    
                lock (bufLock) {
                    int nread = ReadData(buf, offset, size);
                    if (space == 0) {
                        // 释放可写信号.
                        writeSemaphore.Release();
                    }
                    space += nread;
                    available -= nread;
                    if (available > 0) {
                        // 释放一个信号, 以便下一次再读.
                        readSemaphore.Release();
                    }
                    return nread;
                }
            }
    
            /// <summary>
            /// 把本缓冲区的数据复制指定的数组中, 并移动读指针.
            /// </summary>
            private int ReadData(T[] buf, int offset, int size) {
                int nread = (available >= size) ? size : available;
                // 当 rd_nxt 在 wr_nxt 的左边时, 缓冲的右边包含的网络字节数.
                int rdata = capacity - rd_nxt;
                if (rd_nxt < wr_nxt || rdata >= nread/*隐含rd_nxt >= wr_nxt*/) {
                    Array.Copy(dataBuf, rd_nxt, buf, offset, nread);
                    rd_nxt += nread;
                } else {
                    // 两次拷贝.
                    Array.Copy(dataBuf, rd_nxt, buf, offset, rdata);
                    rd_nxt = nread - rdata;
                    Array.Copy(dataBuf, 0, buf, offset + rdata, rd_nxt);
                }
                return nread;
            }
    
            /// <summary>
            /// 写入数据到缓冲区.
            /// </summary>
            /// <param name="buf">要写入的数据的缓冲区.</param>
            public void Write(byte[] buf) {
                Write(buf, 0, buf.Length);
            }
    
            /// <summary>
            /// 写入数据到缓冲区. 注意: 本方法不是线程安全的.
            /// </summary>
            /// <param name="buf">要写入的数据的缓冲区.</param>
            /// <param name="offset">数据缓冲区中要写入数据的起始位置.</param>
            /// <param name="size">要写入的字节数.</param>
            /// <exception cref="ApplicationException">如果空间不足, 会抛出异常.</exception>
            public void Write(byte[] buf, int offset, int size) {
                int n_left = size;
                int n_offset = offset;
                int nwrite;
                int rspace;
                while (n_left > 0) {
                    // 这样的超时控制并不准确!
                    if (!writeSemaphore.WaitOne(writeTimeout, false)) {
                        throw new ApplicationException("Write timeout.");
                    }
    
                    lock (bufLock) {
                        nwrite = (space >= n_left) ? n_left : space;
                        // 当 rd_nxt 在 wr_nxt 的左边时, 缓冲的右边可以放置的网络字节数.
                        rspace = capacity - wr_nxt;
                        if (wr_nxt < rd_nxt || rspace >= nwrite/*隐含wr_nxt >= rd_nxt*/) {
                            Array.Copy(buf, n_offset, dataBuf, wr_nxt, nwrite);
                            wr_nxt += nwrite;
                            if (wr_nxt == capacity) {
                                wr_nxt = 0;
                            }
                        } else {
                            // 两次拷贝.
                            Array.Copy(buf, n_offset, dataBuf, wr_nxt, rspace);
                            wr_nxt = nwrite - rspace; // 是调用下一句之后的 wr_nxt值.
                            Array.Copy(buf, n_offset + rspace, dataBuf, 0, wr_nxt);
                        }
                        if (available == 0) {
                            readSemaphore.Release();
                        }
                        space -= nwrite;
                        available += nwrite;
                        if (space > 0) {
                            // 释放可写信号.
                            writeSemaphore.Release();
                        }
    
                        n_offset += nwrite;
                        n_left -= nwrite;
                    }
                } // end while
    
                /* 不需要 WriteTimeout 的版本.
                // 和 Read 是对称的.
                lock (bufLock) {
                    if (space < size) {
                        // TBD: 是否实现写超时机制?
                        throw new ApplicationException("Not enough space.");
                    }
    
                    // 当 wr_nxt 在 rd_nxt 的左边时, 缓冲的右边可以放置的网络字节数.
                    int rspace = capacity - wr_nxt;
                    if (wr_nxt < rd_nxt || rspace >= size) {
                        Array.Copy(buf, offset, dataBuf, wr_nxt, size);
                        wr_nxt += size;
                    } else {
                        // 两次拷贝.
                        Array.Copy(buf, offset, dataBuf, wr_nxt, rspace);
                        wr_nxt = size - rspace;
                        Array.Copy(buf, offset + rspace, dataBuf, 0, wr_nxt);
                    }
                    if (available == 0) {
                        readSemaphore.Release();
                    }
                    space -= size;
                    available += size;
                }
                */
            }
    
        }
    
    }
    
    Posted by ideawu at 2008-04-02 19:46:03
|<<<34567891011>>>| 7/14 Pages, 84 Results.