分类存档: 编程

will_paginate的twitter/bootstrap样式定义

说明

will_paginate 是一个Ruby on Rails 的分页插件

bootstrap 是一个twitter开发的前端toolkit

bootstrap 中包含了分页的样式 查看

will_paginate 的原有样式和 bootstrap 中分页样式不一致,所以就需要自己定义,下面是方法

0.效果

1.在 rails 项目目录的 lib/ 下新建 bootstrap_link_renderer.rb 加入如下代码
查看代码

2.在 rails 项目目录的 config/application.rb  加入下面的代码以自动加载 lib/

1
config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]

3.使用的
在 view 中使用如下代码

1
<%= will_paginate(@users, :renderer => BootstrapListLinkRenderer) %>

打完收工

解决使用proguard和scoreloop时打开scoreloop活动(activity)引起强制关闭的问题

在proguard.cfg的末尾加入

-keep class com.scoreloop.client.android.ui.** { *; }
-keep class com.scoreloop.client.android.ui.component.achievement.** { *; }
-keep class com.scoreloop.client.android.ui.component.agent.** { *; }
-keep class com.scoreloop.client.android.ui.component.base.** { *; }
-keep class com.scoreloop.client.android.ui.component.challenge.** { *; }
-keep class com.scoreloop.client.android.ui.component.entry.** { *; }
-keep class com.scoreloop.client.android.ui.component.game.** { *; }
-keep class com.scoreloop.client.android.ui.component.market.** { *; }
-keep class com.scoreloop.client.android.ui.component.news.** { *; }
-keep class com.scoreloop.client.android.ui.component.post.** { *; }
-keep class com.scoreloop.client.android.ui.component.profile.** { *; }
-keep class com.scoreloop.client.android.ui.component.score.** { *; }
-keep class com.scoreloop.client.android.ui.component.user.** { *; }
-keep class com.scoreloop.client.android.ui.framework.** { *; }
-keep class com.scoreloop.client.android.ui.util.** { *; }
-keep class com.facebook.android.** { *; }
-keep class com.scoreloop.client.android.core.** { *; }
-keep class com.scoreloop.client.android.core.addon.** { *; }
-keep class com.scoreloop.client.android.core.controller.** { *; }
-keep class com.scoreloop.client.android.core.model.** { *; }
-keep class com.scoreloop.client.android.core.persistence.** { *; }
-keep class com.scoreloop.client.android.core.server.** { *; }
-keep class com.scoreloop.client.android.core.settings.** { *; }
-keep class com.scoreloop.client.android.core.spi.** { *; }
-keep class com.scoreloop.client.android.core.spi.myspace.** { *; }
-keep class com.scoreloop.client.android.core.spi.oauthfacebook.** { *; }
-keep class com.scoreloop.client.android.core.spi.twitter.** { *; }
-keep class com.scoreloop.client.android.core.ui.** { *; }
-keep class com.scoreloop.client.android.core.util.** { *; }

然后重新导出APK就可以了。

2011-9-21更新:
完整的scoreloop列表

Java 的反射伤不起啊。

conversion to dalvik format failed with error 1 解决方法

博主在 Android 开发过程中使用 eclipse 中的 Android Tools 导出 APK 的时候出现了 conversion to dalvik format failed with error 1错误。不使用 ProGuard 就可以不出现这个错误,当然博主既想使用 ProGuard 又不想出现这个错误,谷歌后尝试过很多方法未果。
直到看到  http://sagistech.blogspot.com/2011/07/error-conversion-to-dalvik-format.html 中的评论

Vito Cassisi said…
Upgrading to ProGuard 4.6 worked for me.

于是解决的方法如下

1. 到 这里 下载 ProGuard 最新版,博主下载的时候最新版是4.6。 最新 Android SDK 中的 ProGuard是 4.4;

2. 到 [Android SDK 安装目录]\tools 找到 proguard 文件夹,备份下;

3. 解压下载到的 proguard4.6.zip ;

4. 用解压出来的 bin、lib两个文件夹覆盖 [Android SDK 安装目录]\tools\proguard 中的同名文件夹;

