• 締切済み

PostgresSQLから得たデータが画面出力されない

こんにちは。PostgresSQLからSELECTしたデータをPrintfできない現象について困っています。  環境:WindowsXP Pro  言語:VC++ 6.0  DB:PostgresSQL 8.0  プロジェクト:Win32コンソールアプリケーション 上記の環境で作業を行なっています。 問題となっているソース(一部)を記載します。 ---- wpg_select.cpp --- #include <stdio.h> #include <string.h> #include <conio.h> #include "libpq-fe.h" #pragma comment(lib, "libpq.dll") int main(void) { char szSQL[512]; char szDb_text[256]; PGconn *db = PQsetdbLogin(/*省略*/); if(PQstatus(db)==CONNECTION_BAD){ //エラー処理 return -1; } strcpy(szSQL ,"SELECT VAR_TEXT" ," FROM WK" ," WHERE VAR_SYSCD='CC'" ," AND INT_CD=100"); PGresult *rs = PQexec( db, sSQL ); if (rs == NULL){ //エラー処理 return -1; } //必ず1つのレコードしか返さないので繰り返し処理無し szDb_text = (char*)PQgetvalue(rs, 0, 0); PQclear(rs); PQfinish(db); printf("取得内容: %s\n",szDb_text); getch(); return 0; } 上記を実行すると 取得内容を出力しているprintfで、 "ハンドルされていない例外は、wpg_select.exeにあります:0xC0000005:Access Violation。" が実行時に出力され強制終了されてしまいます。 ※終了後、OUTPUT.Cファイルが表示さます printfをコメントにすると処理は正常終了します。 PQgetvalue関数はvoid*を返すと認識していたため、強引(?)にchar*に キャストし格納していますが、データベース側の文字コードがEUC_JPで あるため、実はUNICODEで帰ってきてる(?)のが原因なのでしょうか。 まだまだ勉強不足と調査不足で大変申し訳ありませんが、 対処方法についてご教示頂けますようお願い致します。 ※長文となり申し訳有りません。

みんなの回答

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.5

>当初の質問にデータベース側の文字コードはEUC_JPと記載してますが ああ、すみません。 書いてあったのを失念していました。 #4でTacosanさんが書かれているように、コマンドプロンプトに euc-jp のデータを出力しても、読める状態で表示はされませんので 読めるようにshiftjisへ変換する必要があります。 コマンドプロンプトに出力したときに、やたらと半角カナが目立つようなら まずeuc-jpで出てきているということで間違いないでしょう。 >キャストとは、EUCからShift_Jisに変換することでしたか…。 違います(^^; void* → char* とか int → long のようなデータ型の変換がキャストです。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

szDb_text は配列で定義されているから szDb_text = (char*)PQgetvalue(rs, 0, 0); という文は (C として) おかしいんだけど, それは理解してます? とはいえこのままだとコンパイルエラーになって終わるだけだからなぁ. 本当は違うのかなぁ.... データベース側の文字コードが EUC ってことは, select で得られるデータも EUC なのかな. だとすると, コマンドプロンプトでは文字化けします (SHIFT JIS しか「きちんと」表示できないので). プログラムで文字コードを変換しないとダメです. ま, とりあえず出力を一旦ファイルにリダイレクトして, それを Internet Explorer で開いてみると読めるかも. 文字コードの変換はそのあとでもいいかな.

t-nakamura
質問者

お礼

何度もアドバイスありがとうございます。 すいません。 何箇所か、掲示板に記載した内容と実際のプログラム内容が一致してませんでした。 ------------------------------------------------- (誤)#pragma comment(lib, "libpq.dll") (正)#pragma comment(lib, "libpqdll.lib") ------------------------------------------------- (誤)szDb_text = (char*)PQgetvalue(rs, 0, 0); (正)strcpy( szDb_text, PQgetvalue(rs, 0, 0)); ------------------------------------------------- (誤)SQL文を格納している箇所 ,"SELECT VAR_TEXT" ," FROM WK" ," WHERE VAR_SYSCD='CC'" ," AND INT_CD=100"); (正) "SELECT VAR_TEXT" " FROM WK" " WHERE VAR_SYSCD='CC'" " AND INT_CD=100" ------------------------------------------------- キャストとは、EUCからShift_Jisに変換することでしたか…。 文字コードを操作した経験が今まで無かったため理解するまでに まだまだ時間がかかりそうです。 >とりあえず出力を一旦ファイルにリダイレクトして, >それを Internet Explorer で開いてみると読めるかも 早急な対応策をありがとうございます。 そういう手がありますか。今すぐに確認をすることが出来ないのですが プログラム作成の時間がとれましたら動作確認してみます。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

