About
RSS

Bit Focus


C++ 中的左值

已经转移到 http://zlo.gs/p/neuront/left-hand-value-in-cpp

Permanent Link: ?p=85 Load full text

Post tags:

 C++
 Left Value
 Operator Overload

char** 不能赋值给 char const**

已经转移至 http://zlo.gs/p/neuront/cannot-convert-pointer-to-pointer-to-char-into-pp-to-const-char

Permanent Link: ?p=83 Load full text

Post tags:

 C
 C++
 const

GCC 的花招: 嵌套函数

    这里所说的 GCC 不是 GNU Compiler Collection, 而是单单指代 GNU C Compiler. 这篇文章并不打算讲标准 C 中的任何东西, 而是要聊聊一个 GCC 的特性: 嵌套函数.
    先来个例子, C 版的 for_each 结合嵌套函数 (必须存为 .c 文件, 使用 gcc 编译才能通过, g++ 压力大)
#include <stdio.h>

void for_each(int* begin, int const* end, void (* fn)(int*))
{
    while (begin < end) {
        fn(begin++);
    }
}

#define ARRAY_SIZE 5

int main(void)
{
    int a[ARRAY_SIZE];
    int n;
    void read(int* x)
    {
        scanf("%d", x);
    }
    for_each(a, a + ARRAY_SIZE, read);
    scanf("%d", &n);

    void add(int* x)
    {
        *x = *x + n;
    }
    for_each(a, a + ARRAY_SIZE, add);

    void print(int* x)
    {
        printf("%d ", *x);
    }
    for_each(a, a + ARRAY_SIZE, print);
    printf("end\n");
    return 0;
}
    这代码的紧凑程度虽然跟闭包没得比, 但是使用与定义能放在一起, 就算是一大进步了. 另一个福利在 add 函数, 它引用了一个局部变量 n, 是在外层函数 main 中定义的. 而 n 的使用并不在 main 的可控范围内, 也许它绕过 for_each 的栈帧, 再继续向上被 add 引用. 这听起来像魔法一样, 幸而 gcc 是个开源软件, 不必担心使用这个特性时会让自己的灵魂落入某个兼职程序员的邪恶巫师手中. 但是这到底是如何实现的呢? 要我讲解 gcc 源码我还没有这个能力, 不过 gcc 有个功能可以让我们比较方便地窥探出其中的技术内幕
$ gcc 源文件 -S -o 目标文件
这样源文件会被编译成汇编指令, 接着分析汇编指令好了.
    上面那个例子情况比较复杂, 不妨分析下面这段简短的代码
void func(int a, int* b, int c)
{
    int nested(void)
    {
        return a + c;
    }
    *b = nested();
}
    这段代码在我机器上 (环境: x86 / Ubuntu 9.10 / GCC 4.4.1) 编译得到的汇编代码如下

Permanent Link: ?p=82 Load full text

Post tags:

 Assembly
 GCC
 for_each
 Nested Function

STL 悲剧之 for_each

    这篇文章谈一个我使用 STL 中 for_each 的负面心得. 我对这个东西在当前 C++ 语法下约束是否能广泛使用持有怀疑态度, 至于能否替代所有的 for 循环, 我持完全否定观点! 如果您发现文中提及的这档子事情本质上是我不了解 STL 而自寻死路, 请不吝赐教, 在下方回复, 在下感激不尽.

    在 Google 中输入 "for_each" 然后猛击 "I’m feeling lucky", 这时我幸运地跳转到大名鼎鼎的 sgi 的网站里, 页面中有个例子
template<class T> struct print : public unary_function<T, void>
{
    print(ostream& out) : os(out), count(0) {}
    void operator() (T x) { os << x << ' '; ++count; }
    ostream& os;
    int count;
};

int main()
{
    int A[] = {1, 4, 2, 8, 5, 7};
    const int N = sizeof(A) / sizeof(int);

    print<int> P = for_each(A, A + N, print<int>(cout));
    cout << endl << P.count << " objects printed." << endl;
}
    从泛型党的视角看来, 这例子非常不错, 完备而规范地演示了 for_each 的用法. 从此泛型党成了大赢家, 除了 for_each 内部, 外面的代码再也不需要 for 这个关键字了.
    而那些说写 C++ 代码像谈话一样简短, 基本上泛型编程完全不及格的程序员, 在写上面功能的时候一般会这样做
