0

Using Minipar + position

I want to use a dependency parser, which is free (al least for education purpose). So Minipar might be the right one. There is an example came with the package but parsing result is relied on surface forms. Surface form is easy to understand but it will be problematic when there are 2 duplicated words in the same sentence so I use position of word in the sentence instead and fortunately it is available the API ^_^. I just use head_pos() from node as below:

#include
#include
#include “ptree.h”

#define LINE_SIZE 100000

void
printParseResult(const ParseNode* node)
{
ParseNode* parent = ((ParseNode*) node)->parent();
if (node->relation() && parent && parent->category()) {
if (parent->root() && parent->category() &&
node->category() && node->root() && node->relation()) {
/* print parent head_pos, surface, category */
printf(“%d\t%s\t%s”, parent->head_pos(),
parent->root(),
parent->category());

printf(“\t”);

/* print node head_pos, surface, category */
printf(“%d\t%s\t%s”, node->head_pos(),
node->root(),
node->category());
printf(“\t”);

/* relation */
printf(“%s”, node->relation());

}
printf(“\n”);
}
forall (ParseNode*, sub, TRSTree, node) {
printParseResult(sub);
}
}

int
main(int argc, char **argv)
{
const char *path;
ParseTree parseTree;
char line[LINE_SIZE];

if(argc != 2) {
fprintf(stderr, “Usage: %s \n”, argv[0]);
return EXIT_FAILURE;
}
path = argv[1];
initialize_minipar(path);

while(fgets(line, LINE_SIZE, stdin) != NULL) {
parseTree.reset();
parse(line, parseTree);
printParseResult(parseTree.root());
}
return EXIT_SUCCESS;
}

I use it like this:

$ echo "I like a cat." | ./vparse ../data  2> /dev/null
1	fin	C	2	like	V	i
2	like	V	1	I	N	s
2	like	V	3	I	N	subj
2	like	V	4	cat	N	obj
4	cat	N	3	a	Det	det

$
6

เกิดอะไรขึ้นกับ fgets ถ้า buffer เล็กกว่าความยาวบรรทัด

เวลาเขียนภาษา C เราใช้ fgets ต้องระบุด้วยว่า buffer ขนาดเท่าไหร ประมาณนี้

char buf[80];
fgets(buf, 80, fp);  

จากตัวอย่างข้างบนถ้าบรรทัดยาวกว่า 79 byte (ต้องเหลือที่ไว้ใส่ ” ด้วย) จะเกิดอะไรขึ้น เท่าที่ลองดู fgets มันก็อ่านได้อยู่ดี อ่านได้แค่ไหนก็เอามาแค่นั้น ไม่มีอะไร return ออกมาพิเศษ

แต่ทำอย่างไรจะตรวจสอบได้ว่าอ่านมาไม่หมด เท่าที่คิดได้ตอนนี้คือดูว่าตัวสุดท้ายใน buf เป็น newline หรือเปล่า ถ้าไม่ใช่ก็อาจจะอ่านมาไม่หมด แต่นี้ลองใน Ubuntu 8.04 นะครับ อาจจะมีระบบอื่นๆ กรณีอื่นๆ ที่ต่างออกไป

0

เริ่มต้นใช้ Lua ต่อกับภาษาซี

วันนี้อยากลองใช้ Lua ดูเพราะว่าขี้เกียจ bind อะไรๆ กับ Python เหนื่อย … ใช้ swig ก็งง (พยายามหาเหตุผลมาเล่น Lua) ก็เลย download Lua 5.1.4 มา แล้วก็ก็สั่ง make linux local สิ่งที่ได้จากการ build ก็อยู่ใน folder เดิมๆ หลังจากนั้นผมก็ copy พวก liblua.a, *.h ทั้งหลาย, และ lua จากใน bin ไปไว้ใน folder เดียวกันหมดเลย สร้าง lua_hrule.c ขึ้นมา ทำอะไรไม่เป็นก็เขียนแค่นี้

lua_hrule.c

#include "lua.h"
#include "lauxlib.h"

int
luaopen_hrule(lua_State *L)
{
    return 1;
}

แล้วก็ Makefile

CC=gcc
all:  hrule.so
hrule.so: lua_hrule.c
	$(CC) -shared -o hrule.so lua_hrule.c liblua.a
clean:
	rm -f  hrule.so

จริงๆ แล้ว Makefile ยาวกว่านี้แต่ build อย่างอื่นที่ไม่เกี่ยว พอสั่ง

make

เสร็จแล้ว ผมก็ได้ hrule.so ออกมา ก็เรียก lua แบบนี้

./lua

แล้วก็สั่ง

require "hrule"

ก็ใช้งานได้นะ ไม่มีข้อความอะไรรายงานข้อผิดพลาดออกมา … ตอนนี้ทำได้แค่นี้เอง เดี๋ยวเขียนต่อ :-P

4

แก้ปัญหา C++ บน x86-64

ปัญหา C++ เบา x86-64 ก็คงจะมีได้หลายๆ อย่างแต่ที่ผมเจอคือ

(unsigned int)string.find(“…”) == string::npos()

