2013-12-15 9 views
5

Cで複数の行を消去し、他の行を削​​除することは可能ですか?複数の行をクリアする

コード:

Displaysenrsordata 
    loop 
    printf("This info stays"); <-stay on screen 
    printf("This info stays"); <-stay on screen 
    printf("This info Refreshes"); <-update redraw 
    printf("This info Refreshes"); <-update redraw 
    printf("This info Refreshes"); <-update redraw 

基本的に私は、同じ場所に滞在し、画面全体をクリアすることなく、更新データを再描画するためにいくつかのテキストを持っていると思います。

+2

これはISO Cを超えているため、環境(Unix端末/ Windowsコンソールapp/...)を指定する必要があります。 – ninjalj

答えて

0

あなたはBrendanに応じて、画面に直接書き込むことができます。

PART古いVGAモードの場合1

は、(レガシー)に書き込むための固定アドレス 表示メモリ領域があります。テキストモードの場合、この領域は0x000B8000から始まります。 グラフィックモードの場合、0x000A0000から開始します。高解像度のビデオモードについて

(例えばVESA/VBE インターフェイスで設定されたもの) 面積が64 KiBの、最も高解像度のビデオモードに限定されているレガシー表示メモリのサイズが必要なので、これは動作しません。 より多くのスペース(たとえば、1024 * 768 * 32-bpp = 2.25 MiB)。 を回避するには、VBEでサポートされている2つの異なる方法があるとします。

最初の方法は「 」のビデオカードのディスプレイメモリの一部分のみがレガシーエリアにマップされ、(マップされている部分を変更できる)「バンク切り替え」と呼ばれます。これはかなり厄介なことがあります。例えば、 ピクセルを描画する必要があるピクセルを1つ描画し、そのピクセルが入っているバンクを計算し、そのバンクに切り替えて、バンク内のどのオフセットを計算しますか。 これを悪化させるためには、いくつかのビデオモード(例えば、ピクセルあたり3バイトの24-bpp ビデオモード)では、ピクセルのデータの最初の部分のみが1つのバンクにあり、同じ ピクセルのデータの第2部分は別の銀行。これの主な利点は、 レガシーディスプレイメモリ領域 が0x00100000以下であるため、リアルモードアドレッシングで動作することです。

ビデオカードの表示メモリ領域全体にアクセスするには、乱雑なバンク切り替えがなく、「リニアフレームバッファ」(または単に「LFB」)と呼ばれる があります。このエリアがあるVESA/VBE インターフェイスに問い合わせる必要があります(通常、「PCIホール」 のどこか0xC00000000xFFF00000の間にあります)。つまり、 はリアルモードでアクセスできず、プロテクトモードまたはロングモード、または 「非リアルモード」を使用する必要があります。

LFBモードを使用しているときにピクセルのアドレスを確認するには、 のように「pixel_address = display_memory_address + y * bytes_per_line + x * bytes_per_pixel」と入力します。 "bytes_per_line"はVESA/VBEインターフェイスからの となります(水平線間には のパディングがある可能性があるため、 "horizontal_resolution * bytes_per_line"と同じではない場合があります)。

VBE/VESAモードを "銀行は切り替え" の場合、それはより多くのようなものになり:いくつかの古いVGAモード(例えば256色 "モード0x13に")については

pixel_offset = y * bytes_per_line + x * bytes_per_pixel; 
bank_number = pixel_offset/bank_size; 
pixel_starting_address_within_bank = pixel_offset % bank_size; 

それは、LFBに似て非常に です行間に余白がないことを除いて、 は "pixel_address = display_memory_address + (y * horizontal_resolution + x) * bytes_per_pixel"とすることができます。テキストモードでは、 は基本的に同じものですが、2バイトで各文字を決定し、 の属性を指定します。 "char_address = display_memory_address + (y * horizontal_resolution + x) * 2"他の古いVGAモードの (モノクロ/ 2色、4色、16色モード)では、ビデオカードの メモリは完全に異なった配置になっています。それは、各プレーンが1ビットのピクセルを含む「プレーン」 に分割され、 には、16色モードで1ピクセルを更新し、別々の プレーンに書き込む必要があります。パフォーマンス上の理由から、VGAハードウェアは異なる書込みモードと異なる読取りモードをサポートしており、複雑になる可能性があります(ここでも適切に説明するには複雑な )。 (80×86で、 "PC互換")I/Oポートの場合

PART 2

、3つの一般 カテゴリがあります。第1は、 固定I/Oポートを使用する「デファクトスタンダード」レガシーデバイスです。これには、PICチップ、ISA DMA コントローラ、PS/2コントローラ、PITチップ、シリアル/パラレルポートなどが含まれます。 これらの各デバイスのプログラミング方法を説明するほとんどのものは、どのI/Oポートデバイス使用。

次のカテゴリには、I/Oポートは デバイスの使用はカード自体上のジャンパによって決定されたレガシー/ ISAデバイスであり、そして、彼らはソフトウェアから使用しているI/Oポートを決定するための健全な方法が ありません。 これを回避するには、エンドユーザは各デバイスが使用するI/OポートをOSに伝える必要があります。ありがたいことに、この皮肉なものはすべて廃止されました (ただし、必ずしも誰もそれを使用しているわけではありません)。