int main()
{
    int A[] = {1, 4, 2, 8, 5, 7};
    const int N = sizeof(A) / sizeof(int);

    int i;
    for (i = 0; i < N; ++i)
        cout << A[i] << ' ';
    cout << endl << i << " objects printed." << endl;
}
    在喷这个改编版的丑陋之前, 不妨先淡定下来, 想想这个例子到底想做什么, 无非是给个数组 (或者其它什么容器) 把每个成员输出 (或者做个什么其它简单的操作), 并记录被操作的元素个数. 然而, 完成这个操作的代码量与它的功能相比, 臃肿得令人发指. 所以, 在用了几次 for_each 之后, 我完全丧失了当初的激情, 变得极其懒惰, 不愿意把简单的操作抽取到函数外部构造成一个对象然后传递给 for_each; 在维护自己以前写的代码时, 也会偷偷把 for_each 改回 for 循环, 因为有的时候我实在不知道伙伴们把我弄出来的那个函数对象类型给维护到哪里去了.
    当然, 我并不认为这是 for_each, 或者 STL, 或者泛型的错. 在我心目中, 泛型思想是风骚的, for_each 的设计是超前的, 问题出在 C++ 语法这个悲剧帝身上, 或者说, 硬要用 C++ 这个传统的面向过程加面向对象语言的语法来包装对象, 来实现类似高阶函数这种函数式编程中的特性, 是悲剧的根源所在. 不仅是 for_each, 连 find_if 等类似的 STL 函数都差不多一样的下场, 与其构造一个精妙绝伦的函数对象类型, 程序员还不如老老实实写个破循环来得实在.
    一个振奋人心的消息是, C++ 新标准即将发布了, 它会支持闭包对象, 那样的话, for_each 以及其它函数就不会像现在这么处境尴尬了.

Permanent Link: ?p=81 Load full text

Post tags:

 C++
 STL
 for_each

STL set 悲剧指导

    这篇文章谈一个我使用 STL 中 set 容器的负面心得. 是的, 我已经被这丫的杀得超神了, 快来人阻止它吧! 如果您发现文中提及的这档子事情本质上是我不了解 STL 而自寻死路, 请不吝赐教, 在下方回复, 在下感激不尽.

    最坏对数时间插入, 删除, 查询, 迭代遍历, 这些听起来都无比诱人, 它们由 STL 中的 set 容器鼎力支持. 然而, set 的只读制度是非常龌龊的, 简而言之, 只要你敢往这个坑里面放, 你就得接受它们以后再也无法修改的命运. 比如下面这段例子
#include <set>
#include <string>

using std::set;
using std::string;

struct student {
    string name;
    int grade;

    student(string const& name_, int grade_)
        : name(name_)
        , grade(grade_)
    {}

    bool operator<(student const& rhs) const
    {
        return name < rhs.name;
    }

    bool operator==(student const& rhs) const
    {
        return name == rhs.name;
    }
};

int main(void)
{
    set<student> students;
    students.insert(student("Li Lei", 5));
    students.insert(student("Han Meimei", 5));
    students.insert(student("Jim Green", 5));

    for (set<student>::iterator i = students.begin();
         students.end() != i;
         ++i)
    {
        ++(i->grade);
    }
    return 0;
}
    student 类的 key 是 name, 跟 grade 没有关系, 原则上来说, 修改后者并不会破坏 set 的存储结构. 然而, 编译器一棒子打死, 不许改, 除非剩下的成员全部 mutable 修饰.
    只读制度悲剧的根源在于, set 所谓的 key 撑死只是个假象, value_type 这玩意儿就是 key_type 本身.
    伪 key 导致的不仅仅是不能改, 重要的是还不能查! 看看 set::find 函数的参数, 要的又是阴魂不散的 key_type. 这意味着什么? 意味着 Han MM 同学报出她名字的时候, 还查不出她几年级, 而必须要利用她的名字, 伪造一个充气娃娃放进去才能找到! 看到这里我就败了, 这明摆着就是不让我用 set, 让我转投 map 么? 一个也许可行的方案是