データベースの情報がないので何ともいえないのだけど、 >格納先変数(szDb_text)を出力すると文字化け(DOS窓内)して出力されます。 printf とかで標準出力に吐いているということですよね? 文字コードはなにを使ってますか? ShiftJISでないと「文字化け」したデータにはなります。 >PQgetvalueからデータを取得する際に (char*)PQgetvalue(…)と 明示的にキャストをしているはずが キャストというのは文字コードの変換をするようなものではないですよ。 なにを期待してのキャストなのでしょう?

t-nakamura
質問者

補足

----------------------------------------------------- 参考サイト1 VC++クライアント http://s-hiasa.ddo.jp/postgre/vc.htm 参考サイト2 サンプルプログラム1 http://www.postgresql.jp/document/pg653doc/ej/programmer/x4941.htm#AEN4943 ここの 187)の箇所 ----------------------------------------------------- >データベースの情報がないので何ともいえないのだけど、 データベースの情報とは? 当初の質問にデータベース側の文字コードはEUC_JPと記載してますが それ以外ですか?ちなみに、取得する項目はVARCHAR型です。 >キャストというのは文字コードの変換をするようなものではないですよ。 >なにを期待してのキャストなのでしょう? 何も期待してません。ただ、日本語が表示されればいいだけで試行錯誤しています。 上記の参考サイト1や2では、キャストする仕組みは組み込まれていませんでした。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

PGgetvalueの解説を読むと http://osb.sra.co.jp/PostgreSQL/Manual/PostgreSQL-7.1-ja/libpq-exec.html "# PQgetvalue PGresult からひとつのタプルを取り、その中からひとつのフィー ルド(属性)の値を返します。タプルとフィールドのインデックス は 0 から始まります。 char* PQgetvalue(const PGresult *res, int tup_num, int field_num); PQgetvalue が返す値は属性値を NULL 終端の ASCII 文字列で表現したものとなります。 しかし PQbinaryTuples() が真の場合、 PQgetvalue が返す値はバックエンドサーバの内部フォー マットによるバイナリ型表現です(ただしフィールドが可変長であってもその サイズは含まれていません)。 したがって、これを正しい C の型にキャストして変換するのはプログラマの 責任です。PQgetvalueが返すポインタは、Gresult 構 造体の記憶領域の一部ですから、これを変更してはいけません。もし値を PGresult 構造体自身の寿命を超えて使うのであれば、明示的に別の記憶領域 にコピーしなければなりません。 " PQclear(rs); PQfinish(db); こういうことした後にさわっちゃいけないんじゃないの? >PGgetvalueの戻り値の領域

t-nakamura
質問者

お礼

アドバイスありがとうございます。 先にSELECTしたデータを内部変数に格納し、すべてのオブジェクト(rs,db)をクリアにしてから、格納したデータを加工したりしようと考えての記述となってしまいました。 PQgetvalueをした後にprintfで確認をとると、とりあえず強制終了はなくなりました。 が、PQgetvalueからデータを取得する際に (char*)PQgetvalue(…)と 明示的にキャストをしているはずが、格納先変数(szDb_text)を出力すると文字化け(DOS窓内)して出力されます。 文字化けを回避するためのアドバイスを頂けないでしょうか。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

PQclear とか PQfinish で領域を解放しちゃってる可能性はありますが, PostgreSQL の前に C のプログラムとして変. szDb_text は配列名なのに, なんでポインタ値を代入してるの? なんで strcpy にそんなに引数があるの?

t-nakamura
質問者

お礼

ご指摘ありがとうございます。 打ち間違えてしまいました。 実際のソースでは、そんなにstrcpyに引数はありません。

