C言語でテキストカーソル位置の取得をしたいのですがどうしたらよいでしょうか?

  printf("\x1B[6n\n);

  ^[[24;9R
のようにカーソル位置を表示できることまではわかったのですが、
これをどう加工して、変数に取得できるでしょうか?
sprintf?,scanf?

よろしくお願いします。

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

A 回答 (2件)

 エスケープ・シーケンスはコンソールデバイス(画面出力/キー入力デバイス)が処理していますので、printf() つまり stdout に出力しないと動作しません。


 また、stdout に "\x1B[6n" を出力すると、コンソールデバイスは現在のカーソル位置を stdin に "\x1B[yy;xxR" の形式で返しますから、結果は当然 stdin から読まなければなりません。

 sprintf(buff, ...) で buff にエスケープ文字列を書き込んでも、コンソールデバイスには何の指令も届きませんから、printf(...), fprintf(stdout, ...), puts() など stdout に出力する関数を使用してください。
 結果の文字列を受け取る場合も同様です。gets() など stdin から入力する関数を使います。
 sscanf(buff, ...) を使うのでしたら、buff にはコンソールデバイスから返される文字列が事前にセットされいなければなりません。

#include <stdio.h>

void main(void)
{
 char buff[16];
 int cursor_x, cursor_y;

 printf("%s", "\x1B[6n");
 gets(buff);
 sscanf(buff, "\x1B[%d;%dR", &cursor_y, &cursor_x);

 printf("x = %d, y = %d\n", cursor_x, cursor_y);
}

 もっと簡単にするのなら buff を使わずに直接 stdin から読み込みます。

#include <stdio.h>

void main(void)
{
 int cursor_x, cursor_y;

 printf("%s", "\x1B[6n");
 scanf("\x1B[%d;%dR", &cursor_y, &cursor_x);

 printf("x = %d, y = %d\n", cursor_x, cursor_y);
}

 確かに No.1 のものは、説明のためとはいえ冗長過ぎましたね。
    • good
    • 0
この回答へのお礼

そっか、画面に出力しないと行けないのですね。納得しました。

コードの方もお見事ですね!
使わせていただきます。m(__)m

余計なゴミを出力しないといけないと思ったんですが、
エスケープシーケンスでうまく消せばいんですね!
やってみます!

助かりました。ありがとうございます!

お礼日時:2002/03/12 14:15

 エスケープ・シーケンスですね。

例えば次のようになると思います。

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

void main(void)
{
 char buff[16];
 int cursor_x, cursor_y;

 printf("%s", "\x1B[6n");
 gets(buff);
 cursor_y = atoi(strchr(buff, '[') + 1);
 cursor_x = atoi(strchr(buff, ';') + 1);

 printf("x = %d, y = %d\n", cursor_x, cursor_y);
}

※ 左上隅の座標は 0, 0 ではなくて 1, 1 になります。
※ サンプルを走らせると x は必ず 1 になりますが、これはコマンドとして実行したためです。(実行のために Enter キーを押すと、カーソルは左端に移動しますから)
※ Borland C でしたら、#include <conio.h> で int wherex(void) と int wherey(void) が使えるはずですので、そちらの方が簡単でしょう。(MS-DOS の場合ですが)
    • good
    • 0
この回答へのお礼

こんにちは。ご回答ありがとうございます!

実際に動かしてみましたが、いや~、お見事ですね。
しっかりと動きました。採用させてもらいます。
ありがとうございました。

さて、私の考えていたアプローチでもやってみたんですが、
どうもうまくいきませんでした。
x = 0, y = 0
となってしまいます。
どなたか原因わかる方いらっしゃらないでしょうか?
よろしくお願いします。

--
#include <stdio.h>

void main(void)
{
char buff[16];
int cursor_x, cursor_y;

sprintf(buff, "%s", "\033[6n");

sscanf(buff, "[%[^;];%[^R]R", &cursor_y, &cursor_x);

printf("x = %d, y = %d\n", cursor_x, cursor_y);
}

お礼日時:2002/03/11 12:01

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

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

このQ&Aを見た人はこんなQ&Aも見ています

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

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

Qc言語でのカーソル移動(?)について

C言語でCUIに表示された20*20の●をカーソルで移動するプログラムを作ろうと思い、
カーソルでの移動の部分でカーソルのアスキーコードを探しても無く、どうプログラムしたら良いのかがわからなくて、困っています。
やり方を教えていただけませんでしょうか?

Aベストアンサー

環境はなんです?
たいていはエスケープシーケンスとかで移動させることになりますけど。

http://archive.linux.or.jp/JF/JFdocs/Bash-Prompt-HOWTO-5.html
http://www.mm2d.net/c/c-06.shtml

QDOS画面でテキストカーソルの位置を移動する(C言語)

 DOS用のC言語プログラムを作っています。そこで
printf関数などで文字列を表示した後表示した文字列の
間に違う文字列を挿入したりしたいのですがそんなことは
可能でしょうか?

#include <stdio.h>
int main(void){
printf("13456789");
printf("2");
return 0;
}
というプログラムを作ったとして1と3の間に割り込んで2と
入れたい場合どうしたらよいでしょうか?
開発環境はwindowsXPでコンパイワはBorlandです。

Aベストアンサー

#1の方の手順が使えるのは、本当にMS-DOS互換のプログラムだけです。
Borlandのコンパイラが、実は往年のTurboC++だとか言わない限り、WinXPではエスケープシーケンスは使えません。
Borland C++ 5.5等を使われているのであれば、それはコンソールアプリであって、DOSアプリとは中身が違います。
(見た目や書き方は大差ないですが)

→Win32APIを呼ぶのが定石でしょうか。
SetConsoleCursorPosition等を調べてみてください。

Qfgetsなどのときのstdinのバッファを消すには?

こんにちは,今C(C++でない)を使用しています。
たとえば,
char str[20]
fgets(str,sizeof(str),stdin)
としたときに20字以上を打つと,stdinのバッファに20字以上の分が残ったままになります。

C++などでは
fflush(stdin)で,うまくいきますが,普通のCでは対応がされていないみたいでうまくいきません。

よろしくお願いします。

Aベストアンサー

あ,テキスト入力だからこんな大掛かりなことしなくてもいいんだ.
末尾に'\n'が出るまで掃出せばいいんですよね.

fgets(str, sizeof(str), stdin);
if ( str[strlen(str)-1] != '\n' ){
while( getchar() != '\n' );
}

でいいんだ.失礼しました.

Qsleep()関数について

"数秒おきに警報をn回鳴らすプログラム"をC言語で作成しようと
考えています。

プログラム実行環境はWindowsですが、
sleep()関数は使用できないのでしょうか??

仮に使用できない場合、この関数に代わる関数や代替方法が
あれば教えて頂けませんでしょうか? 宜しくお願いします。

Aベストアンサー

正確な動作でも構わなければ
windows.hをインクルードして
Sleep()関数を使いましょう.
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200207/02070061.txt

しかし,正確に数秒おきに動作を行いたい場合はマルチメディアタイマ等を使いましょう.
マルチメディアタイマはミリ秒間隔でコールバック関数を呼び出すことができます.
timeSetEventを用いてコールバック関数の登録を行うことができます.
timeKillEventでコールバック関数の解除を行うことができます.

多分他にも方法があると思うのですが…私はこれぐらいしか知りません^^;

参考URL:http://www.katto.comm.waseda.ac.jp/~katto/Class/GazoTokuron/code/time.html

Q標準出力の上書き

C言語にていての質問です.

一度標準出力に出力した文字の上に上書きして出力することは可能でしょうか?
例えば,カウントダウンするとき
「10」を出力したあとに,同じ部分に「半角空白+9」を出力できますか?
printf("10");printf(" 9");では「10 9」になってしまいますよね.

よろしくお願いします.

Aベストアンサー

>printf( " %d\r", i );
ではなく
printf( "%d \r", i );
でなければならない。

カウントダウンし
_10
の上に
_9
を上書きすると
_90
になってしまう( _ は空白の意味)

なので、\rの前に空白を1つ入れて
10_
の上に
9_
を上書きするようにしないと
9__
になってくれない。

「桁が減った時に、画面上に残ってる前の数字が消えるように、数字の次に空白を入れる」のを忘れないように。

例えば
1.02
1.01
1
0.99
0.98
0.97
の、1.01から1になる時のように、一気に3文字も短くなる場合は
1.02___
1.01___
1___
0.99___
0.98___
0.97___
と言う感じで、末尾に3個の空白を入れないと、1つ前の文字が残ってしまう。

QLNK2019: 未解決の外部シンボルのエラーが出る

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自キャラのデータ
Point2D g_jikipos = {40, 400};//自キャラの座標

//画像ハンドル
int g_jikiimage[11];

//色々なファイルの読み込み
int LoadFiles(){
//画像ファイル読み込み
if(LoadDivGraph("media\\player01.bmp",
11,11,1,64,64,g_jikiimage) == -1) return -1;

return 1;
}


 mymain.h
//他から呼び出させるMyMainの関数
void MyMain();
int LoadFiles();


 myhelper.h(サンプルなので打ちミスはない)
#include "DxLib.h"
#include <limits.h>
#include <math.h>

//構造体宣言
//座標またはベクトルを記録する構造体
struct Vector{
float x,y;
};
typedef Vector Point2D;
//線を記録する構造体
struct Line2D{
Point2D startpos, endpos;
float katamuki;//傾きをラジアン値で記録
Vector speed;//移動している場合は速度をセット
};
//球体を記録する構造体
struct Ball2D{
Point2D position;
float hankei;//半径
};
//四角形を記録する構造体
struct Rect2D{
Point2D lefttop;
Point2D rightbottom;
float width;
float height;
};


//ライブラリ関数
Point2D PosInView(Point2D in);
int XInView(float inx);
int YInView(float iny);
void ScrollToLeft(float jikiposx);
void ScrollToRight(float jikiposx);
void ScrollToUp(float jikiposy);
void ScrollToDown(float jikiposy);
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness);
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag);
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
int *imgarray, int allframe, float fps);
//ベクトル関数
Vector CreateVector(Vector in, float veclen);
Vector AddVector(Vector v1, Vector v2);
Vector SubVector(Vector v1, Vector v2);
Vector AddVectorInFrameTime(Vector pos, Vector speed);
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel);
Vector Normalize(Vector in);
Vector RotateVector(Vector in, float radian);
float VectorLengthSquare(Vector in);
float DotProduct(Vector v1, Vector v2);
float CrossProduct(Vector v1, Vector v2);
void SetLine2DKatamuki(Line2D *in);
void DrawLine2D(Line2D in, int Color, int Thickness);
void DrawBall2D(Ball2D in, int Color, int Fill);
//当たり判定関数
bool HitTestLineAndBall(Line2D linein, Ball2D ballin);
bool IsPointAtLineFace(Line2D linein, Point2D ptin);
bool HitTestLineAndLine(Line2D line1, Line2D line2);
bool HitTestBallAndBall(Ball2D a, Ball2D b);
bool HitTestPointAndBox(Rect2D rect, Point2D pt);
//タイマー関数
void SetSimpleTimer(int idx, int time);
int GetPassedTime(int idx);


