C言語とgnuplotを利用して下記のプログラムを書きました。

#include<iostream>
#include<cstdio>
#include<stdio.h>
using namespace std;
#define GNUPLOT_PATH "C:/gnuplot/gnuplot/binary/gnuplot.exe"




int main()
{
FILE *gp;
char s[100];
scanf("%s", s);

gp = _popen(GNUPLOT_PATH, "w");
if (gp == NULL) {
fprintf(stderr, "Oops, I can't find %s.", GNUPLOT_PATH);
exit(EXIT_FAILURE);
}

// gnuplotにコマンドを送る
fprintf(gp, "set terminal png\n");
fprintf(gp, "set output 'plot_sample.png'\n");
//fprintf(gp, "set "xl 距離"\n");
fprintf(gp, "set title '%s'", s);
fprintf(gp, "set xrange [-pi:pi]\n");
fprintf(gp, "plot sin(x), (x+1)*x*(x-1)\n");

fflush(gp); // バッファに格納されているデータを吐き出す(必須)
//getchar(); // 入力待ち
_pclose(gp);
exit(EXIT_SUCCESS);
}

ここでscanf(%s,s);のところでsに、あア亜と入力しました。

最終的にpngの画像としてあア亜と出力させようとしているのですが、文字化けして文字がうまくひょうじされていません。
なぜ、うまくいかないのかわかっていません。
pngにおける文字の取り扱いの問題なのかC言語における文字の取り扱いなのかと考えて解決策を考えているのですが、うまくいきません。
もしわかる方がいましたら教えていただけないでしょうか?

よろしくお願いいたします。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

詳細はわかりませんが


・PNGは、画素全部の色情報でできている:座標(X,Y)の色は何、というのが全画素分
最終的な画像をgnuplot側で処理して出力される。
Gnuplotとの文字コードが不一致だと、文字化けする。

・EMFは、図形の情報でできている: 座標(x,y)に○、座標(X,Y)に□、といった感じ
文字列も、テキストそのものがデータとして記録される。
EMFを表示するアプリでの文字コードと一致すれば文字化けしない

ということではないか、と。
HTMLで例えるなら、
・PNGはエンコード不一致状態で文字化けした状態をスクリーンショットで保存したもの。
・EMFはHTMLそのものを保存して、後で正しいエンコーディングでブラウザで見ている状態
とでもいいましょうか。

○ファイル保存方法
FILE *型 はファイルポインタといって、OSの機能を使って、異る装置に対する入出力を、同じ操作で行うために使われるものです。
_popenはその入出力先としてプログラムを指定します。使い終ったら_pcloseで閉じます。
fopen関数を使うと、入出力先とてファイルを指定できます。使い終ったらfcloseで閉じます。

オープンしてFILE *と結びつければ、その先がプログラムなのかファイルなのかは意識する必要はほとんど無く、例えばfprintfでその出力先へ出力してくれます。

今回の場合なら、_popen→fopenで出力先だけ変えるのが、変更箇所も少なく、元に戻しやすい方法です。
なお、出力先のファイル指定を忘れずに。今のままでは_popenをfopenに変えただけだと、gnuplotの実行ファイルを破壊します。

このあたりの入出力はC言語だけでなく、他言語でも基礎ですので、勉強することをお勧めします。
    • good
    • 0
この回答へのお礼

ありがとうございます。勉強します

お礼日時:2011/04/24 18:38

文字にも表示するための「番号」が付いてるのは判る?



で、その番号ってのは「規格」が色々有ってね。
入力と出力と処理とで規格が合致してないと正しく表示できない。

入力がAという規格の「ファイル」に記述された文字
処理がBという規格の文字を扱って
出力がCという規格・・・
なんて事になったら変換しないといけない

Aがインチ、Bが尺、Cがメートル みたいな話。どれも長さなのに。