5. 问题解决。使用 Android Tools 导出 APK 吧。

AndEngine的HelloWorld

AndEngine 今天的主角,是一个 Android 平台的开源 2D OpenGL 游戏引擎,采用 GNU Lesser GPL,包含游戏引擎的常用功能,同时内置了Box2D物理引擎,你可以非常方便的在你的程序里面使用物理效果。。下面将要通过一个 HelloWorld 来介绍 Android 的基本用法。

1.准备工作

1)eclipse、Android SDK的安装配置,这个就不用多说,具体自行Google

2)签出 AndEngine 以及 AndEngineExamples 的代码,eclipse的插件 Mercurial Eclipse 就可以轻松签出,它们的版本库地址分别是

https://andengine.googlecode.com/hg/

https://andengineexamples.googlecode.com/hg/

2.在 Eclipse 中新建一个 Android 项目, File->New->Android Project  ,输入相应的内容,注意Build Target选择 1.6 点击 Finish

3 .把 AndEngine 加入到上一步新建的项目中

方法一:加入 AndEngine 的代码到 项目中,把准备工作中签出的 AndEngine 项目中 src目录的 文件 复制到 上一步新建的项目 目录中的 src 里面。这样做的好处是你可以自由的修改 AndEngine 的源代码

方法二:加入 andengine.jar 到项目中,在上一步新建的项目中新建文件夹 “lib”,把准备工作中签出的 AndEngine 项目中 lib 目录下面的 andengine.jar,在 eclipse 的 Package Explorer 中的新建项目中找到  andengine.jar ,右键->Build Path ->Add to Build Path。这样做的好处是方便简洁

4.HelloWorld,修改项目中原有的 Activity,代码如下,注意类名的一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import org.anddev.andengine.ui.activity.BaseGameActivity;
import org.anddev.andengine.entity.primitive.Line;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.background.ColorBackground;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;

public class helloae extends BaseGameActivity {
      // ===========================================================
    // Constants
    // ===========================================================

    private static final int CAMERA_WIDTH = 720;
    private static final int CAMERA_HEIGHT = 480;

    // ===========================================================
    // Fields
    // ===========================================================

    private Camera mCamera;

    // ===========================================================
    // Constructors
    // ===========================================================

    // ===========================================================
    // Getter & Setter
    // ===========================================================

    // ===========================================================
    // Methods for/from SuperClass/Interfaces
    // ===========================================================

    @Override
    public Engine onLoadEngine() {
            this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
            return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera));
    }

    @Override
    public void onLoadResources() {
    }

    @Override
    public Scene onLoadScene() {
            this.mEngine.registerUpdateHandler(new FPSLogger());

            final Scene scene = new Scene(1);
            scene.setBackground(new ColorBackground(1.0f, 1.0f, 1.0f));
            final Line line = new Line(0,240, 720, 240, 5.0f);

            line.setColor(1, 0, 0);
            scene.getFirstChild().attachChild(line);
           
            return scene;
    }

    @Override
    public void onLoadComplete() {

    }

    // ===========================================================
    // Methods
    // ===========================================================

    // ===========================================================
    // Inner and Anonymous Classes
    // ===========================================================
}

添加完这段代码之后,别忘了在你项目的AndroidManifest.xml 中添加
<uses-permission android:name=”android.permission.WAKE_LOCK”/ >

5.运行

运行截图

没错,就是在屏幕中间绘制一条红色的横线。
参考:AndEngine初步

Lua学习笔记(4)–函数

说明:Lua学习笔记的内容都是《Lua程序设计.第二版》的读书笔记,笔记中很多内容都是来自于书中

1.函数参数

1)无论函数的哪种用法都要将所有参数放到一对圆括号中。即使调用函数时没有参数,也必须写出一对空括号。对于此规则只有一个中特殊的例外情况:一个函数若只有一个参数,并且此参数是一个字面字符串或是table构造式,那么可以不用括号,例如:

1
2
3
4
5
6
print "HW" <--> print("HW")
dofile 'a.lua' <--> dofile(a.lua)
print [[a multi-line
 message]]