//グローバル変数
extern float g_frametime;
extern Rect2D g_framerect;//画面領域(当たり判定)
extern Point2D g_current_field_pos;//現在の左上座標
extern Rect2D g_stagesize;//ステージサイズ

//定数宣言
const float ZEROVALUE = 1e-10f;
const float PIE = 3.1415926f;
const int SCROLL_LIMIT = 200;
----------------------------------------------------------------
 エラー内容
1>myhelper.obj : error LNK2019: 未解決の外部シンボル "void __cdecl MyMain(void)" (?MyMain@@YAXXZ) が関数 _WinMain@16 で参照されました
1>C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\my\Debug\my.exe : fatal error LNK1120: 外部参照 1 が未解決です
1>my - エラー 2、警告 0
ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ
----------------------------------------------------------------
画像を貼り付けときます
(見えにくい場合→http://www.dotup.org/uploda/www.dotup.org154142.jpg.html)
初心者なのでわかりやすくお願いします

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自...続きを読む

Aベストアンサー

ファイル構成から推測するに
mymain.cpp というファイルに
void MyMain(void) {
// ここに処理を書く
}
という関数が必要なようです。

Qコマンドラインに出力した文字を消すには

printf 関数などで出力した文字を行単位などで消したい場合,どのような操作をすればよいでしょうか.
visual studio 2005を使っているのですがprintfでエスケープシーケンスを使っても,うまく文字を消すことができなかったです.
分かる方いたら教えてください.

Aベストアンサー

エスケープシーケンスが使えないなら、恐らくWindowsのAPIを使わなくてはなりません。

GetConsoleScreenBufferInfoでコンソールのサイズなどを取得し、
ReadConsoleOutputでコンソールの内容を取得し、
不要な行を消去して、
WriteConsoleOutputで書き込めば良いはずです。
詳細はGoogleさんに聞けば、サンプルが見つかると思います。

しかし、printf等は検索結果やエラー情報など、後から消す必要の無いものを表示するためのものだと思います。
sorokukuさんがどのようなプログラムを製作中なのかはわかりませんが、無理に消す方法を探すよりも、普通のWindowsアプリにしてテキストコントロールやラベルで表示したほうが簡単だと思います。Visual C++ Expressでも.NETを使ったアプリなら作れるはずですし、Turbo C++と言う手もあります。

Q?

C Machineをダウンロードして、プログラムを作ったのですが、エラーで「インクルードファイル<conio.h>はオープンできません」と表示されました。なぜオープンできないんでしょうか?わかる方、教えてください。

Aベストアンサー

ほかのコンパイラから、conio.hをもってこればできるかと思いましたが、
LCCの試食版からもってきたらダメでした。
ほかのコンパイラのヘッダファイルだといいかもしれませんが。
ただ、ヘッダファイルにせよ、著作権は存在すると思われるので、そこは気をつけてください。
CMachineではEXEファイルを作ることはできないので、
ほかのフリーコンパイラを探してみてはどうです?

Qint型からchar型への変換

タイトル通り、int型からchar型への変換の仕方がわかりません!><
どうしたらいいのでしょうか?

Aベストアンサー

#include <stdio.h>


char buf[5];
int no;

no = 10;
sprintf(buf, "%d", no);

QEnterキーを押されたら次の処理に移るという事をしたい。

コンソールアプリケーション上で文字列を表示させた後、ユーザーがエンターキーを押したら次の文字列を表示するという仕様にしたいのですが、エンターキーだけ入力待ちにするっていうのはどのように書けばいいんでしょうか?

Aベストアンサー

#include <stdio.h>

int main(void)
{
char *str[] = {"abc", "def", "ghi", "jkl"};
int i;

for(i = 0; i < 4; i ++){
while(getchar() != '\n') ;
puts(str[i]);
}
return 0;
}


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報