C言語 プログラミング

Hello,worldの次のC言語のプログラム【Python、Go言語との比較も実施】

同じプログラムを複数のプログラミング言語で記述してみました。

やってみると、その違いがよくわかります。

タイピング練習の簡単なプログラムを、PythonとGo言語で書いてみた記事をアップしました。

やってみることで、言語間の違いが明らかになってきたので、気が向いたらシリーズ化するかもしれないけれど、今これは外せないというプログラミング言語があったので今回追加で調整した話になります。

hollo,world!の生みの親、C言語です。

Go言語は、JavaやC++に近さを感じたし、PythonはRupyに近いものがあるとは思ったものの、C言語はそれらとはまた違うし、今も使われ続けていますが、ひと世代前の言語です。

いまなら開発環境は手元に作ってあるので、数十年前に一度は似たようなプログラムを作ったことがあるけれど、今回再トライしてみました。

C言語でタッチタイピング練習プログラムを作成

タッチタイプC言語

C言語とPythonとGo言語を比較

やってみた結果で、3つの言語を比較してみます。

同じ内容のプログラムを書いたはずなのに、コーディングの量は、プログラミング言語が違うだけで明らかな違いがでました。

python(48行) < Go言語(85行) < C言語(100行)

大きな理由は、標準で用意されているライブラリと言語そのものがもっている標準機能の差でした。

pythonとGo言語やC言語との大きな差は、ライブラリの差(ファイル読み込み部分)
自作するかしないかでコーディング量に差がでました。

Go言語とC言語との差は主に、C言語が直接は持たない文字列型にたいして、文字列操作とメモリをアロケーション部分にコーディングがプラスで必要だった点です

 

つくるのにかかった時間は、正直習熟度の問題があるのでなんとも言えませんが、同じ習熟度であればこのコーディング量の差は、それ以上に生産性に響いてくる感触でした。

もちろん、プログラミング言語はこれだけでは語れなくて、性能やセキュリティなどの要因も評価軸にははいってきますし、C言語にしてみれば、C++にしてクラスライブラリを使えば、大きな差がでた開発部分はつくらなくてもよくなります。

それにしても、同じものを3つのプログラミング言語で書いてみると、違いが明らかに実感できました。

C言語の特徴

さて今回作ってみた、C言語の他言語と比較した特徴的な部分を示します。

  • ポインタの取り回しが独特(他言語にはない)
  • 範囲操作はなく、1つずつ操作
  • 配列・リストは自分で制御のため、メモリの動的確保は面倒
  • 実行ファイルの動作はやはり軽い(今回はWindows10)

 

ポインタの取り回しが独特(他言語にはない)

C言語といえば、やはりポインタ操作です。
文字列の比較をインデックスでやろうとしましたが、ポインタの方が楽なので結局ポインタで書いています。