f{x=10, y=20}
type{}

2.函数的多重返回值,这点和其他很多语言不一样,lua中的函数可以有多个返回值,在return 后面用逗号将多个返回值隔开即可

1)如果一个函数调用不是一系列表达式的最后一个元素,那么只产生一个值,如果函数没有返回值则是nil,

1
2
3
4
function foo0() end
function foo2() return "a", "b" end
x, y = foo2(), 20 -- x= "a", y = 20
x,y = foo0(), 20, 30 -- x = nil ,y=20,30被X掉了

2)如果一个函数调用是一系列表达式的最后一个元素,那么则按多重赋值的方式处理

3)table构造式可以完整的接受函数调用的结果,前提是table构造式的最后一个表达式

4)使用()强制函数只返回一个值

5)return f()返回f的所有返回值

3.可变参数

1)简单的例子,…为一个表达式,行为类似于一个多个返回值的函数

1
2
3
4
5
6
7
funtion add(...)
local s = 0
     for i,v in ipais{...} do
          s = s + v    
     end
return s
end

2)funtion foo(…) return … end是一个“多值恒定试”可以用于跟踪(trace)可变参数函数的可变参数,例:

1
2
3
4
function foo1(...)
print("calling foo:",  ...)
     return foo(...)
end

3)通常使用表达式{…}就可以遍历变长参数,如果可变参数列表中有nil,则使用select来访问可变参数列表

1
2
3
4
for i = 1, select('#', ...) do
local arg = select(i, ...) -- 得到第i个参数
     --do sth
end

4.具名参数,lua并不存在像python那样的具名参数,使用的是函数参数不用括号的规则之一,table构造式来变相的使用具名参数,例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
w = Window{x = 0, y=0,
                 width=300,height=200,
                 title="lua", background="blue",
                 border = true}

function Window(option)
--检查必要参数
     if type(option.title) ~= "string" then
          error("no title")
     elseif type(option.width) ~= "number" then
          error("no width")
     elseif type(option.height) ~= "number" then
          error("no height")
     end
     
     --其他参数都是可选的
     _Window(option.title,
                  option.x or 0,
                  option.y or 0,
                  option.width, option.height,
                  options.background or "white",
                  options.border -- 默认为false(nil)
                  )
end

Lua学习笔记(3)–语句

说明:Lua学习笔记的内容都是《Lua程序设计.第二版》的读书笔记,笔记中很多内容都是来自于书中

1.赋值

1)赋值(assignment)的基本含义:修改一个变量或是一个table中元素的值

2)多重赋值:将多个值赋予多个可赋值对象,每个值和每个可赋值对象用逗号隔开,例如

1
a,b = 10, 2 * x -- a的值为10 b的值为2 * x

同时,先对=(赋值)右边的的所有元素求值,再进行赋值,用此可以很方便的交换两个变量的值

1
x, y = y, x

lua总是会将等号右边值的个数调整到和左边一致,如果值的个数少于变量的个数,那么多余的变量赋值为nil,如果值更多,则丢弃 ,注意:尽量保证=(赋值号)左右个数一致来避免一些隐性的错误,例:

1
2
a, b, c = 0,1 -- a = 0, b=1, c = nil
a, b = 0,1,2 -- a = 0, b=1,2被丢弃

2.局部变量:使用local来定义一局部变量,lua中局部变量的概念和其他语言类似,在此不再赘述,使用 do-end来强制创建一个作用域,在lua中有一种习惯写法是

1
local foo = foo

这个语句创建一个局部变量foo并用全局变量foo的值来初始化,这个语句可以保存foo的值,或是加快相应作用域对foo的访问

注:lua中没有用local定义的变量都是全局变量

3.控制结构

1)选择结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if a < 0 then a = 0 end
if a< 0 then a = 0 else a = 1 end

if op == "+" then
     r = a +b
elseif op == "-" then
     r = a - b
elseif op == "*" then
     r = a * b
elseif  op == "/" then
     r = a / b
else
     error("xxx")
end

lua中没有switch语句

