web-dev-qa-db-ja.com

コマンドプロンプトとPowerShellがターミナルとは異なる出力結果を表示するのはなぜですか?

私は本から次のサンプルコードを持っています:

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

int main(int argc, char *argv[])
{
  printf("Hello World (pid:%d)\n", (int) getpid());
  int rc = fork();

  if (rc < 0)
  {
    //fork failed
    fprintf(stderr, "fork failed\n");
    exit(1);
  }

  else if (rc == 0)
  {
    //child (new process)
    printf("Hello I am child (pid:%d)\n", (int) getpid());
  }

  else
  {
    //parent goes down this path (main)
    printf("Hello, I am parent of %d (pid:%d)\n",
            rc, (int) getpid());
  }

  return 0;
}

Windows(PowerShellとコマンドプロンプト)では、次のように表示されます。

Hello World (pid:1283)
Hello, I am parent of 1284 (pid:1283)Hello I am child (pid:1284)

Linux(ターミナル)では、次のようになります。

Hello World (pid:1923)
Hello, I am parent of 1924 (pid:1923)
Hello I am child (pid:1924)

次の画像に示すように。

同じコードが異なるプログラムで異なって表示されるのはなぜですか? Windowsは、コードの読み取り方法に基づいて出力を誤って表示しているだけですか?それとも、コンパイラーの問題ですか? Linuxでは付属のgccを使用しています。私はWindowsでcygwingccを使用しています。

Windows上のPowerShell

powershell-windows

Linux上のターミナル

terminal-linux

Windowsでのコマンドプロンプト

cmd-windows

また、このコードを実行します:

#include <stdio.h>

int main()
{
    printf("Name\n");
    printf("Address Line 1\n");
    printf("Address Line 2");
}

Windows上のPowerShellでコードを正しく出力します。

enter image description here

2
Jinzu

Cygwinの場合、明らかに競合状態があり、行の本体を形成する文字を出力し、次に行末(CRLF)を出力し、別のプロセスが入ることができます。その間、実際にはbody1 body2 CRLF CRLF(わかりやすくするために間隔を追加)。

標準Cは、「対話型デバイス」へのstdoutを完全にバッファリング(つまり、複数行)することを禁止していますが、それよりも少なく、どのような場合でも、オペレーティングシステム(Cは正式に「ホスト環境」と呼んでいます)が複数のプロセスからの出力を処理する方法を許可します。一度「送信」されると、完全にCの範囲外になります。私が間違っていなければ、この場合はPOSIXでさえ、CygwinがPOSIXを完全に満たすことができるわけではありません。

4

WindowsでUnix改行(\n)を使用しており、\r\nである必要があります。

違いはよく ここで説明

改行には3つの異なるタイプがあり、すべて元々は主要なオペレーティングシステムに固有です:Windows/DOS、Macintosh、およびUnix。 Macの改行を使用したドキュメントはWindowsシステムでは恐ろしく見え、UnixでWindowsの改行を使用したドキュメントも正しく解釈されません。これの原因は、改行が実際にどのように作成されるかです。 Macは、デフォルトで、<CR>として表される単一のキャリッジリターン(\r)を使用します。一方、Unixは、単一の改行(<LF>)、\nを使用します。 Windowsはさらに一歩進んで両方を使用し、()の組み合わせ\r\nを作成します。

自分でテストするには、次の行を変更するだけです。

printf("Hello World (pid:%d)\n", (int) getpid());
fprintf(stderr, "fork failed\n");
printf("Hello I am child (pid:%d)\n", (int) getpid());
printf("Hello, I am parent of %d (pid:%d)\n",
            rc, (int) getpid());

これに:

printf("Hello World (pid:%d)\r\n", (int) getpid());
fprintf(stderr, "fork failed\r\n");
printf("Hello I am child (pid:%d)\r\n", (int) getpid());
printf("Hello, I am parent of %d (pid:%d)\r\n",
            rc, (int) getpid());

改行を使用したクロスプラットフォームの一貫性が必要な場合は、OS /シェルのバージョンに基づいてコードに定数を適用し、正しい改行を割り当ててから、\nがあるすべての場所に割り当てることをお勧めします。コード。

1
JakeGould