第232章 S-JISからJISに変換する


今回はS-JISからJISへの変換プログラムを作ります。



S-JISからJISに変換するには、

#include <mbstring.h> unsigned int _mbcjmstojis( unsigned int c );

を使います。使い方は_mbcjistojmsと同じです。 (前章を参照してください)
また、S-JISで2バイト文字の1バイト目であるかどうかは

int _ismbblead( unsigned int c );

を使います。cが2バイト文字の1バイト目であれば 0以外をそうでなければ0を返します。

JIS(日本語メール)では2パイト文字(列)とASCII文字(列)の前に特別な合図がありました。 しかし、S-JISではそのようなものはありません。 そこで、この合図を付けてやる必要があります。 また、「\r\n」は「\n」に変換してやる必要があります。

では、プログラムを見てみましょう。

// conv02.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "JISを開く(&O)...", IDM_OPEN MENUITEM "JISで保存(&S)...", IDM_SAVE MENUITEM SEPARATOR MENUITEM "終了(&X)...", IDM_END END END

普通のリソース・スクリプトです。

// conv02.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include <windowsx.h> #include <mbstring.h> #include "resource.h" #define ID_EDIT 100 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); int MyOpen(HWND, char *, HWND); void MyJisToSJis(char *, char *); int MySave(HWND, char *, HWND); void MySJisToJis(char *, char *); char szClassName[] = "conv02"; //ウィンドウクラス HINSTANCE hInst;

MySave, MySJisToJis関数のプロトタイプ宣言が増えました。

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; hInst = hCurInst; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //ウィンドウ・クラスの登録 ATOM InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst;//インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); }

いつもと同じです。

//ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるJIS<->SJIS変換", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

ウィンドウタイトルが少しだけ変わりました。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; static HWND hEdit; RECT rc; static char szFileName[MAX_PATH]=""; switch (msg) { case WM_CREATE: hEdit = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_MULTILINE, 0, 0, 0, 0, hWnd, (HMENU)ID_EDIT, hInst, NULL); break; case WM_SIZE: GetClientRect(hWnd, &rc); MoveWindow(hEdit, 0, 0, rc.right - rc.left, rc.bottom - rc.top, TRUE); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_OPEN: MyOpen(hWnd, szFileName, hEdit); break; case IDM_SAVE: MySave(hWnd, szFileName, hEdit); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hEdit); DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

szFileNameはstatic変数にしておくとMyOpen関数で開いたファイル名が MySave関数でセーブするときのデフォルトファイル名となります。 (上書き保存するとき便利)

メニューからIDM_SAVEが選択されるとMySave関数を呼び出します。