2)循环

①while用法 conditon为假时退出循环

1
2
3
while <conditon> do
     -- do sth
end

②repeat-until(重复直到):condition为真时退出循环 condition中的表达式可以访问循环体中的局部变量

1
2
3
repeat
     -- do sth
until <conditon>

③数字型for

1
2
3
for var = exp1, exp2, exp3 do
     --do sth
end

var 从exp1变化到exp2以exp3为步长如果不指定exp3默认为1 exp1,exp2,exp3在循环开始时一次性求值
同时,要取出循环体内的变量必须copy到一个有更大作用域的变量中

1
2
3
4
5
6
7
8
9
10
--在列表中查找一个值
local found = nil

for i = 1, #a do
     if a[i] < 0 then
          found = i
          break    
     end
end
print(found)

④泛型for,例子

1
2
3
4
5
6
7
8
--输出table a中的所有value
for i,v in ipairs(a) do
     print(v)
end
--输出table a中的所有key
for k in pairs(a) do
     print(k)
end

⑤for的特点 :循环体中的都是局部变量、决不硬挨对循环变量赋值

4.break和return只能是一个语句块后的最后一句

1
2
3
4
funtion foo()
return --语法错误
     do return end -- OK
end

Lua学习笔记(2)–运算符

说明:Lua学习笔记的内容都是《Lua程序设计.第二版》的读书笔记,笔记中很多内容都是来自于书中

1.运算符和优先级

^
not,#,-(符号一元)
*,/,%
+,-
..
<,>,<=,>=,~=,==
and
or

1)从上到下,优先级逐渐降低,除了^(指数)和..(字符串连接)是右结合,其他的都是左结合,本人通常都是使用括号决定运算的顺序

2)算术运算符都可以用于实数

2.%(取模)的特殊说明

1)取模的定义 : a % b == a – floor(a/b)*b

2)对于正实数,x %.1 * 10e-n(n>=0)就是取得x中的小数点n位以后的数字

例如可以使用x – x%1.0e-2来取得精确到小数点两位后的结果,对于负实数则不是这样,可以先取负实数的绝对值,进行之前的         操作,在加上负号

3.关系运算符

1)与c语言不同的有不相等操作符~= 注意尽量不要比较不同类型的值

4.逻辑运算符and,or, not

1)and: 如果它的一个操作数为假就返回第一个操作数,否则返回第二个

2)or:如果它的一个操作数为真就返回第一个操作数,否则返回第二个

3)and和or都是短路求值

4)not永远只返回true 和false

5)技巧,根据 Lua 逻辑运算符的特性可以使用下面的技巧

①x = x or v –如果 x 没有赋值则给 x 一个默认值v 等价于 if not x then x = v end

②(a and b) or c 前提b不为假 则与c中的 a ? b : c  类似,例 max = (x > y) and x or y,解析

根据and和or规则有:如果(x>y)为真,(x>y) and x返回的结果是 x,而x or y 则返回的结果x;如果(x>y)为假,(x>y) and x         返回的结果是 (x>y),因为(x>y)为假(x>y) or y 则返回的结果y

Lua学习笔记(1)

说明:Lua学习笔记的内容都是《Lua程序设计.第二版》的读书笔记,笔记中很多内容都是来自于书中

1.Lua区分大小写;

2.Lua的8中基本类型:nil(空)、boolean(布尔)、number(数字)、string(字符串)、userdata(自定义类型)、  function(函数)、 thread(线程)、 table(表),使用type函数可以确定一个值的类型

1)nil用于区别其他值,用nil来删除全局变量和table中的元素

2)Lua的boolean 将nil和fasle视为”假”,包括0和空字符串都是为”真”

3.Lua的注释:

1)行注释为:

1
--注释内容

2)块注释为:

1
2
3
--[[
注释内容
]]

3.字符串用””(双引号)、‘’(单引号)来包围,也可以使用

1
2
3
4
[[
1
2
]]

包围带格式的字符串,类似于python的

1
2
3
4
'''
行1
行2
'''