第三のカテゴリーは、それが(ほとんどの場合、 デバイスが使用するI/Oポートを変更)を使用してI/Oポートデバイスを尋ねる いくつかの方法があります場合は、「&プレイプラグ」です。たとえば、 には、それぞれのPCIデバイスに関する多くの情報を示す「PCI構成スペース」があります。ここにはPCIがあります。 このカテゴリの場合、 は、実行時に を実行せずにどのデバイスがどのI/Oポートを使用するかを判断する方法がなく、一部のBIOS設定を変更すると、これらのデバイスがI/Oを変更する可能性があります。ポート。

また、Intel CPUはCPUのみであることに注意してください。 「PC 互換」のコンピュータとは根本的に異なるものでは、これらのCPUを で使用することはできません。インテルのCPUマニュアルでは、 チップセットを含め、CPU自体の外部にあるハードウェアについては、 に何も伝えません。

パート3

は、おそらくより多くの情報(それはOSの開発者/愛好家のための を意図しています)のために行くには最高の場所はhttp://osdev.org/(自分のwikiと そのフォーラム)です。

ここでは例のカラードットを描画するASMで、drawn from here

これは、指定されたグラフィックス 座標で画面上の色のドットになります。

INPUT:

AH = 0Ch 
AL = Color of the dot 
CX = Screen column (x coordinate) 
DX = Screen row (y coordinate) 

OUTPUT:画面上のピクセルを除く

何もありません。

注:この関数は、新しい色 値との排他的論理和(XOR)を実行し、ALのビット7のピクセルの現在のコンテキストが設定されます。

このプログラムは、ピクセルをプロットする方法を示します。画面の中央に4つの赤い ピクセルをプロットする必要があります。

.model tiny 
.code 
org 100h 
start: 

mov ax,13  ; mode = 13h 
int 10h ; call bios service 

mov ah,0Ch ; function 0Ch 
mov al,4 ; color 4 - red 
mov cx,160 ; x position = 160 
mov dx,100 ; y position = 100 
int 10h ; call BIOS service 

inc dx  ; plot pixel downwards 
int 10h ; call BIOS service 
inc cx  ; plot pixel to right 
int 10h ; call BIOS service 
dec dx  ; plot pixel up 
int 10h ; call BIOS service 

xor ax,ax  ; function 00h - get a key 
int 16h ; call BIOS service 

mov ax,3 ; mode = 3 
int 10h ; call BIOS service 

mov ax,4C00h ; exit to DOS 
int 21h 

end start 

いくつかの最適化この方法はあまり速くないと我々はそれが たくさん速く作ることができます。どうやって?ビデオメモリに直接書き込みます。これはかなり簡単に行われます 。

VGAセグメントは0A000hです。各ピクセルがどこに行くのかを調べるには、 この単純な数式を使ってオフセットを取得します。

Offset = X + (Y * 320) 

私たちはすべて、この場所に数を置くことで、画面上のピクセル が今そこにあります。色は何色かです。 命令を使用して、ピクセルを画面に配置することができます。最初に はstosbを使用してALに値をES:DIに入れたり、新しい 形式のMOV命令を使用することができます。

mov es:[di], color 

私たちはどちらを使用しますか?ピクセルを画面に書き込もうとするときには、可能な限り速く行う必要があります。

Instruction  Pentium 486 386 286 86 

STOSB     3  5  4  3 11 
MOV AL to SEG:OFF  1  1  4  3 10 

あなたがMOVメソッドを使用している場合は、(STOSB はありません)DIをインクリメントする必要があるかもしれません。

連続している必要があるスプライトを使用するプログラムがある場合は、消去してから再描画するとちらつきに問題が発生します。これを避けるには、 に「ダブルバッファ」を使用することができます。これは のメモリの別の部分であり、書き込みしてすべての情報を 画面にコピーします。

+0

ソースにリンクするだけでなく、別のソースからコピーした単語を適切に引用符で囲む必要があります。私はその答えと、コピーされたテキストの2番目のセクションでそうしました。あなた自身が将来これを行うようにしてください。 –

-4

いいえ、コンソールウィンドウの一部だけを消去することはできません。

+0

標準のC++でフルスクリーンを消去することさえできません。 –

+0

@BenjaminBannier標準には含まれていませんが、リフレッシュレートが高すぎない場合は正常に動作するシステム(「cls」)またはシステム(「clear」)を実行できます。 –

2

Linuxで作業している場合は、ncursesを使用してください。

例:

#include <stdio.h> 
#include <ncurses.h> 
    int main (void) 
    { 
    int a = 0; 
    initscr(); 
    printw("This info stays \n"); 
    printw("This info stays\n"); 
    curs_set (0); 
    while (a < 100) { 
      mvprintw (3, 4, "%d", a++); 
      mvprintw (3, 8, "%d", a++); 
      mvprintw (3, 12, "%d", a++); 
      refresh(); 
      sleep (1); 
    } 
    endwin(); 
    return 0; 
} 
2

あなたは、現在の行が\bを印刷することにより\r、または現在の行の最後の文字をプリントアウトすることで上書きできます。

+0

どうしたの? – alk

+0

+1は '\ r'を使って簡単な解を求めます。 – sujin

関連する問題