Python」タグアーカイブ

C 言語で文字列メンドクサイ

最近の Linux なら locale は ja_JP.UTF-8 でイケるようだ。

scanf – Wikipedia
scanf ってこんなに面倒だったかなぁ…
gets だと思いっきり警告だし。

wchar_t って Linux では 4 バイトなんだね。
Windows つか Visual Studio では 2 バイトなのですけど。

最近の Windows SDK のようにセキュリティ関数が存在してくれないと怖いなぁ…
文字列処理って簡単にバッファオーバーランが起こせるからね。
malloc で動的処理すればなんとかなりそうだけど std::string のほうが(略

日本語の文字数カウントとかをするには UNICODE にするのが一番なわけで。
とりあえずバッファオーバーラン等を考慮しないでうまくいったコード。

#include <stdio.h>
#include <stddef.h>
#include <locale.h>
#include <string.h>

int 
main (int argc, char *argv[])
{
    /* set locale */
    setlocale( LC_CTYPE, "ja_JP.UTF-8" );

    /* おまけ、変数バイト数チェック */
    printf("int     サイズ = %d\n", sizeof(int));
    printf("char    サイズ = %d\n", sizeof(char));
    printf("wchar_t サイズ = %d\n", sizeof(wchar_t));

    /* バッファ */
    char cin[256];
    wchar_t s[256 * 4];
    char c[4] = {0};

    /* 何か入力させる */
    printf("何か文字列を入力して Enter\n");
    scanf("%s", cin);

    /* UNICODE に変換 */
    const char *cc = cin;
    size_t t = mbsrtowcs(s, &cc, strlen(cc), NULL);
    printf("文字数は %d です\n", t);

    /* 一文字ずつ書き出ししてみる */
    int i=0;
    for (i; i<t; i++)
    {
        wctomb(c, s[i]);
        printf("%s\n", c);
    }
    return 0;
}

あーくそ!Python ならたったコレだけ、import も無しで同じことができるんだが。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

s = raw_input("何か文字列を入力して Enter\n")
u = unicode(s, "utf8")
print "文字数は %d です" % len(u)
for c in u:
    print c.encode("utf8")

しかもバッファオーバーランの心配は無いと思うし。

※追記、GLib を使えば簡単だった
gunichar | PaePoi

クライアント領域のサイズ

GetWindowRect とか自分で書いて思い出したので書いておこう。
Windows の SDK を含む GUI ツールキットと Linux での GTK+ のサイズについて。
とりあえず全部 300×300 サイズなウインドウを作ってみる

SDK

hWnd = CreateWindow(
    szWindowClass,
    szTitle,
    WS_OVERLAPPEDWINDOW, 
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    300, // Width
    300, // Height
    NULL,
    NULL,
    hInstance,
    NULL);

WindowsForm

WPF

<Window x:Class="_wpf.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        
    </Grid>
</Window>

PyGtk (Linux)

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import gtk

class Template(gtk.Window):
    def __init__(self):
        gtk.Window.__init__(self)
        self.connect("delete-event", gtk.main_quit)
        self.resize(300, 300)
        self.show_all()

if __name__ == "__main__":
    w = Template()
    gtk.main()

MFC や Qt は知らない、MFC は SDK と結果は同じになるはずだが。
とにかく結果、Windows の画像は VirtualBox ose 上である。

GTK+ はクライアント領域のサイズ、Windows は全部が全体サイズです。
いやいや、Windows は WPF になってもまだデフォルトは外枠を含んだサイズなんですね。
よく見るとメニューさえクライアント領域に食い込んで含まれてしまうのが解る。

Windows でクライアント領域のサイズを指定するには

SDK の場合
AdjustWindowRectEx 関数を使うか GetClientRect との差を自力計算する。

WindowsForm の場合

this.ClientSize = new Size(300, 300);

WPF の場合
SizeToContent を WidthAndHeight に指定し 300×300 のコンテンツを入れる。

何故クライアント領域のサイズがどうだというと。
メニューやツールバー、ステータスバーなんかも当然クライアント領域内に食い込む。
画像ビューアや動画プレイヤーを作る場合は当然実寸で表示したくなるよね。
そうするとメニューやステータスバーのサイズまで計算し加算しなくてはいけないハメに…
ちなみに私の作った Cinema はそうやっている、ステータスバーは面倒で付けなかった。

コンテンツのサイズでクライアント領域サイズを決めたほうがイイに決まっている。
本当に GTK+ や WPF のレイアウタって神ですよ。

SDK はしかたがないとして WindowsForm はどうなんだ?ですよね。
WPF は古い考え方をブチ壊したのだから最初からクライアントサイズにすればいいのに。

IronPython IDisposable and Python Context Management

What is the equivalent of the C# “using” block in IronPython? – Stack Overflow

IronPython で using てか IDisposable が利用できたんだ。
知らなかった、てゆーか with, as って何だ?
私が買った Python の本にはこんなの書いていなかった気がするんだが。

with – odz buffer

Python 2.5 以降で使えるらしい、IronPython だけというわけでは無いようで。
やっぱり知っている人は少ないのか、もう少し調べてみよう。

3.10 コンテキストマネージャ型

__ext__ 指定だけだと例外になった、__enter__ と常に対にする必要あり。
試しに何か書いてみよう、と思ったけど IronPython で思いつかなかった(ぉい!

で、PyGtk の gtk.MessageDialog は destroy() メソッドを呼ぶ必要があるので

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import gtk

class MessageBox(gtk.MessageDialog):
    def __init__(self, parent=None, flags=0, type=gtk.MESSAGE_INFO, 
                  buttons=gtk.BUTTONS_NONE, message_format=None):
        gtk.MessageDialog.__init__(self, parent, flags, type, buttons, message_format)
    def __enter__(self):
        #print 'enter' # debug
        return self
    def __exit__(self, *excinfo):
        #print 'exit %s' % repr(excinfo) # debug
        self.destroy()

def messagebox(text):
    with MessageBox(buttons=gtk.BUTTONS_OK, message_format=text) as dlg:
        dlg.run()  

messagebox("Test !")

おぉ!確かにこれで解放処理を書かずに関数が使える。
でも try, finally のほうが解りやすいと思うんですけど…
組込みなら使うけど自分で書くかは少し微妙。

Double.NaN

びっくりした事

あれ?C# って Double ならモロに 0 で除算してもコンパイルエラーにならないんだ。
clr なら同じかなと思って IronPython で為してみたけど実行エラーが出るだけだった。
てか文法が合っているなら普通の Python でもこの強引なコードで読み取りは通るんだね。

def check():
    print 0/0
input("wait: ")
check()

C# も為してみようと思ったけど仮想 Vista を立ち上げるのが面倒なので mono でやってみる。
Mandriva One GNOME は gcc がデフォでは入っていないくせに gmcs はしっかりあるんだよね。
ま、最近の GNOME なら全部入っているだろうけど。

ということで

Console.WriteLine(0/0);

だと mono でもしっかりコンパイルエラーになります、忠実に再現しているのね。

Double.NaN フィールド (System)

コレも当然動く。
こういうのって便利なのだろうか?普通に例外を吐くだけのほうが楽だと思うのだが。

プログラミングの良さげな Q&A サイトめっけ

最近 PyGtk ネタを書いていないので。
ちと海外を探していて良さげな Q&A サイトを見つけた。
プログラミング系全般を扱っているがタグで分けているので解りやすい。

Stack Overflow

Python だけで現在 15,000 もあるし PyGtk だけをタグから探すことも可能。

Hottest ‘pygtk’ Questions – Stack Overflow

全体的に Windows 環境でのことが多いのは当然だよと。
ついでにソコを見ていて見つけたんだが。

GNOME

busybox.py のコードに衝撃!こんなことができたんだ。

busybox

それと pygtk-docs.tar.gz を展開すればローカルでドキュメントが見られる。
今まで Web で全部読んでいたから軽い local で観覧できるのは嬉しいよ。
実は Fedora ならデフォルトで DevHelp にコレは入っているんだけーが…

local_manual

ところで pygoo って何?と思ったので探してみたけど

pygoo – Project Hosting on Google Code

利用したい人っているのかなぁ…
標準オブジェクトを継承して自分で拡張できなきゃ小物すら作れないと思うんだが。
上記の busybox.py を見て本当にそう思う。