2009年2月27日
CでGetPrivateProfile*を使わずにINIファイルを扱う
以前、『Slashcolon /: » C#でGetPrivateProfile*を使わずにINIファイルを扱う』というエントリで超適当なコードを晒したわけですが…今回は、そのC言語版です
要するに客先指定で、C#ではなくC/C++で書くのが命題なので仕方ない。フラットホームは前回同様WindowsCEなので、GetPrivateProfileStringとかのWinAPIはありません。WindowsCEでもMFCを使うのであれば、AfxGetApp()->GetProfileString(…)とか使えるんですけど…今回はMFCもなし。
最初、CodeProject辺りで誰か作ってくれてないか検索してみたのですが…見たものは全て内部でGetPrivateProfileStringを使ってました。要するにWinAPIをラップしてC++のクラスとして公開してるものがほとんど
残念ながら、WindowsCEじゃ使えないので前回同様に超適当にでっち上げてみた。
今回のは、空白とかも無視しないしINIファイル形式をガチガチに規定してるので使用は運用でカバーできる場合のみ、さらに問題があっても前回のC#版同様自己責任ってことで。もちろん、コメント、バグ報告、改善要望etc.は歓迎します
#define BUFSIZ 512 TCHAR *GetString(TCHAR *Section, TCHAR *Key, TCHAR *Default, TCHAR *IniFile) { TCHAR buffer[BUFSIZ]; TCHAR token1[BUFSIZ], token2[BUFSIZ]; TCHAR section[BUFSIZ]; TCHAR *p; BOOL sectionFound = FALSE; FILE *fp; if ((fp = _tfopen(IniFile, _T("r"))) == NULL) { return(_tcsdup(Default)); } _sntprintf(section, sizeof(section), _T("[%s]"), Section); while (_fgetts(buffer, BUFSIZ, fp) != NULL) { if ((p = _tcschr(buffer, L'=')) != NULL) { *p = L' '; } _tcscpy(token1, _T("")); _tcscpy(token2, _T("")); _stscanf(buffer, _T("%s %s"), token1, token2); if (_tcscmp(token1, section) == 0) { sectionFound = TRUE; // 指定セクション発見 } else { if (*token1 == L'[') { sectionFound = FALSE; // 別セクション発見 } } if (sectionFound == TRUE) { if (_tcscmp(token1, Key) == 0) { // 指定セクションの指定キーを発見 fclose(fp); return(_tcsdup(token2)); } } } fclose(fp); return(_tcsdup(Default)); } int GetInt(TCHAR *Section, TCHAR *Key, int Default, TCHAR *IniFile) { TCHAR *p; TCHAR *endp; long l; p = GetString(Section, Key, _T(""), IniFile); // 文字列として取得 if (p != NULL && _tcscmp(p, _T("")) != 0) { // 指定のセクションとキーが見つかった l = _tcstol(p, &endp, 0); if (*endp == L'\0') { free(p); return((int)l); // long値をintへ } } free(p); return(Default); }
GetString関数の戻り値領域は_tcsdupで確保されるので、厳密に言えばfreeで解放が必要です。でも、たいていの場合は初期時に読み込んで終了まで保持しておくことが多いと思うので神経質になるほどでもないかと思いますが…。
もっと、効率的でスマートな方法があると思うので教えていただければうれしいです。
TrackBack URL :