#include <map>
#include <string>

using std::map;
using std::string;

struct student_periphery {
    int grade;
};

map<string, student_periphery> students;
这样建模的话也是够狗血的, 如果哪个函数拿着一份 student_periphery 问怎么查出学生姓名, 那就更悲剧了.

Permanent Link: ?p=79 Load full text

Post tags:

 set
 C++
 STL

django 架设网站入门指南[贰]

上节回顾 – ORM 和数据库

创建 admin 应用

    打开 guestbook/urls.py 仔细研究一下注释, 会看到有几行写着, 取消注释来激活 admin. django 的 admin 应用是一个非常不错的后台. 现在就来开启它吧
from django.conf.urls.defaults import *

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Example:
    # (r'^guestbook/', include('guestbook.foo.urls')),

    # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
    # to INSTALLED_APPS to enable admin documentation:
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    (r'^admin/', include(admin.site.urls)),

    (r'^$', 'guestbook.home.views.display'),
    (r'^echo/$', 'guestbook.home.views.echo'),
    (r'^save/', 'guestbook.home.views.save_message'),
)
    因为是应用, 所以呢, 还得去 settings.py 登记
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
    'guestbook.home',
)
    最后要记得执行数据库同步来创建 admin 相关的表
$ guestbook/manage.py syncdb
    现在转到 http://localhost:8000/admin/ 会看到登录提示页面啦. 现在填入第一次 syncdb 时输入的帐号密码就能登入了. 不过现在的 admin 还很挫, 甚至不能管理留言. 进入 guestbook/home 目录, 创建 admin.py 源文件, 加入如下内容
from guestbook.home.models import Message
from django.contrib import admin

admin.site.register(Message)
    刷新页面, 唉, 没有反应, 因为服务器仅监视那些改动过的文件并重新载入, 这次是单独添加的文件所以没有自动重置, 所以得重启服务器才行. 然后, 就能在 admin 应用中看到留言对象并修改它们了.

定制 admin

Permanent Link: ?p=77 Load full text

Post tags:

 django
 Tutorial
 Web Server
 Python

django 架设网站入门指南[壹]

上节回顾 – 配置 基本视图和逻辑

数据库配置

    仍然在 settings.py 中, 找到 DATABASE_ 开头的项目. 现在用 sqlite3 作为数据库, 它已经集成在 python 2.5 以后的版本中, 这样就省去了安装配置的环节. 现在修改这些项目
DATABASE_ENGINE = 'django.db.backends.sqlite3'
DATABASE_NAME = 'guestbook/db_file'
这里 DATABASE_NAME 同样需要给出文件的绝对路径, 原理跟之前模板目录那个一样, 如果不能确定每次的工作目录, 那么就填绝对 db_file 的路径吧. 保存设置, 然后执行数据库同步操作
$ guestbook/manage.py syncdb
会输出提示
Creating table auth_permission
Creating table auth_group
Creating table auth_user
Creating table auth_message
Creating table django_content_type
Creating table django_session
Creating table django_site

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no):
这些是 django 为内置的用户, 会话等类型建立的表, 最后询问是否立即建立一个超级用户. 这里答 yes (仅一个 y 是不行的唉), 然后输入用户名, 电子邮箱和密码. 最后会建立表的索引, 然后结束. 现在, 你可以在 guestbook 目录下看到文件 db_file 了, 它是数据库使用的文件.

ORM 和数据库操作

    django 的 ORM 非常轻松. 打开 home 目录下的 models.py, 建立留言类型
from django.db import models

class Message(models.Model):
    name = models.CharField(max_length=32)
    content = models.CharField(max_length=32)
    dt = models.DateTimeField(auto_now=True)
注, 使用 django 的 ORM, 该类型需要继承于 models.Model, 而要往数据库中放的数据项, 需要是 models 模块中的对应的域类型. 至于 auto_now=True, 它指出时间和日期在该对象插入数据库时自动使用当前日期时间.
    类型弄好了, 得再同步一次数据库. 这些操作可以不重启服务器
$ guestbook/manage.py sql home
$ guestbook/manage.py syncdb
    回到 guestbook/home/views.py, 增加函数 save_message, 让它将表单数据存入数据库, 并重定向回到首页

