2008. 2.29.
石立 喬

Visual C++ 2008 Express Edition の易しい数値計算(2)

――― 数値を数字(文字列)に変換して表示し、ファイルに保存する ―――

 理工系の技術者や学生にとって、コンピュータは計算をして、結果を数値で求める道具である。したがって、まず、数値を適切な文字列として画面上に表示する方法を述べる。
 表を作成する場合には、書式(フォーマット)を揃えることが重要になる。すなわち、一般に、1)整数値の出力は右詰めにすること、2)実数値の小数点の位置を揃えること、3)小数点以下の桁数を揃えて四捨五入すること、などが要求される。これには、.NET FrameworkのString::Formatメソッドが便利である。
 計算結果は、パソコン上で見るだけではなく、ファイルに保存し、印刷したり、表計算ソフトにデータを移してグラフ化したりできると便利である。これらの目的でファイルに出力する方法も述べる。

数値を文字列として画面に表示する一番簡単な方法
 Console::WriteLine()の括弧の中に、int型、double型などの変数をそのまま記述すると、最適の文字列に自動的に変換されて表示される。「a+b」は、数値aを文字列化したものと、数値bを文字列化したものとを連結する意味になるので、数値計算をしたい場合には、「(a+b)」としなければいけない。「a-b」も同様である。
 図1に簡単なプログラム例を示す。除算には、整数値をdoubleにキャストしてある。精度が余り必要でない場合には、floatにキャストして、出力の桁数を減らすことができる。


図1 一番簡単な数値の教示方法


 上のプログラムで得られた結果を図2に示す。double型の場合は符号のほかに有効数字15桁で、float型の場合は有効数字7桁で出力される。符号を含めて左詰めで出力され、位置揃えはできない。


図2 得られた結果


数値を文字列として画面に表示するいろいろな方法
 任意のデータ型の変数をaとすると、下記の方法で文字列化でき、表示できる。一旦、Stringクラスの変数string1に代入する方法は、コンソールアプリケーション以外の、Windowsフォームアプリケーションなどでも使用できる。
 1) データ型変数を直接そのまま使用する
 すでに最初に述べた、一番簡単な方法で、数値を文字列化したものと普通の文字列とを混在させるときに便利である。
   Console::WriteLine(a);
 または
   String^ string1=""+a;
   Console::WriteLine(string1);
 string1にaのみを代入する String^ string1=a;はエラーになる。""のような空の文字列をaの前または後に加えておく。
 2) ConvertクラスのToString()メソッドを使用する
 上記の方法よりは、文字列への変換を明示的にできる。
   Console::WriteLIne(Convert::ToString(a));
 または
   String^ string1=Convert::ToString(a);
   Console::WriteLIne(string1);
 ToString()の括弧内には、a+bなどの演算式を入れることができる。
 3) 各データ型構造体のToStringメソッドを使用する
 書式指定はできるが、文字列の占有桁数指定ができないので、右詰めができない。
   Console::WriteLine(a.ToSTring());
 または
   String^ string1=a.ToString();
   Console::WriteLIne(string1);
 ToString()の括弧内には、いろいろな引数を入れることができる。技術計算に有用なものを下記に示す.

 ToString() ------ 整数は、符号を含めてすべて、実数はdouble型は有効数字15桁、float型は7桁
 ToString("D") --- 10進数の意、整数に対しては引数なしと同じ、実数では実行時エラー
 ToString("Dq") -- q桁で表示し、頭に0が付く(一種の右詰めではあるが、頭に0が付く)
 ToString("E") --- 指数表示の意、仮数部は小数点以下6桁(デフォルト)
 ToString("Eq") --- 仮数部は小数点以下q桁
 ToString("F") ---- 固定小数点の意、小数点以下2桁(デフォルト)
 ToString("Fq") --- 小数点以下q桁
 ToString("#,##0") --- 整数の3桁区切り