int MyOpen(HWND hWnd, char *szFileName, HWND hEdit) { DWORD dwSize; OPENFILENAME ofn; HANDLE hFile; DWORD dwAccBytes = 0; char szTitle[64], *szTitle_org = "猫でもわかるJIS<->SJIS変換[%s]"; char *lpszStr, *lpszResult; char szFile[MAX_PATH]; //オープンするJIS文書 HANDLE hStr, hResult; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.lpstrFilter = "text(*.txt)\0*.txt\0All files(*.*)\0*.*\0\0"; ofn.lpstrFile = szFileName; ofn.lpstrFileTitle = szFile; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.lpstrDefExt = "txt"; ofn.lpstrTitle = "JISファイルを開く"; if(GetOpenFileName(&ofn) == 0) return -1; hFile = CreateFile(szFileName, GENERIC_READ, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); dwSize = GetFileSize(hFile, NULL); if (dwSize >= 1024 * 64) { MessageBox(hWnd, "ファイルサイズが大きすぎます", "Too Big File!", MB_OK); CloseHandle(hFile); dwSize = 0; return -1; } //最後にヌル文字を付け加えるのでファイルサイズより1バイト多く確保 hStr = GlobalAlloc(GHND, dwSize + 1); if (hStr == NULL) { MessageBox(hWnd, "メモリ確保に失敗しました", "Error", MB_OK); return -2; } lpszStr = (char *)GlobalLock(hStr); //変換後の文字列を格納するメモリは少し余分に確保しておくと安全 hResult = GlobalAlloc(GHND, dwSize + 1024); if (hResult == NULL) { MessageBox(hWnd, "メモリ確保に失敗しました", "Error", MB_OK); return -2; } lpszResult = (char *)GlobalLock(hResult); ReadFile(hFile, lpszStr, dwSize, &dwAccBytes, NULL); lpszStr[dwAccBytes] = '\0'; MyJisToSJis(lpszStr, lpszResult); Edit_SetText(hEdit, lpszResult); GlobalUnlock(hStr); GlobalUnlock(hResult); GlobalFree(hStr); GlobalFree(hResult); wsprintf(szTitle, szTitle_org, szFile); SetWindowText(hWnd, szTitle); CloseHandle(hFile); return 0; }

szTitle_orgがちょっとだけ変更になりました。

void MyJisToSJis(char *lpOrg, char *lpDest) { int i = 0, iR = 0, c; BOOL bSTART = FALSE;//JIS->SJIS変換が必要かどうか while (1) { if (lpOrg[i] == 0x1b && lpOrg[i + 1] == 0x24 && lpOrg[i + 2] == 0x42) { bSTART = TRUE; i += 3; continue; } if (lpOrg[i] == 0x1b && lpOrg[i+ 1] == 0x28 && lpOrg[i + 2] == 0x42) { bSTART = FALSE; i += 3; continue; } if (lpOrg[i] >= 0x21 && lpOrg[i] <= 0x7e && bSTART) { c = MAKEWORD(lpOrg[i + 1], lpOrg[i]); lpDest[iR] = (char)HIBYTE(_mbcjistojms(c)); lpDest[iR + 1] = (char)LOBYTE(_mbcjistojms(c)); i += 2; iR += 2; continue; } if (i == 0 && lpOrg[0] == '\n') { lpDest[iR] = '\r'; lpDest[iR + 1] = '\n'; i++; iR += 2; continue; } if (lpOrg[i] == '\n' && lpOrg[i - 1] != '\r') { lpDest[iR] = '\r'; lpDest[iR + 1] = '\n'; i++; iR += 2; continue; } if (lpOrg[i] == '\0') { lpDest[iR] = lpOrg[i]; break; } lpDest[iR] = lpOrg[i]; iR++; i++; } return; }

この関数に変更はありません。

int MySave(HWND hWnd, char *szFileName, HWND hEdit) { char *lpszStr, *lpszResult; char szTitle[64], *szTitle_org = "猫でもわかるJIS<->SJIS変換[%s]"; char szFile[MAX_PATH] = ""; OPENFILENAME ofn; HANDLE hFile, hStr, hResult; DWORD dwByte = 0; int iLength; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.lpstrFilter = "Text files(*.txt)\0*.txt\0All files(*.*)\0*.*\0\0"; ofn.lpstrFile = szFileName; ofn.lpstrFileTitle = szFile; ofn.nMaxFileTitle = MAX_PATH; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; ofn.lpstrDefExt = "txt"; if (!GetSaveFileName(&ofn)) { return -1; } iLength = Edit_GetTextLength(hEdit); if ( iLength >= 1024 * 64) { MessageBox(hWnd, "テキストが大きすぎます", "Error", MB_OK); return -2; } hStr = GlobalAlloc(GHND, iLength + 1); if (hStr == NULL) { MessageBox(hWnd, "メモリ確保に失敗しました", "Error", MB_OK); return -3; } hResult = GlobalAlloc(GHND, iLength + 1024); if (hResult == NULL) { MessageBox(hWnd, "メモリ確保に失敗しました", "Error", MB_OK); return -3; } lpszStr = (char *)GlobalLock(hStr); lpszResult = (char *)GlobalLock(hResult); Edit_GetText(hEdit, lpszStr, iLength + 1); MySJisToJis(lpszStr, lpszResult); hFile = CreateFile(szFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); WriteFile(hFile, lpszResult, strlen(lpszResult), &dwByte, NULL); CloseHandle(hFile); GlobalUnlock(hStr); GlobalUnlock(hResult); GlobalFree(hStr); GlobalFree(hResult); wsprintf(szTitle, szTitle_org, szFile); SetWindowText(hWnd, szTitle); return 0; }

エディットコントロールから文字列を取得するときうっかり

Edit_GetText(hEdit, lpszStr, sizeof(lpszStr));

などとしないでください。

void MySJisToJis(char *lpszOrg, char *lpszDest) { int i = 0, iR = 0, c; BOOL bSTART = FALSE; while (1) { if (_ismbblead(lpszOrg[i]) && bSTART == FALSE) { lpszDest[iR] = 0x1b; lpszDest[iR + 1] = 0x24; lpszDest[iR + 2] = 0x42; c = MAKEWORD(lpszOrg[i + 1], lpszOrg[i]); lpszDest[iR + 3] = (char)HIBYTE(_mbcjmstojis(c)); lpszDest[iR + 4] = (char)LOBYTE(_mbcjmstojis(c)); bSTART = TRUE; i += 2; iR += 5; if (!_ismbblead(lpszOrg[i])) { lpszDest[iR] = 0x1b; lpszDest[iR + 1] = 0x28; lpszDest[iR + 2] = 0x42; bSTART = FALSE; iR += 3; } continue; } if (_ismbblead(lpszOrg[i]) && bSTART) { c = MAKEWORD(lpszOrg[i + 1], lpszOrg[i]); lpszDest[iR] = (char)HIBYTE(_mbcjmstojis(c)); lpszDest[iR + 1] = (char)LOBYTE(_mbcjmstojis(c)); i += 2; iR += 2; if (!_ismbblead(lpszOrg[i])) { lpszDest[iR] = 0x1b; lpszDest[iR + 1] = 0x28; lpszDest[iR + 2] = 0x42; bSTART = FALSE; iR += 3; } continue; } if (lpszOrg[i] == '\r') { lpszDest[iR] = '\n'; i += 2; iR++; continue; } if (lpszOrg[i] == '\0') { lpszDest[iR] = lpszOrg[i]; break; } lpszDest[iR] = lpszOrg[i]; iR++; i++; } return; }

前章と逆のことをする関数です。

もっと効率のよい方法で書き換えてみてください。


[SDK第3部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 04/Oct/1999 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。