如果块中有包含]]可以使用在开头和结尾加上数量相同的等号,例如:

1
===[]===

这种方式同时适用于块注释

4. ..(两个点号)为Lua的字符串连接操作符 ,lua 5.1中, 在字符串前放置#(井号)来获得字符串长度(长度操作符(length operator))

5.table

1)table是lua中的唯一的重要的数据结构机制;

2)table没有固定大小;

3)table可以使用整数和其他类型的值来索引(除了nil);

4)通过key访问table的两种方式[]和. 例如 a[“b”] 和 a.b 是一样的

5)table 的创建,table构造式

例:

1
2
3
4
5
6
7
8
9
10
11
12
a = {}
a = {"one","two","three"}
a = {x = 10, y = 20} -- 等价于a = {};a.x =10; a.y = 20
a["x"] = 10
a[10] = "great"
--显式用一个表达式来初始化索引值:
opnames = {["+"] = "add", ["-"]="sub",
["*"] = "mul", ["/"] = "div"}
i = 20; s = "-"
a = {[i+0] = s, [i + 1] = s..s, [i+2]=s..s..s}
print(opnames[s]) --&gt; sub
print(a[22]) --&gt; ---

6)如果table中的某个元素没有被初始化则那个元素的值为nil

7)如果把table当作数组来用的话使用整数作为索引,与C语言不同索引从1开始,注:虽然可以访问0位置处的值,但是不计入table的长度,可能造成隐式的错误

1
a = {[0] = "one","two","three"}

8)如果table中有空隙即table中间的元素被赋值为nil 则#认为nil为table的结束标志从而导致计数错误,如果table 中没有空隙,使用#来统计长度,否则使用table.maxn来去的table的最大正索引//但是仍然不能处理多个空隙的情况,所以尽量避免把有空隙的table当作数组来使用

9)使用统一的索引方式来操作同一个table的,否则可能造成隐式的错误

10)table构造式创建table时,可以使用;(分号)来代替逗号来区分不同成分,最后一个元素的后面有个,(逗号)也不是错误

顺便做下广告 需要SSH,VPN的同学可以访问 http://www.sshops.net/

ID3DXFont在设备丢失时的操作

ID3DXFont在调用ID3DXFont::DrawText时如果设备已经丢失(Lost)而没有进行处理时会导致程序奔溃。
在窗口处理 WM_SIZE 消息(最大化、最小化、改变窗口大小等)时,会造成设备丢失(Lost)。需要按如下的方法进行Reset:

1
2
3
ID3DXFont::OnLostDevice
IDirect3DDevice9::Reset
ID3DXFont::OnResetDevice

参考:http://topic.csdn.net/u/20081103/16/3ed93cfc-ad5e-4836-b792-25f3d8671231.html

为N卡的D3D程序配置PerfHUD调试工具

首先从nvidia的网站下载PerfHUD调试工具
下载链接为 http://developer.nvidia.com/object/nvperfhud_home.html

然后一路next安装,当然可以根据需要调整安装选项。

这个时候桌面上就会出现一个 “NVIDIA PerfHUD 6 Launcher” 的图标

双击以后就可以进行配置

可以将你的D3D的程序拖到桌面上的“NVIDIA PerfHUD 6 Launcher” 来启动 PerfHUD,但是有一个前提,你的D3D程序需要进行配置,下面贴上创建DirectX9设备的代码,代码来自“PerfHUD 6 Quick Tutorial”(安装完PerfHUD以后“开始”菜单中会有)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Set default settings
UINT AdapterToUse=D3DADAPTER_DEFAULT;
D3DDEVTYPE DeviceType=D3DDEVTYPE_HAL;
#if SHIPPING_VERSION
// When building a shipping version, disable PerfHUD (opt-out)
#else
// Look for 'NVIDIA PerfHUD' adapter
// If it is present, override default settings
for (UINT Adapter=0;AdapterGetAdapterCount();Adapter++)
{
    D3DADAPTER_IDENTIFIER9 Identifier;
    HRESULT Res;
    Res = g_pD3D-&gt;GetAdapterIdentifier(Adapter,0,&amp;Identifier);
    if (strstr(Identifier.Description,"PerfHUD") != 0)
    {
        AdapterToUse=Adapter;
        DeviceType=D3DDEVTYPE_REF;
        break;
    }
}
#endif
if (FAILED(g_pD3D-&gt;CreateDevice( AdapterToUse, DeviceType, hWnd,
              D3DCREATE_HARDWARE_VERTEXPROCESSING,
              &d3dpp, &g_pd3dDevice) ) )
{
    return E_FAIL;
}