「文字コード」で調べたら良いんじゃないかな。
使ってる表示と処理が何になってるかって話。
因みにC言語自体は「バイナリ」として扱うから規格自体は何でも関係ないんだけどそれを編集しているエディタの「文字表示」が入出力と異なってると(以下略・・・かなりややこしいからすぐ理解できないとおもう
    • good
    • 0
この回答へのお礼

ありがとうございます。
文字コードで検索して考えてみます。

お礼日時:2011/04/23 19:59

> pngにおける文字の取り扱いの問題なのかC言語における文字の取り扱いなのかと考えて解決策を考えているのですが、うまくいきません



まず、pngはbmp等と同じで、各点の色しか覚えていません。「pngにおける文字の取り扱い」は、ただの「絵」であって、「文字化け」は、その絵を作るときに発生します。

C 言語では、特になにもしなければ、ソースに書いたバイト列がそのまま出力されます。
scanfも受け取ったバイト列そのままです。
文字化けしないようにするには、出力の際に文字コードを変換するか、出力を受けとるソフトの方で変換するか、です。


今回の場合は、Cが出力する文字コードと、Gnuplotが期待する文字コードの不一致が原因でしょう。
Gnuplotの対応は、バージョンやパッチ、ビルド時の設定によって違ってきます。そのため、御自身で調べていただかないとなのですが
・スクリプトで 「set encoding XXX」 と文字コードを変更する
・Cの文字コード変換ライブラリを探すかして、Gnuplotが求めるコードで出力する
といったことが必要です。

また、直接_popenでgnuplotに送らず、一旦ファイルに書き出せば、期待通りのスクリプトがgnuplotに送られているかの確認もできるし、いちいちCのコンパイル→実行をしなくても、スクリプト変更による動作の確認ができます

この回答への補足

#include<iostream>
#include<cstdio>
#include<stdio.h>
using namespace std;
#define GNUPLOT_PATH "C:/gnuplot/gnuplot/binary/gnuplot.exe"

int main()
{
FILE *gp;
char s[100];
//scanf("%s", s);

gp = _popen(GNUPLOT_PATH, "w");
if (gp == NULL) {
fprintf(stderr, "Oops, I can't find %s.", GNUPLOT_PATH);
exit(EXIT_FAILURE);
}

// gnuplotにコマンドを送る
//fprintf(gp, "set terminal png\n");
fprintf(gp, "set terminal emf color 'Ryumin-Light-EUC-H' 16\n");
fprintf(gp, "set output 'plot_sample.emf'\n");
fprintf(gp, "set title 'ううう'\n");
//fprintf(gp, "set title '%s' font 'MS明朝", s);
fprintf(gp, "set xrange [-pi:pi]\n");
fprintf(gp, "plot sin(x), (x+1)*x*(x-1)\n");

fflush(gp); // バッファに格納されているデータを吐き出す(必須)
//getchar(); // 入力待ち
_pclose(gp);
exit(EXIT_SUCCESS);
}

プログラムを上記のように変更しました。ファイル形式をpngからemfに変換しています。すると文字化けされずに表記されました。
しかし、うまくいった理由がわかりません。できれば別の形式で保存したいのですが。うまくいった理由や他の手法があれば教えていただけないでしょうか?よろしくお願いいたします。

補足日時:2011/04/23 20:54
    • good
    • 0
この回答へのお礼

ありがとうございます。

>直接_popenでgnuplotに送らず、一旦ファイルに書き出せば、期待通りのスクリプトがgnuplotに送られているかの確認もできるし、いちいちCのコンパイル→実行をしなくても、スクリプト変更による動作の確認ができます。

この部分を自分で行おうとしているのですが、具体的なやり方がわかりません。
よろしければ、教えていただけないでしょうか?

よろしくお願いいたします。

お礼日時:2011/04/23 19:58

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qscanf( )で日本語を入力する方法を教えてください。

こんにちは、現在C言語とC++を勉強中の者です。

コンパイラーは、Borland C++を使っています。
scanf( )では、日本語を入力できないと思っていました。

ところが、「猫でもわかるプログラミング」では日本語を入力できています。
ただ、使用しているコンパイラーがVC++なのです。

日本語入力はコンパイラーによるものなのでしょうか?
調べてもわかりません。

OSは、WINDOWS-ME です。
よろしくお願いします。

Aベストアンサー

>プログラムで強制的に入力モードの変更はできないものでしょうか?

IMM系のAPIでできそうだと思ったのですが、試したところうまく動作しませんでした。DOS窓上では無理なのか、私のスキルが足りないのかはわかりませんが...。(IMM系APIについては「猫でも...」の「Windows SDK編」の278章から書いてあります。) そこで、ちょっとズルをして、キーボード入力をソフト的に送る方法を考えました。おそらくwahhahha_2002さんの環境でも動作すると思うので試してみてください。(なお、インデントに全角スペースを使用しています。コピーして使う場合はタブにでも置き換えてください)

-----------------------------------------------
#include <stdio.h>
#include <windows>

/* Alt + [半角/全角] */
void ChangeMode(void)
{
  keybd_event(VK_MENU, 0, 0, 0);
  keybd_event(VK_KANJI, 0, 0, 0);
  keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
  return;
}

int main()
{
  char buf[256];

  ChangeMode();
  printf("好きな言葉を入力してください:");
  scanf("%s", buf);
  printf("あなたは「%s」と入力しました。\n", buf);
  ChangeMode();

  return 0;
}

>プログラムで強制的に入力モードの変更はできないものでしょうか?

IMM系のAPIでできそうだと思ったのですが、試したところうまく動作しませんでした。DOS窓上では無理なのか、私のスキルが足りないのかはわかりませんが...。(IMM系APIについては「猫でも...」の「Windows SDK編」の278章から書いてあります。) そこで、ちょっとズルをして、キーボード入力をソフト的に送る方法を考えました。おそらくwahhahha_2002さんの環境でも動作すると思うので試してみてください。(なお、インデントに全角スペースを...続きを読む

Qscanf("%s", buf);でスペースを含んだ文字

コンソールプログラムで
scanf("%s", buf);
を使用してユーザに入力された文字によって処理を行いたいのですが、このままではスペースを含む文字列がスペースの手前で切られてしまいます。
C:\Program Filesなどを入力可能にさせたい場合にはどのようにするのがベターですか?

Aベストアンサー

お任せください!
そもそもscanfを使うというのはお勧めでは
ありません。scanfは文字+改行文字が入力
されないと完了しないためです。
が、それは良しとしましょう。
scanfの書式ですが、

int n = scanf("%[^\r\n]",buf);

という便利な書式があります。
perlでもおなじみの書式ですね。
上記の山文字"^"より前が読み込ませたい文字の集まりで、ハイフン指定が出来ます。
"^"より後ろが読込みを停止させたい文字の集まりです。上記の指定は復帰改行以外の文字が現れるまで読み込みます、という書式です。
下記のような指定も出来ます。

int n = scanf("%[a-zA-Z0-9\\: \t^\r\n]",buf);

なお、戻り値は読み込んだ項目数ですので、
if(n >= 1)
{
}
で判断できますね。

Qファイル出力の場所を指定

現在C++にてhtmlファイルを出力するプログラムを作っているのですが、出力場所を指定することはできるのでしょうか?(現在はそのプログラムソースが保存されている場所と同じファイル内に出力されますが、それをデスクトップに出力するなど。)
もし、方法がありましたら、教えてください。
ソースや参考HPのURLなどのせていただけたらありがたいです。
環境はVisualStudio.NET2003です。
よろしくお願いします。

Aベストアンサー

単にファイル名の前にパスを指定する。

絶対パス指定
fp=fopen("c:/temp/test.txt","w");

相対パス指定
fp=fopen("./hoge/test.txt","w");


デスクトップはOSやユーザによって場所が異なるので、少し面倒です。
XPの場合環境変数を利用してこんな感じで出来ると思います。

例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void main(void)
{
FILE *fp;
char fname[1024];
strcpy(fname,getenv("USERPROFILE"));
strcat(fname,"/デスクトップ/test.txt");
fp=fopen(fname,"w");
//処理
fclose(fp);
}

QC言語で全角文字を扱いたいのですが、

C言語で全角文字を扱いたいのですが、

全角文字列を入力して特定の箇所の文字(例えば3文字目)を抜き出して、表示するという感じのプログラムをしたいのですが、うまくいきません。

半角文字ならば、配列を使ってできるのですが・・・・・

Aベストアンサー

文字コード環境によって違います。

(1)Shift-JIS、EUC-JP
 基本的にANSI規格の8bitコード体系の上に乗ってる16bitコードなので、処理上は2バイトで1文字として扱います。
 char mojiretu[] = "テスト";
 char moji[3];
 int n = 2;
 memcpy(moji, mojiretu + (n - 1) * 2, 2);
 char moji[2] = 0;
 printf("%d番目の文字は「%s」\n", moji);
 // "2番目の文字は「ス」"と表示

(2)UTF-16の場合
 UNICODEの16bitコードです。C言語ではwchar_t等のワイド文字として扱います。
 wchar_t mojiretu[] = L"テスト";
 wchar_t moji[2];
 int n = 2;
 moji[0] = mojiretu[n - 1];
 moji[1] = L'\0';
 wprintf(L"%d番目の文字は「%s」\n", moji);
 // "2番目の文字は「ス」"と表示

(3)その他
 コードによっては1文字のサイズが固定とは限りません(例:UTF-8)
 それぞれにそれなりの処理が必要です。

文字コード環境によって違います。

(1)Shift-JIS、EUC-JP
 基本的にANSI規格の8bitコード体系の上に乗ってる16bitコードなので、処理上は2バイトで1文字として扱います。
 char mojiretu[] = "テスト";
 char moji[3];
 int n = 2;
 memcpy(moji, mojiretu + (n - 1) * 2, 2);
 char moji[2] = 0;
 printf("%d番目の文字は「%s」\n", moji);
 // "2番目の文字は「ス」"と表示

(2)UTF-16の場合
 UNICODEの16bitコードです。C言語ではwchar_t等のワイド文字として扱います。
 wchar_t mojiretu[] = L...続きを読む


人気Q&Aランキング

おすすめ情報