พอเอา (unsigned int) ออกก็ใช้ได้เลย :-P. กว่าจะเจอแทบแย่ เจอ method ยาว แบบ 300 บรรทัด มี if มี while ซ้อนๆ กันงงๆ หน่อย.

0

make check

เวลาใช้ autotools คำสั่งที่ผมใช้บ่อยมักจะเป็น ./configure, make และ make install ที่มักจะต้องใช้เวลาเอาโปรแกรมมาติดตั้ง.

make check ไม่ค่อยได้เรียก มาเจอแรกๆ ก็ใน libthai. เห็นใน libthai กับ gtest สร้าง folder ขึ้นมาใส่โปรแกรมสำหรับ test เลยผมก็ทำบ้าง. สร้าง test ขึ้นมาแล้วก็เอา Makefile.am ไปใส่ พร้อมกับ sample1.cpp. ที่สำคัญคือต้องแก้ configure.in และ Makefile.am ใน top folder ด้วย ให้สร้าง/เรียก test/Makefile

ใน test/Makefile.am ผมเขียนแบบนี้ (ส่วนมากเป็นท่าที่ลอก libthai มา)

TESTS = sample1 #อันนี้บอกว่า test อะไรบ้าง

# ข้างล่างนี้บอกว่าสร้าง test case อย่างไร
check_PROGRAMS = sample1
sample1_SOURCES = sample1.cpp
sample1_LDADD = $(top_srcdir)/toto/libtit.la # บอกว่าจะ test กับ library อะไร

ใน sample1.cpp ผมเขียนว่า:

int main()
{
return 0;
}

เวลาเรียก make check ก็ผ่านหมด ถ้า return 1 ก็จะ fail แทน

1

สร้าง library เพื่อ test unit

ทีแรกโปรแกรมที่ผมใช้ link กับกลายเป็น executable file ไฟล์เดียวเลย อาจจะทำให้เขียน test unit ยาก (อีกนัยหนึ่งคือผมทำไม่เป็นนั่นเอง) ผมเลยจะสร้างส่วนหนึ่งเป็น library ก่อน.

สมมุติว่าเดิมมี executable file ชื่อ toto (ตั้งตามอ.อานนท์)

Makefile.am ก็จะหน้าตาประมาณ
INCLUDES = -I$(top_srcdir)
bin_PROGRAMS = toto
toto_SOURCES = toto_shell.cpp titi.cpp tata.cpp

แต่ผมก็จะแยก titi tata ออกมาเป็น libtiti ก็จะเขียนแบบนี้

INCLUDES = -I$(top_srcdir)

# เพื่อสร้าง library
lib_LTLIBRARIES = libtiti.la
libtiti_la_SOURCEs = tit.cpp tata.cpp

bin_PROGRAMS = toto
toto_SOURCES = toto_shell.cpp
toto_LDADD = libtiti.la # บอกว่าใช้ toto ไป link กับ libtiti

เท่านี้ก็แยกกันได้แล้ว แต่ก็ไม่ได้เขียนถึง *.h เลย … เวลา make install แล้วใช้ได้จริง หรือเปล่าก็ไม่รู้ อาจจะต้องทำอะไรต่ออะไรอีก. แน่นอนที่เขียนไปคงมีอะไรมั่วมากมาย. แต่ว่าตอนต่อไปผมก็คงยังไม่ลอง install อยู่ดี แต่เน้นทำ test unit ก่อน คงเขียนเรื่อง make check ^_^.

1

googletest + autotools

ผมอยากลองใช้ googletest ที่เอาไว้ทำ unit test สำหรับ C++ ก่อนหน้าที่จะลองเล่นได้มีปัญหาที่มาดักหน้าคือ จะแก้ configure.in (configure.ac) อย่างไรให้ใช้ gtest ได้.

ท่าง่ายแบบใช้ pkg-config ก็ใช้กับกรณีนี้ไม่ได้ด้วย. พยายามจะใช้ AC_CHECK_LIB แต่ก็ยากเกินไปอ้าง method ของ C++ ไม่รู้ทำไง :-P. แต่ดูไปดูมาก็เจอว่ามี gtest-config พอจะไช้แทน pkg-config ได้ แต่ว่าถ้าใช้แต่ gtest-config ก็ดูท่าจะเขียน configure.in ยาวอีก.

แต่หาไปหามาสักพักก็พบ gtest.m4 เป็นตัวช่วยสำคัญที่ทำสั่ง GTEST_LIB_CHECK ใน configure.in ได้เลย แต่ว่าจะเอา gtest.m4 มาใส่ใน aclocal.m4 ได้อย่างไร ผมก็ลืมไปแล้ว ไม่ได้ใช้นาน หรือว่าผมไม่เคยทำเป็นเลย ไม่ค่อยแน่ใจ. แต่หาไปหามาก็พบว่าสั่ง aclocal -I $HOME/gtest-1.1.0/m4 ได้เลย ^_^ (ผมเอา gtest ไว้ใน $HOME อะนะครับ).

พอเรียก configure แล้วก็ได้ข้อความประมาณนี้ออกมา

checking for gtest-config… /home/veer/bin/gtest-config
checking for Google Test… yes

น่าจะใช้ได้แล้วมั้ง ต่อไปก็แก้ Makefile.am แล้วก็เขียน test case (ที่จะลองต่อไป)