Permanent Link: ?p=76 Load full text

Post tags:

 Web Server
 Tutorial
 Python
 django
 ORM

django 架设网站入门指南[零]

安装

    根据 django 官方文档, 需要 python 2.3 或更高版本. 不过按现在的 python 普及程度, 想必大家的机器上都有 python 2.5 或 2.6 了. 我的操作系统是 ubuntu 9.10, 自带的是 2.6 版本.
    debian 用户安装 django 很简单, 只需要
# apt-get install python-django
就可以了, 其它发行版看有没有类似的方法. 或者在官方站点下载源代码安装
    祝好运.

建立项目 startproject

    首先找到一个地方, 建立一个项目 guestbook, 我们将在这个项目中搭建一个留言板.
$ django-admin startproject guestbook
有些系统中 django-admin 并非一个命令, 需要
$ python django-admin.py startproject guestbook
    执行完这个之后, 当前目录下会创建一个名为 guestbook 的目录, 里面包含了一个最简单的服务器: 显示一个主页. 执行
$ python guestbook/manage.py runserver
启动后会看到类似以下输出
Validating models...
0 errors found

Django version 1.1.1, using settings 'guestbook.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
这时, manage.py 已经在本地 8000 端口创建了一个服务器, 赶快打开浏览器去访问吧!

    为 guestbook/manage.py 加上可执行属性 (在 ubuntu 9.10 下该属性已经自动添加了)
$ chmod u+x guestbook/manage.py

创建应用 startapp

    在 django 世界的哲学里, 每个功能称之为一个应用. 创建应用也使用 manage.py 来完成. 比如现在用以下命令创建一个首页应用
$ guestbook/manage.py startapp home
这时 guestbook 目录下会多出一个 home 目录, 里面有这些文件
__init__.py
models.py
tests.py
views.py
    比较烦的是, 这时得回去修改设置, 打开 settings.py 查找 INSTALLED_APPS, 在这一坨里面加一行
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'guestbook.home',
)
    这样 home 应用才算是有了名分. 好, 现在再来实现功能. 因为现在只是处理页面, 所以只需要在 guestbook/home/views.py 里面修修补补就好了. 打开它, 其实相当于是个空文件, 把这一段代码放进去
from django.http import HttpResponse

def display(req):
    return HttpResponse('<html><body>hello, django!')
    我知道你已经不耐烦了, 如果你曾经写 php 的话. 不过现在还有最后一步, 修改路径映射. 打开 guestbook/urls.py, 在里面加一句话

Permanent Link: ?p=74 Load full text

Post tags:

 Web Server
 Tutorial
 django
 Python

Makefile 与 C 语系头文件依赖自动解析

已经转移到 http://zlo.gs/p/neuront/makefile-c-auto-dependency

Permanent Link: ?p=63 Load full text

Post tags:

 C
 C++
 Makefile

编译期数值计算程序设计思路

已经转移到

http://zlo.gs/p/neuront/compile-time-calculation-in-cpp

Permanent Link: ?p=50 Load full text

Post tags:

 Template
 Metaprogramming
 C++

划分问题与连续自然数幂和之通项公式

已经转移到

http://zlo.gs/p/neuront/number-of-parts-when-geometry-cut

Permanent Link: ?p=45 Load full text

Post tags:

 Algebra
 Algorithm
 Geometry

泛型编程中的策略类

已经转移到

http://zlo.gs/p/neuront/traits-classes-in-generic-programming

Permanent Link: ?p=36 Load full text

Post tags:

 Generic Programming
 C++
 Template

闰年判定

已经转移到

http://zlo.gs/p/neuront/leap-year-test-algorithm

Permanent Link: ?p=25 Load full text

Post tags:

 Algorithm

已知两圆圆心坐标及半径求两圆交点

已经转移到

http://zlo.gs/p/neuront/circles-intersections-algorithm

Permanent Link: ?p=14 Load full text

Post tags:

 Algorithm
 C
 Geometry

0 1 2 3 4 5 6 7 8 9 10 Page 11 12


. Back to Bit Focus
NijiPress - Copyright (C) Neuron Teckid @ Bit Focus
About this site