putchar()関数について質問します。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
shika
記事: 6
登録日時: 5年前

putchar()関数について質問します。

#1

投稿記事 by shika » 5年前

OS:Windows 10 64bit版
コンパイラ:BCC32
コマンドラインコンパイル
putchar()が上手く機能しません。字化けしてしまいます。

コード:

#include <stdio.h>

void main0(void)
{
	char s[80] = "これは、ファイルシステムのテストです。\n";
	char *sp = s;

	while (putchar(*sp++))
		;
}

void main1(void)
{
	int c;

	while ((c = getchar()) != '\n')
		putchar(c);
}

int main(void)
{
	main0();

	return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: putchar()関数について質問します。

#2

投稿記事 by みけCAT » 5年前

Windows 7 Home Premium Service Pack 1 (64ビット)
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
でテストしましたが、字化けは確認できず、正常に「これは、ファイルシステムのテストです。」と出力されました。
本当にputchar()が上手く機能しないのですか?
ソースコードを実行環境と合わない文字コードで保存し、
そのバイト列がそのまま出力されているため、字化けして見えるだけではないですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

shika
記事: 6
登録日時: 5年前

Re: putchar()関数について質問します。

#3

投稿記事 by shika » 5年前

もしそうなら、main1()関数も、字化けするはずです。main1()の方は正常に作動します。他のプログラムなら
bcc32 や、cl の場合は正常でも、gcc の場合は正常でも、C++ の時、g++の場合のみ、字化けしたり、します。
何か外部からの干渉もあるのでしょうか?ウイルスが潜んでいるのでしょうか?

かずま

Re: putchar()関数について質問します。

#4

投稿記事 by かずま » 5年前

Windows 10 Home, Visual C++ 2017 でも文字化けしますね。

main の先頭に次のコードを追加してみてください。
文字化けしなくなります。

コード:

int main(void)
{
	char buf[1024];
	setvbuf(stdout, buf, _IOLBF, sizeof buf);
	main0();
	fflush(stdout);
	getchar();
	return 0;
}
コマンドプロンプトから実行する場合は、
fflush(stdout); getchar(); はなくてもよいでしょう。

また、_IOLBF(行バッファリング) を _IONBF(バッファリングなし) に
変えると、文字化けします。

Linux ではデフォルトで、
標準出力がファイルの場合は _IOFBF(フルバッファリング)で
標準出力が端末の場合は _IOLBF(行バッファリング)となりますが、

Windows では、
標準出力が端末の場合は _IONBF(バッファリングなし)となるようです。

さらに、Windows 10 のコマンドプロンプトは、単一の出力文字列の
最後の文字が、2バイト文字の先頭バイトで終わっていると
エラーだと解釈して、「・」に変えてしまうようです。

以上は私の妄想であって、そうだという記述は見つけることができませんでした。

putchar に限らず他の出力関数でも文字化けします。

コード:

#include <stdio.h>

int main(void)
{
	char buf[1024];
	setvbuf(stdout, buf, _IOLBF, sizeof buf);
	printf("%s", "\x82\xa0\x82");
	printf("%s\n", "\xa2\x82\xa4");
}
_IONBF にするか、または setvbuf なしにしてみてください。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: putchar()関数について質問します。

#5

投稿記事 by みけCAT » 5年前

shika さんが書きました:
5年前
もしそうなら、main1()関数も、字化けするはずです。main1()の方は正常に作動します。
私の仮説が正しい場合、「main1()関数も、字化けするはず」ではありません。

main1()関数ではプログラムに埋め込んだ文字(列)データは出力せず、入力に基づいたデータを出力します。
そのため、通常はある環境で入力に用いる文字コードと出力に用いる文字コードは同じだと考えられるので、
ソースコードの文字コードによる問題は発生しないと考えられます。
('\n'を表すコードが一般的な10ではない特殊な文字コードなら、問題が発生するかもしれませんが…)

一方、main0()関数では、プログラムに埋め込んだ文字(列)データを出力しています。
したがって、ソースコードの文字コードの影響を受ける可能性があります。
shika さんが書きました:
5年前
他のプログラムなら
bcc32 や、cl の場合は正常でも、gcc の場合は正常でも、C++ の時、g++の場合のみ、字化けしたり、します。
何か外部からの干渉もあるのでしょうか?ウイルスが潜んでいるのでしょうか?
ここはわかりません。
ただし、コンパイラによってはソースコードや出力バイナリに用いる文字コードを設定する機能があるので、
その設定の影響も受ける可能性が考えられます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Bull
記事: 149
登録日時: 9年前

Re: putchar()関数について質問します。

#6

投稿記事 by Bull » 5年前

修理中だった PC (Windows 10 Home 64bit Version 1809) が返ってきたので、今更ですが実験してみました。

以下のコンパイラーで #1 のプログラムをコンパイル実行しました。

GCC
gcc (i686-posix-dwarf-rev0, Built by MinGW-W64 project) 8.1.0

BCC32
Embarcadero C++ 7.30 for Win32 Copyright (c) 2012-2017 Embarcadero Technologies, Inc.
Embarcadero Technologies Inc. bcc32c version 3.3.1 (36350.30c6854.779bede) (based on LLVM 3.3.1)

VC++ (Visual Studio 2017)
Microsoft(R) C/C++ Optimizing Compiler Version 19.16.27030.1 for x64

VC++ (Visual Studio 2019)
Microsoft(R) C/C++ Optimizing Compiler Version 19.20.27508.1 for x64

いずれのコンパイラーでも文字化けせずに表示できました。

Windows10 の現バージョンでコンソールに不具合があるようなのですがつい最近 1809 にアップデートしたためか、レガシーコンソールにはしていなくとも、当方の環境では正常に表示できました。
参考
Windows10 OctoberUpdate(1809) でのコンソールのバグ
もしコンソールの不具合が原因なら、レガシーコンソールを使用することで解消するかもしれません。

なお、C言語標準ライブラリの影響を排除するために以下のようなプログラムでも検証を行いましたが、文字化けせずに正常に表示できました。

コード:

#include <windows.h>

int main(void)
{
	char buff[] = { '\x82', '\xa0', '\x82', '\xa2', '\x82', '\xa4', '\r', '\n' };

	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	DWORD nCharsToWrite = 1;
	DWORD nCharsWritten;
	for (auto c : buff) {
		WriteConsoleA(hConsole, &c, nCharsToWrite, &nCharsWritten, NULL);
		Sleep(1000);
	}
}

sahmaro

Re: putchar()関数について質問します。

#7

投稿記事 by sahmaro » 5年前

的外れかもしれませんが、
> while (putchar(*sp++))
> ;
while (putchar(*sp))
sp++;
とするか
while (fputc(*sp++, stdout))
;
としても文字化けするか確認してみましょう。
規格上 putchar はマクロが許容されているため、putchar(*sp++) とすべきではありません。

返信

“C言語何でも質問掲示板” へ戻る