String::Formatメソッドによる数値の書式付き文字列化
 .NET FrameworkのString::Formatメソッドは、C言語系のprintfと同等な機能を持っている。下記は最も簡単な用法を示し、{ }内は変数の並び順である。

  string1=String::Format("A={0}, B={1}, A+B={2}",a,b,a+b);

 実際には、{ }の中に符号を含む占有桁数(フィールド幅)、整数、実数、指数表示などの種別を指定する記号(D、E、Fなど)、表示桁数または小数点以下の桁数または有効桁数を記すことができる。

 { }の中を{n,p:Aq}で表すとすると、以下の指定ができる。" " の内部のミスは、ビルド時にエラーとならず、実行時にエラーとなるので、注意を要する。

 n ------- 変数の並び順(インデックス番号)、省略できない
 p ------- 占有桁数(コンマ、ピリオド、マイナス、空白を含む)、省略された場合、または桁数不足の場合は、符号を含めてすべてを左詰めで表示
 A ------- 表示形式、省略された場合は、自動的に最適の形式が選ばれる
      D ---- 10進表示、整数に限る、実数はエラーになる
      E ---- 指数表示
      F ---- 固定小数点表示
 q ------- 桁数、表示形式(A)との併用に限る、省略された場合はデフォルト値をとる
      表示形式D ---- 頭に0を付けた、マイナス記号を除く桁数(デフォルトは0が付かない)
      表示形式E ---- 仮数部の小数点以下の桁数(デフォルトは6)
      表示形式F ---- 小数点以下の桁数(デフォルトは2)

 この他、整数に対する3桁区切りの
 {n,p:#,##0} ---- 数値が0の場合には一桁だけ0を表示する
 {n,p:#,###} ---- 数値が0の場合にはすべて空白にする
などもある。

 結局、数値計算の出力に最も実用的なものは、
  整数、実数にかかわらず、占有桁数p桁で右詰め表示し、小数点以下をp桁に揃える{n,p:Fq}
    [例] {n,9:F2} -------- C言語形式の %9.2f に相当
  整数を占有桁数p桁で右詰め表示する{n,p}
    [例] {n,5} ----------- C言語形式の %5d に相当
である。

 以上の説明のように、数値計算結果の作表には String::Formatメソッドが最適であるので、実例を下記に示す。Console::Read(); は、「続行するには…」の表示を抑えるために使用している。その代わり、終了させるには「Enter」などのキー入力を2回行う必要がある。

#include "stdafx.h"
using namespace System;

int main()
{

   Console::Title="数表";
   String^ string1;
   string1="      二乗   三乗   四乗   平方根 ";
   Console::WriteLine(string1);
   string1="---- -------- -------- -------- ----------";
   Console::WriteLine(string1);
   for(int a=1;a<11;a++){
      string1=String::Format(" {0,2}    {1,5}    {2,5}    {3,6}    {4,7:F4}",a,a*a,a*a*a,a*a*a*a,Math::Sqrt(a));
      Console::WriteLine(string1);
   }

   Console::Read();

   return 0;

}

 得られた結果を図3に示す。


図3 得られた結果


計算結果をファイルとして保存する方法
 単純なコンソールアプリケーションでは、計算結果が「コマンドプロンプト」ウインドウに表示されるだけで、保存できない。したがって、ここではコンソールに書き出す代わりに、ファイルに書き出す方法を紹介する。
 下記はファイルに書き出すプログラムで、StreamWriterクラスの名前空間として、System::IOを指定しておく。出力したいファイルの名称は、gcnew StreamWriter(<パス名、ファイル名>)、で設定する。すでに同名のファイルが存在する場合には上書きし、存在しなければ新たに作成する。
 StreamWriterクラスのオブジェクトをswriter1としておき、従来のConsoloe::WriteLine()の代わりに、swriter1->WriteLine()を使ってファイルに書き出す。最後に swriter1->Close(); でストリームを吐き出させることを忘れないようにする。

#include "stdafx.h"

using namespace System;
using namespace System::IO;

int main()
{

   String^ string1;
   StreamWriter^ swriter1=gcnew StreamWriter("A:sample.txt");
   string1="      二乗   三乗   四乗   平方根 ";
   swriter1->WriteLine(string1);
   string1="---- -------- -------- -------- ----------";
   swriter1->WriteLine(string1);
   for(int a=1;a<11;a++){
      string1=String::Format(" {0,2}    {1,5}    {2,5}    {3,6}    {4,7:F4}",a,a*a,a*a*a,a*a*a*a,Math::Sqrt(a));
      swriter1->WriteLine(string1);
   }

   swriter1->Close();  //これを忘れてはいけない

   Console::Read();

   return 0;

}

 できたファイルは任意のエディタで開くことができるが、文字コードを「Unicode(UTF-8)」に設定できないと、日本語の文字化けが生じる。印刷したい場合には、エディタの機能を利用する。
 上記のプログラムで得られたファイルを、試みに「メモ帳」で開いて確認したのが図4である。「メモ帳」の場合には、自動的に文字コードが「UTF-8」と認識されたが、「ワードパッド」では文字化けが生じた。


図4 出力されたファイルを「メモ帳」で確認したところ


計算結果を表計算ソフトに渡す方法
 計算結果を表計算ソフトに渡して、さらなる計算をしたり、グラフ化したりすることができる。それなら、最初から表計算ソフトの標準関数を使って計算すれば良いではないかとの意見もあろうが、「Visual C++ 2008」との連携の例として紹介する。
 表計算ソフト(ここではExcel 2003を使用)を開いて、前述のプログラムで作成した sample.txt を読み込もうとすると、「テキストファイルウイザード」が開き、以下のような手順が必要になる。
 「テキストファイルウイザード 1/3」で、「スペースによって右または左に揃えられた固定長フィールドのデータ」にチェックが付いていること、「文字コード」欄が「65001: Unicode(UTF-8)」になっていることを確認し、「次へ」をクリックする。
 「テキストファイルウイザード 2/3」の「データのプレビュー」欄で、必要があれば複数個の「↑」をマウスで左右にドラッグして整理し、「次へ」をクリックする。
 「テキストファイルウイザード 3/3」の「列のデータ形式」欄で、「G/標準」にチェックが付いていることを確認して「完了」をクリックする。
 この手順で読み込まれた状態を図5に示す。「--------」のあるセルを削除し、文字の中央揃えなどを行うと見やすくなる。


図5 「エクセル」に読み込んだ計算結果


「Visual C++ の勉強部屋」(目次)へ