:如果使用visual stdio 来开发的话,要使用Release 配置来编译程序,否则在使用PerfHUD的时候会出错。


(这张图片同样来自于“PerfHUD 6 Quick Tutorial”)
在稍后的博文中将会写这个工具如何使用。

Update on 2010-08-13
如果使用PerfHUD出错、异常,请更新显卡驱动到最新版。

c语言文件打开模式

可以使用的模式字符串
“r”
打开文件用于读取,如果文件不存在则返回错误。
“w”
打开文件用于写入,如果文件已经存在,则删除原文件。
“a”
打开文件用于写入文件结尾(附加),在数据没有写入之前不移除EOF,如果文件不存在则创建。
“r+”
打开文件用于读取和写入(文件必须存在)。
“w+”
打开新文件用于读取和写入,如果文件已经存在,则删除源文件。
“a+”
打开文件用于读取和附加,附加操作会在数据写入之前将 EOF 移除,在数据写入之后重新加入 EOF ,如果文件不存在则创建。
注:当使用 “a” 或者 “a+” 模式打开文件时,所有的写入操作都在文件的结尾进行,可以使用 fseek 和 rewind 对文件指针进行重定位,但是写入操作会将文件指针重新移至文件结尾,因此,已经存在的数据不会被覆盖。

当使用 “r+” 、”w+” 、”a+” 模式打开文件时,文件可以读写(也就是文件可以更新),需要注意的是,如果在读写之间进行切换时它们必须介于 fflush, fsetpos , fseek 或是 rewind 之间,如果需要,可以使用 fseek 或者是 fsetpos 来改变当前位置。

附加模式
添加在上面的模式之后
t
以文本模式打开(转换过),在这个模式的输入中,将CRTL+Z 视为 EOF。
b
以二进制模式打开(未转换),回车符和换行符将被忽略。
注:如果 t 或者 b 没有指定,将使用全局变量 _fmode , 如果它们作为模式的前缀,函数调用失败且返回NULL。
c
为关联的文件开启 commit 标识,当 fflush 或者 _flushall 被调用时,数据将直接写入文件。
n
将关联的文件的 commit 标识设为 “no-commit,n为默认值,如果在链接了 COMMODE.OBJ 相应的设置将被覆盖
。如果没有链接 COMMODE.OBJ 全局的默认值为 “no-commit” 。
N
指定文件不被子进程继承。
S
指定文件缓存优化,不强制,顺序方式读取文件。
R
指定文件缓存优化,不强制,随机方式读取文件。
T
指定文件为临时文件,如果可能,将不会写入磁盘。
D
指定文件为临时文件,如果对应的文件指针全部关闭,文件将被删除。

从MSDN  ms-help://MS.MSDNQTR.v90.chs/dv_vccrt/html/c534857e-39ee-4a3f-bd26-dfe551ac96c3.htm 翻译和摘抄。

出现 warning: implicit declaration of function `inet_aton’ 的一种解决办法

在Linux下进行socket编程时,载入相应头文件后调用 inet_aton()时出现警告信息
warning: implicit declaration of function `inet_aton’

Google了下,使用提供的方法未能解决掉这个警告,我是那种见不得一个警告出现的人。于是尝试自己解决。经过各种实验以后发现去掉gcc的编译选项-std=c99后该警告消失。

但是去掉之后不能使用如下的for的形式,变量i必须在循环外部定义。
C code:

1
for(int i = 0; i < LENGTH; ++i);

如果要使用上面这种循环方式的话,可以使用-std=gnu99的编译选项。这样就两全其美了。