関連するQ&A

  • C言語の初心者です。これを実行してみてください。

    「a」って打ち込んだら「a」ってでましたか? #include<stdio.h> int main(void){ char a; printf("aaa\n"); scanf_s("%c", &a); printf("%c", a); return 0; }

  • C言語 ソートについて

    #include <stdbool.h> #include <stdio.h> void swap(char *a, char *b) { } bool is_at(char c) { } void justify(char line[], int n) { } int main(void) { char line[] = "a@b@@@c@@d@@@ef@@g"; size_t n = sizeof(line) - 1; justify(line, n); printf("%s\n", line); return 0; } 上の雛形を使って文字列lineに含まれる@以外の文字を文字列の前の方に詰めていくプログラミングを作るという問題を解いていたのですが下のプログラミングまでは出来たのですが最後のjustifyの部分がわかりません 良ければ解答をお願いします #include <stdbool.h> #include <stdio.h> void swap(char *a, char *b) { char temp = *a; *a = *b; *b = temp; } bool is_at(char c) { if(c == '@') { return true; } else { return false; } } void justify(char line[], int n) { for(int i=0;i<n-1;i++) { } } int main(void) { char line[] = "a@b@@@c@@d@@@ef@@g"; size_t n = sizeof(line) - 1; justify(line, n); printf("%s\n", line); return 0; }

  • 配列について

    初歩的な質問ですいませんが、質問よろしくお願いします。 ◎1----------------------------- #include<stdio.h> int main(void) { char ss[10]="AB"; printf("ss=%s\n",ss); return 0; } ------------------------------------ ◎2-------------------------------- #include<stdio.h> int main(void) { char ss[10]; ss[0]='A'; ss[1]='B'; ss[2]=0; printf("ss=%s\n",ss); return 0; } ----------------------------------- ◎3------------------------------- #include<stdio.h> #include<string.h> int main(void) { char ss[10]; strcpy(ss,"AB"); printf("ss=%s\n",ss); return 0; } ----------------------------------- ◎4------------------------------- #include<stdio.h> int main(void) { char ss[10]; ss="AB"; printf("ss=%s\n",ss); return 0; } ---------------------------------- 以上4つのプログラムで、◎2と◎3は正常に動くと理解できたのですが、何故、◎1は正常に動き、◎4は「'const char [3]' から 'char [10]' に変換できません。」といったようなエラーが出てしまうか分かりません。 教えていただければ嬉しいです。

  • 何処が間違っていますか?

    ---------------------------------------------------------------------------------------- #include<stdio.h> #include<stdlib.h> #define MAX_LINE 128 int main(void); int main(void) { char buf[MAX_LINE]; int n; printf("降水確率を入力してください。\n"); gets(buf); n = atoi(buf); printf("降水確率は %d %% です。\n",n); if (n >= 50) { printf("傘を忘れずにね。\n"); } else { printf(傘はいりません。\n"); } printf("いってらっしゃい。\n"); return(0); }

  • スレッドとメッセージキューに関して

    現在、下記のようなプログラムを作成しています。 内容は、メッセージキューを受信するスレッドを生成するというイメージです。 処理内容は下記のようになります。  (1)メッセージキューの生成  (2)スレッド生成(メッセージキュー受信側)  (3)スレッド停止  (4)メッセージキューの削除 しかし、(3)のスレッド停止を実施しても、(4)のメッセージキューの削除以降にて、msgrcvのエラーが出力されてしまいます。 スレッド停止を行ったことから、TestThreadは動作しなくなり、(4)のメッセージキューの削除にて、エラーともならずに終了することを望んでりますが、上手くいきません。 下記に作成しているプログラムを記載いたします。 正常終了をするには何がいけないのでしょうか? ご教授宜しくお願い致します。 [test.cc] ---------------------------------------------------------------- #include <time.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <ctype.h> #include <stdlib.h> #include <pthread.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/msg.h> // メソッドポインタ定義 typedef void (*testT); // スレッドID pthread_t threadId; // メッセージキュー識別子 int msqId; // 送受信するメッセージ struct msgbuf{ long int type; char data[BUFSIZ]; }; // テストスレッド void TestThread() { // メッセージ struct msgbuf message; while( 1 ) { printf("### TEST ###\n"); printf("msq start\n"); // 受信 if( msgrcv( msqId, &message, BUFSIZ, 0, 0 ) == -1) { printf("ERR! msgrcv errno[%d]\n", errno); continue; } printf("msq ed\n"); sleep(1); } return; } // メイン int main(int argc, char *argv[]) { // メッセージキュー識別子退避変数 int testMsqid; // スレッド操作リターン値 int status; // スレッドa用のパラメータ pthread_t thread_test; printf("### TEST START ###\n"); // メッセージキューの作成 if( (testMsqid = msgget((key_t)1111, 0666 | IPC_CREAT)) == -1 ) { printf("ERR! CREATE bkMsqId[%d]\n", testMsqid); return 1; } // メッセージキュー識別子を共通変数に設定 msqId = testMsqid; printf("msgget OK\n"); sleep(5); // スレッドを生成 status = pthread_create(&thread_test, NULL, (void*(*)(void*))TestThread, (void*)NULL); if(status!=0) { printf("pthread_create ng\n"); return 1; } printf("pthread_create OK\n"); sleep(5); // スレッド停止 status = pthread_cancel(thread_test); // スレッド停止結果 if ( status != 0 ) { printf("pthread_cancel ng\n"); return 1; } printf("pthread_cancel OK\n"); sleep(5); // メッセージキューの削除 if ( msgctl( msqId, IPC_RMID, NULL) == -1 ) { printf("msqId[%d] errno[%d]\n", msqId, errno); return 1; } printf("msgctl OK\n"); sleep(5); printf("### TEST E N D ###\n"); return 0; } ----------------------------------------------------------------

  •  現在、私はC言語を学んでいます。

     現在、私はC言語を学んでいます。  プログラミングの初期の初期の問題なんですが、 「Hello World」という有名なプログラムがありますよね? それについての質問です。 #include<stdio.h> main() { printf("Hello World"); return 0; } も #include<stdio.h> main(void) { printf("Hello World"); return 0; } も #include<stdio.h> int main() { printf("Hello World"); } もちゃんと表示できます。 ここで質問です。 int main(void) int main() main() main(void) はどう違うんですか? あと、 return 0; はあっても無くてもいいようなんですが どういう意味があるんでしょうか?

  • abcdとキーボードで打ったらdcbaと表示されるプログラム

    C言語に関しては初心者です。 メイン関数は変更せずに行います。 /* reverse.c: reverse a given string */ #include <stdio.h> #include <string.h> void reverse(char *); /* プロトタイプ宣言 */ int main(void) { char str[100]; scanf("%s", str); reverse(str); printf("%s\n", str); return (0); } void reverse(char *s) { char n; int i; char str; n = strlen(str) - 1; for(i=0,i++,i<=100) { s[i] = *s[n-i]; printf("%s\"s[i]); } }

  • ファイルの出力

    コマンドラインで指定したファイルの内容を一行ずつ表示するプログラムです。一行表示するごとに次の行も表示するか尋ねます。 #include<stdio.h> #include<stdlib.h> #include<ctype.h> int main(int argc, char *argv[]) {  FILE *fp;  char str[80];  char ch;  if (argc != 2){   printf("コマンドライン引数が違います\n");   exit(1);  }  if ((fp = fopen(argv[1],"r")) == NULL){   printf("ファイルが開けません");   exit(1);  }  while(!feof(fp)){   fgets(str, 79, fp);   if (!feof(fp)) printf("%s",str);   printf("追加しますか?(y/n)");   gets(str);   if ( toupper(*str) == 'N') break;   printf("\n");  }     if (fclose(fp) == EOF){   printf("ファイルを閉じれません\n");   exit(1);  }  return 0; } while文の   gets(str);  if ( toupper(*str) == 'N') break; この部分を  ch = getchar();  if ( toupper(ch) == 'N') break; でやると上手く実行できないのですが、なぜでずか?

  • ポインタと出力について

    現在C言語を勉強している者ですが、参考書をもとに自分でソースコードを書いて少し疑問に思った所がありました。以下がそのソースコードです。 #include <stdio.h> int main(void) { int dt = 0x41424344; int *ip; char *cp; ip = &dt; cp = (char *)ip; printf("%x\n", *ip); printf("%x\n", *cp); printf("%x\n", *cp++); printf("%x\n", *cp++); printf("%x\n", *cp++); return 0; } 出力結果は 41424344 44 44 43 42 となります。 私の予想していた結果は 41424344 44 43 42 41 でしたが、結果はなぜか44が二回出力されています。 2番目のprintf("%x\n", *cp); と 3番目のprintf("%x\n", *cp++);は明らかに3番目のprintfが *cp++ で番地が1つ進んでいると思うのですが結果を見る限りでは同じ数字44が出力されています。なぜこうなってしまうのでしょうか? 説明不足でしたらまた追加しますのでどうかよろしくおねがいします。  

  • データを読み込み

    データを読み込んで、表示するというものですが、 実行するとなぜか各行を読み込んだあとに 改行が入ってしまいます。 わかる方は何かアドバイスをお願いします。 ===================================== #include <stdio.h> #include <stdlib.h> #include <string.h> char filename[15], string[81]; main(){  FILE *fp = 0;  printf("input file:");  scanf("%s", filename);  if( (fp=fopen( filename, "r")) == NULL ){   printf("%s:don't open file", filename );   exit( 1 );  }  while(fgets( string,81, fp ) != NULL ){  printf("%s", string);  }  fclose( fp );  return 0; } =========================== test.dat : 80byte/rec =========================== 01234567890123456789012345678901234567890123456789012345678901234567890123456789 00000000000000000000000000000000000000000000000000000000000000000000000000000000 11111111111111111111111111111111111111111111111111111111111111111111111111111111

専門家に質問してみよう