覚書ページに gtk.Button を追加。
gtk.Button だけでは書くことがスゲェ少ないのでオマケ付き。
細かい解説ではなく実用的に書いているつもり。
というか解説ならば英語だけど公式サイトのみで十分だと思うのよね。
しばらくは覚書ページに専念…するかもしれない。
アルゴリズム関係の勉強もやりたいし自作アプリの機能追加もやりたいし…
覚書ページに gtk.Button を追加。
gtk.Button だけでは書くことがスゲェ少ないのでオマケ付き。
細かい解説ではなく実用的に書いているつもり。
というか解説ならば英語だけど公式サイトのみで十分だと思うのよね。
しばらくは覚書ページに専念…するかもしれない。
アルゴリズム関係の勉強もやりたいし自作アプリの機能追加もやりたいし…
前々回 Python の True, False は整数と書いたけど
そういえば isinstance() は?
やっぱりそうなるか。
他にオブジェクトのタイプを正確に調べるには…
How to compare type of an object in Python? – Stack Overflow
こんなに色々タイプ比較方法があったんだ、めもめも。
でも速度はどうなるんだろう?
import time
t = 100000
s0 = time.time()
for i in range(t):
isinstance(i, int)
print time.time() - s0
s1 = time.time()
for i in range(t):
type(i) is int
print time.time() - s1
s2 = time.time()
for i in range(t):
"%d" % i
print time.time() - s2
結果
0.0666399002075 0.0661001205444 0.157742977142
変わらないや、一応試した文字列変換可能かどうかでは遅すぎるかやはり。
私が以前自分で書いたコレもサル丸出しだなと。
とにかく type() がいいみたいなので現行版をベースに作りかえてみる。
とはいえもはや SeeMe で使っているのは原型を留めていないのであるが…
ついでにアトリビュートには直接アクセスできないようにとか % 演算子に変更とか…
#!/usr/bin/env python
#-*- coding:utf-8 -*-
ERROR_READ = 'Configuration file READ ERROR\n[%s]\n%s=\nvalue is not %s'
ERROR_WRITE = 'Configuration file WRITE ERROR\n(%s, %s) value is not %s'
ERROR_HEADER = 'Configuration file header value is not str'
import os
class InifileBase():
"""
This class is Inheritance Base
"""
def __init__(self, filename):
"""
Attribute is the file name only
"""
self._filename = filename
def _get_value(self, section, key):
"""
This Methods is Inheritance Base
"""
return None
def read_int(self, section, key, default):
"""
@param default: int.
"""
result = self._get_value(section, key)
if result == None:
return default
try:
return int(result)
except:
raise ValueError, ERROR_READ % (section, key, "int")
def read_float(self, section, key, default):
"""
@param default: float.
"""
result = self._get_value(section, key)
if result == None:
return default
try:
return float(result)
except:
raise ValueError, ERROR_READ % (section, key, "float")
def read_bool(self, section, key, default):
"""
@param default: bool.
"""
result = self._get_value(section, key)
if result == None:
return default
if result == "1" or result == "-1":
return True
elif result == "0":
return False
else:
raise ValueError, ERROR_READ % (section, key, "bool")
def read_str(self, section, key, default):
"""
@param default: str.
"""
result = self._get_value(section, key)
if result == None:
return default
return result
class InifileReader(InifileBase):
"""
This class is read-only
ini files to load faster
"""
def __init__(self, filename):
"""
@param filename: the full path name.
"""
InifileBase.__init__(self, filename)
def _get_value(self, section, key):
"""
Read using the file stream
"""
if os.path.exists(self._filename):
section_in = False
f = open(self._filename)
try:
for linenn in f:
line = linenn.strip()
if line == "":
continue
if section_in:
if "=" in line:
pos = line.index("=")
if key == line[:pos]:
return line[pos+1:]
if len(line) > 2 and line[0] =="[" and line[-1] == "]":
return None
if len(line) > 2 and line[0] =="[" and line[-1] == "]":
if section == line[1:-1]:
section_in = True
finally:
f.close()
return None
class Inifile(InifileBase):
"""
ini file to read and write class.
"""
def __init__(self, filename):
"""
Loading degradation inifile
@param filename: the full path name.
"""
InifileBase.__init__(self, filename)
self._header = ""
self._ini = []
if os.path.exists(filename):
f = open(filename)
x = f.read()
f.close()
lines = x.split("\n")
section = ""
for line in lines:
if line == "":
continue
if len(line) > 2 and line[0] =="[" and line[-1] == "]":
section = line[1:-1]
elif section == "":
pass # Nothing
elif "=" in line:
pos = line.index("=")
self._add(section, line[:pos], line[pos+1:])
def _add(self, section, key, value):
"""
Add to contents.
"""
for dic1 in self._ini:
if section in dic1.keys():
for dic2 in dic1[section]:
if key in dic2.keys():
dic2[key] = value
return
dic1[section].append({key: value})
return
self._ini.append({section: [{key: value}]})
def _get_value(self, section, key):
"""
Get to contents.
"""
for dic1 in self._ini:
if section in dic1.keys():
for dic2 in dic1[section]:
if key in dic2.keys():
return dic2[key]
return None
def save(self):
"""
Save the contents.
"""
s = ""
if self._header:
s += self._header
for dic1 in self._ini:
for section in dic1.keys():
s += "[%s]\n" % section
for dic2 in dic1[section]:
for key in dic2.keys():
s += "%s=%s\n" % (key, dic2[key])
s += "\n"
if s != "":
f = open(self._filename, "w")
f.write(s)
f.close()
def add_header(self, header):
"""
@param headre: str.
"""
if type(header) is str:
self._header = header
else:
raise ValueError, ERROR_HEADER
def section_exists(self, section):
"""
Check existence of section.
"""
for dic1 in self._ini:
if section in dic1.keys():
return True
return False
def erase_section(self, section):
"""
Remove the specified section.
"""
for dic1 in self._ini:
if section in dic1.keys():
dic1.pop(section)
return True
return False
def erase_key(self, section, key):
"""
Erase Key
"""
for dic1 in self._ini:
if section in dic1.keys():
for dic2 in dic1[section]:
if key in dic2.keys():
dic2.pop(key)
return True
return False
def write_int(self, section, key, value):
"""
@param value: int.
"""
if type(value) is int:
self._add(section, key, str(value))
else:
raise ValueError, ERROR_WRITE % (section, key, "int")
def write_float(self, section, key, value):
"""
@param value: float.
"""
if type(value) is float:
self._add(section, key, str(value))
else:
raise ValueError, ERROR_WRITE % (section, key, "float")
def write_bool(self, section, key, value):
"""
@param value: bool.
"""
if type(value) is bool:
if value:
self._add(section, key, "1")
else:
self._add(section, key, "0")
else:
raise ValueError, ERROR_WRITE % (section, key, "bool")
def write_str(self, section, key, value):
"""
@param value: str.
"""
if type(value) is str:
self._add(section, key, value)
else:
raise ValueError, ERROR_WRITE % (section, key, "str")
継承使っているし、こうなると初心者は見ても意味解らないかも。
Y901x と SeeMe に使うのはこれでいいとして、覚書ページはどうするか…
てかあそこに書いた方法では今では動画再生できなくなったと解っているんだが。
最近の 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
ネタを何にしようか困っていたけどドコかの誰かにヒントをもらったので構造体を。
構造体は何気に便利です。
単純に「入れ物」として使うだけでもありがたい言語仕様である。
たとえば WindowsSDK には RECT 構造体が define されている。
RECT 構造体
コレを Linux で利用するには自身で定義するだけ。
LONG なんて Linux では当然定義されていないので int か long で全置換。
#include <stdio.h>
#include <string.h>
typedef struct tagRECT {
int left;
int top;
int right;
int bottom;
} RECT;
int main(int argc, char *argv[])
{
RECT rc = {10, 10, 320, 240};
printf("x=%d, y=%d, width=%d, height=%d\n", rc.left, rc.top,
rc.right - rc.left, rc.bottom - rc.top);
return 0;
}
後はこの rc という変数の要素がウインドウのサイズ情報なのだと理解しやすい。
他のデータは他の構造体でまとめる、内部で利用する情報はまとめたほうが整理しやすい。
ソレのドコが便利なのかはメモリ内に保存するデータが多くなると実感するよ。
実際にアプリを作っているといつのまにかトンデモネェ数になってしまうから。
たとえば私の作った Y901x でのアトリビュートや Cinema の public 変数中身の数を見て呆れてくれ。
実際にアプリを作ったことが無い人には解らないかもだけどコレでも少ないほうだ。
それだけならたいして便利では無いのですけど。
Windows で GUI アプリを本当に作っている人なら GetWindowRect 関数を使ったことが無い人はいない。
と思うけどどうなのだろう。
GetWindowRect 関数
そう、この関数に RECT 構造体のポインタを渡せばウインドウ外観のサイズ情報は一度で取得できる。
void hoge(HWND hWnd)
{
RECT rc;
GetWindowRect(hWnd, &rc);
/* サイズに関する何かの処理 */
つまり構造体のポインタを渡すだけで多数の情報を一度でゲットできる関数を作れば後々で楽。
C# 言語なんて仕様でソレを駆使している感じ、GC なので戻り値で済ませるように作っているけど。
おかげで型がアホみたく多い言語になってしまったのは何ともいえん、バランスって難しい。
とにかく、後々サイズ大きくなりそうなアプリを作るなら構造体の利用方法を覚えたほうがいい。
というか class の利用方法を覚えるのに必須の知識ですので。
C 言語で何か作れる人にはどうでもいい話。
今となっては C/C++, C#, Python, PHP をゴチャマゼで利用している私ですが…
十年前は C 言語を勉強していて見事ポインタで挫折した人である。
ポインタは実態へのアドレス(以下略
って、そんなのは解っているよ!だからポインタをどう使えばソフトウエアが作れるんジャ!
という理由である、勝手な思い込みだけど似たような人は多いと思う。
こんな状態である人に解りやすく説明してくれている本やサイトは存在しない。
実はたった一つのことだけを気がつけばいいだけ。
以下のコードについて細かい説明は一切しない、初心者本を読んでくれ。
#include <stdio.h>
void plusfunc(int num1, int num2, int nResult)
{
nResult = num1 + num2;
}
int main(int argc, char *argv[])
{
int n1, n2, n3;
n1 = 2;
n2 = 3;
n3 = 0;
plusfunc(n1, n2, n3);
printf("%d+%d=%d\n", n1, n2, n3);
return 0;
}
コレを実行すると
2+3=0
と出力される、つまりコレじゃ関数で値を変更できないんだよ!
理由が解らない人は本で調べよう、だからポインタを使う。
#include <stdio.h>
void plusfunc(int num1, int num2, int* nResult)
{
*nResult = num1 + num2;
}
int main(int argc, char *argv[])
{
int n1, n2, n3;
n1 = 2;
n2 = 3;
n3 = 0;
plusfunc(n1, n2, &n3);
printf("%d+%d=%d\n", n1, n2, n3);
return 0;
}
これで 2+3=5 と正常な出力になる、と初心者本はこんな感じの説明をしていたと思う。
いや、このコードって何かおかしいだろ?余程のバカでなければこう書くはずだ。
#include <stdio.h>
int plusfunc(int num1, int num2)
{
return num1 + num2;
}
int main(int argc, char *argv[])
{
int n1, n2, n3;
n1 = 2;
n2 = 3;
n3 = plusfunc(n1, n2);
printf("%d+%d=%d\n", n1, n2, n3);
return 0;
}
えっと、つまりポインタってどういう時に使えば使いこなせるの?
となってしまった、だから私はポインタが無い Delphi に一度逃げた…
という昔話はどうでもよくて。
int で説明するから理解できない、文字列で説明すればアッサリ理解できる。
#include <stdio.h>
#include <string.h>
void plusfunc(int num1, int num2, char* szResult)
{
sprintf(szResult, "%d だよ!", (num1 + num2));
}
int main(int argc, char *argv[])
{
int n1, n2;
char szRes[16];
n1 = 2;
n2 = 3;
strcpy(szRes, "0 かな?");
plusfunc(n1, n2, szRes);
printf("%d+%d=%s\n", n1, n2, szRes);
return 0;
}
C 言語の文字列は = で代入できないので関数を使うしかない。
つまり = では値を変更できないものを変更する関数を作る時にポインタを使う。
それだけ、strcpy 等の標準関数だってやはりポインタを使っているわけです。
それに気がついただけでいつのまにか C 言語は書けるようになった。
もっと細かいことについては何か作っていれば自然と理解できているはず。
手持ちの本で int で説明されている部分を文字列に置き換えて読めば結構理解が早い。
どうしてプログラミング本って全部 int なんでしょう?int だから解らないのに。