比較が if (*p1++ == *p2++) のような感じになります。
他言語のイメージでは、if (p1[i] == p2[i]) { i=i+1; になります。

ポインタを知らない人からみると、???になるかも知れないです。

 

範囲操作はなく、1つずつ操作

GoもPythonも、ある範囲を指定して、その範囲内の処理をさせることができます。

a in リストや文字列、で文字列の中やリストの中を操作するというイメージ。

それが、C言語では、最後を自分で指定するか、最後が何かを知っていて最後がくるまでループして処理するという形をとります。

文字列なら、最後がNULL文字'\0'とか、ファイルならEOFまでとかいうのが基本になります。

近年のプログラミング言語には、この範囲操作がはいってきたことが、プログラミング言語の進歩の一つになっています。

 

配列・リストは自分で制御のため、メモリの動的確保は面倒

上記の話にも関係しますが、配列(全体)、文字列(全体)というとらえ方は言語としてはもっていないため、範囲などは自分で指定してやる必要があります。

例えば、list[100]とかです。

これが、中身がないときは、サイズをゼロにしておいて徐々に増やしていくというのを実現しようとすると、標準にはないため作る必要がでてきます。

今回はC++は使わず、C言語の範囲で実装したため、一部のサイズは実用レベルを想定して固定値にしました。

C言語を難しくしている一因かもしれませんね。

 

実行ファイルの動作はやはり軽い(今回はWindows10)

近年の言語から比較すると、開発効率は落ちそうですが、実際にできたプログラムは、タイピングプログラムという動作速度はそう関係ないものでも起動などに軽さを感じました。
メリットもまだまだ健在です。

 

C言語による、タイピング練習用プログラム

参考までに、実際のソースコードをのせておきます。

タイピング練習プログラムの概要

  1. ファイルから複数の文字列を読込み
  2. 一行をランダムに表示
  3. ユーザから一行入力
  4. 表示・入力文字列の一致率と入力時間を表示
  5. 入力がなしで終了、あれば表示から繰返し

 

実際の動作結果

	 タイピング練習プログラム(C言語版) ***

	表示された文字を入力してください.
	   qwert yuiop
	 > qwert
	正解率:45 パーセント  時間:   3.69 秒
	
	表示された文字を入力してください.
	   zxcvbnm,
	 > zxcvbnm,
	正解率:100 パーセント  時間:   4.07 秒
	
	表示された文字を入力してください.
	   abcdefghij
	 >
	おつかれさまでした!
	

表示される文字列(テキストファイル)の内容

	
	zxcvbnm,
	abcdefghij
	qwert yuiop
	

 

ソースコード

 

ヘッダファイル取り込み。
ファイル操作、文字列操作、乱数・時間関連のヘッダをインクルードします。

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

 

ファイルから文字ポインタ(文字列)の配列に一気に読み込む関数と、2つの文字列を比較して一致率を計算する関数をつくっています。
ポインタをすすめながら比較するなど、他の言語には見られないコーディングになりますが、C言語は一般的にこのような書き方が多いです。

 

	
	#define MAX_TEXT_LINES 128

	/* 表示文字列と入力文字列の一致度合いを返す */
	int calc_hit_rate(char *prtstr, char *inpstr) 
	{
	    char *pp, *pi;
	    int ihit;

		ihit = 0;
	    pp = prtstr;
	    pi = inpstr;
	    while (*pp != '\0') { 
			if (*pi == '\0')
				break;
			if (*pp++ == *pi++)
				++ihit;
		}
		return (int)((ihit * 100) / strlen(prtstr));
	}

	/* ファイルをtextlines[]に読み込み */
	int read_flines(char* fname, char *textlines[])
	{
	    FILE *fp;
	    char buf[512];
	    char *p;
	    int iline;

	    if ((fp = fopen(fname, "r")) == NULL) {
	        fprintf(stderr, "ファイル(%s)がオープンできませんでした", fname);
	        return -1;
	    }
	    iline = 0;
	    while (fgets(buf, sizeof(buf)-1, fp) != NULL) {
	        p = buf + strlen(buf) - 1;
	        if (*p == '\n') *p = '\0'; /* 文字列最後の改行をカット */
	        if ((p = strdup(buf)) == NULL) {
	            fprintf(stderr, "メモリの確保に失敗しました");
	            fclose(fp);
	            return -1;
	        }
	        textlines[iline++] = p;
	        /* 制限値を超えたら単にループ抜け */
	        if (iline >= MAX_TEXT_LINES - 1) break; 
	    }
	    textlines[iline] = NULL;
	    fclose(fp);
	    return iline;
	}
	    

 

メイン関数:C言語

メイン処理部分は下記になります。
特記事項を特にあげれば2点です。

  • 乱数処理の範囲指定(0からNまで)のために、剰余を利用
  • 秒数を出すのに、time関数では秒単位になるため、今回はclockを利用

clockはCPU時間から計算するため、CPUの負荷状態によっては値はかわってきますが、今回はそこまでシビアなものではないのでこれで十分と考えました。

	int main()
	{
	    int mline, id;
	    char *textlines[MAX_TEXT_LINES];
	    char *prtstr, *p;
	    char inpstr[512];
	    clock_t ts, te;
	    double tsub;

		printf("*** タイピング練習プログラム(C言語版) ***\n");
	    if ((mline = read_flines("typetext.txt", textlines)) == -1) {
	        exit(-1);
	    }

		srand((unsigned)time(NULL));
		for (;;) {
			printf("\n表示された文字を入力してください.\n");
			id = rand() % mline;
			prtstr = textlines[id];
			if (*prtstr == '\0') {
				continue;
			}
			printf("   %s\n", prtstr);
			printf(" > ");
			*inpstr = '\0';
	        ts = clock();
	        gets(inpstr);
		    te = clock();
	        p = inpstr + strlen(inpstr) - 1;
	        if (*p == '\n') {
	            *p = '\0'; /* 改行カット*/
	        }
		    /* 入力がなかった場合は終了 */
			if (*inpstr == '\0') {
				printf("おつかれさまでした!\n");
				break;
			}
			tsub = (double)(te - ts) / CLOCKS_PER_SEC;
			printf("正解率:%d パーセント  時間: %6.2f 秒\n", 
			  calc_hit_rate(prtstr, inpstr), tsub);
		}
	    return 0;
	}

 

以上、今回は、C言語でPythonやGo言語で作成したタイピング練習プログラムをつくってみました。

タイピング練習プログラムはさまざまな言語仕様を学ぶのに適した題材です。

何か新しい言語を学ぶときには、是非参考にしてみてください。

 

Go言語、Pythonのケースは下記から読むことができます。

関連記事
HelloWorldの次のプログラム
プログラムの勉強でHelloWorldの次には何をつくったら良いか?【Go言語版】

  新しいプログラミング言語の勉強をはじめたのだけど、Hello,World!の次って何をつくればいいか悩む そんな時 ...

続きを見る

関連記事
Pythonプログラミング
HelloWorldの次に作るべきプログラム【つくるとわかるPythonの特徴】

先日Go言語版をだしたので、Pythonはじめたときにどんなものをつくったのか気になって見てみたら、プログラミング言語が異なると ...

続きを見る

 

最後までお読みいただき、ありがとうございました。

-C言語, プログラミング
-, ,

Copyright© SIMPLEONESOFT (BLOG) , 2022 All Rights Reserved.