C言語認定試験(2級出題範囲)

参考(2級出題範囲)

出題内容
定数 浮動小数点定数 指数形式を許す
浮動小数点接尾語はf、l、F、Lのいずれか
整数定数 整数接尾語として長語接尾語(l、L)を含む
文字定数 拡張表記は8進拡張表記、16進拡張表記を含む
文字列リテラル 拡張表記は8進拡張表記、16進拡張表記を含む
列挙定数
演算子 ビット演算子、条件演算子、代入演算子、キャスト演算子、ポインタ/アドレス演算子、構造体演算子、sizeof演算子
宣言指定子 void、short、long、float、double、構造体共用体指定子(struct、union)、列挙型指定子(enum)、型修飾子(const)、typedef
変数 上記型指定子の単純変数、配列
外部定義
プリプロセッサ機能 ファイルの包含
ライブラリ関数
数学関数<math.h>
double cos(double x); double sin(double x);
double tan(double x); double exp(double x);
double log(double x); double log10(double x);
double pow(double x, double y);
double sqrt(double x); double ceil(double x);
double fabs(double x); double floor(double x);
入出力関数<stdio.h>
NULL、EOF、FILE、stderr、stdin、stdout、
FILE *fopen(const char *filename, const char *mode);
int fclose(FILE *stream);
int fscanf(FILE *stream, const char *format, …);
int fprintf(FILE *stream, const char *format, …);
int sscanf(const char *s, const char *stream, …);
int sprintf(char *s, const char *stream, …);
int fgetc(FILE *stream, …); int fputc(int c, FILE *stream);
char *fgets(char *s,int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int getc(FILE *stream, …); int putc(int c, FILE *stream);
char *gets(char *s);int puts(const char *s);
int ungetc(int c, FILE *stream);
一般ユーティリティ関数<stdlib.h>
NULL  double atof(const char *nptr);
int atoi(const char *nptr);
long int atol(const char *nptr);
int rand(void);  void srand(unsigned int seed);
int abs(int i);  long int labs(long int j);
文字列操作関数<string.h>
NULL  size_t
char *strcpy(char *sl,const char *s2);
char *strncpy(char *sl,const char *s2, size_t n);
char *strcat(char *sl,const char *s2);
char *strncat(char *sl,const char *s2, size_t n);
int strcmp(const char *sl,const char *s2);
int strncmp(const char *sl,const char *s2, size_t n);
char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);
char *strstr(const char *sl, const char *s2);
size_t strlen(const char *s);
その他
  • main関数の引数、整数型以外の関数
  • 自己参照構造体
  • 変数の記憶クラスと通用範囲(auto、static、register、extern)

※3級出題範囲含む

注)各級とも日本工業規格 (JIS) X3010 で出題・解答する。

C言語認定試験(3級出題範囲)

C言語プログラミング能力認定試験
(C-Language Programming Skills Qualification Test)

http://www.sikaku.gr.jp/js/cp/

C言語認定試験とは

C言語を駆使した応用プログラムの作成能力を認定

C言語は、記述の自由度が高く、使用可能なプラットホームが多いなど、使用できる場面が多いことから、現在最も広く普及しているプログラミング言語です。このC言語のプログラミング能力の測定を目的に、1992年より開始されたのがサーティファイ 情報処理能力認定委員会が主催する「C言語プログラミング能力認定試験」です。
保有スキルのレベルに合わせた3段階の認定基準を設けることにより、これから新たにプログラミングの学習を始める方から、現在プログラマやシステム・エンジニアとして既に活躍されている高度IT技術者の方まで、幅広い皆様から受験いただいています。

初学者から、ビジネスシーンで活躍できるプログラマまで、幅広いスキルを測定

「C言語プログラミング能力認定試験」は、これからプログラミングを学び始める方を対象とした「3級」から、プログラマやシステム・エンジニアとして活躍されている方の保有スキルを客観的にアピールできる「1級」まで、幅広いスキルを測定しています。
特に「1級」では、実際にPCを使用して、プログラムの仕様変更やこれに伴うプログラミング作成(コーディング・コンパイル・デバッグ)を行う、極めて実践的な資格・検定試験として、IT業界でも高く評価されています。

基本情報技術者試験の午後の試験対策としても有効

「C言語プログラミング能力認定試験」の「2級」及び「3級」は、経済産業省認定「基本情報技術者試験」の「午後問題」の出題形式も意識して作成しています。そのため、「基本情報技術者試験」の学習と連動した活用も多く見られます。保有スキルのレベルに応じた級位取得を目標としていただくことで、C言語のプログラミング能力を高めるだけではなく、「基本情報技術者試験」の合格にもつなげていくことができます。

C言語認定試験について

試験名

C言語プログラミング能力認定試験
(C-Language Programming Skills Qualification Test)

試験目的

C言語を駆使して応用プログラム(言語処理系、ユーティリティなど)を作成する能力を認定します。

認定基準

一級 C言語を駆使し、応用プログラム(言語処理系、ユーティリティなど)が作成できる能力を有する。また使用しているOSについて理解をしている。
二級 小規模のプログラム(500行程度)が適切に(理路整然、簡潔、正しく、速く)書ける。また各種基本アルゴリズムを理解している。
三級 C言語の概念を理解し、簡単なプログラムが書ける。

 

参考(3級出題範囲)

出題内容
定数 整数定数 10進定数、8進定数、16進定数
整数接尾語は符号無し接尾語(u、U)のみ
文字定数 ワイド文字定数(L’c文字の列’)を除く
拡張表記は単純拡張表記のみ
文字列リテラル ワイド文字列リテラル(L”s文字の列”)を除く
拡張表記は単純拡張表記のみ
演算子 算術演算子、インクリメント演算子、デクリメント演算子、(算術の)代入演算子、関係演算子、等値演算子、論理関係演算子、括弧演算子、コンマ演算子
型指定子 char、int、unsigned、signed
変数
  • 上記型指定子の単純変数、配列
  • 初期化の構文
基本制御文 break、continue、do、for、if、return、switch、while
プリプロセッサ機能 #define、#include
ライブラリ関数
入出力関数<stdio.h>
EOF  NULL
int printf(const char *format, …);
int scanf(const char *format, …);
int getchar(void);  int putchar(int c);
文字操作関数<ctype.h>
int isalnum(int c);  int isalpha(int c);
int iscntrl(int c);  int isdigit(int c);
int isgraph(int c);  int islower(int c);
int isprint(int c);  int ispunct(int c);
int isspace(int c);  int isupper(int c);
int isxdigit(int c);  int tolower(int c);
int toupper(int c);
その他 Cの歴史と特徴

 

現在使用するC言語教科書には、文字操作関数<ctype.h>の内容について不足するので、

下記のサイトを参考にしてください。

  • http://www.c-tipsref.com/reference/ctype.html
  • http://www.bohyoh.com/CandCPP/C/Library/ctype_h.html

 

a C HTTP Client

C#やJavaでは簡単にhttp Clientプログラムができる。C言語ではソケットを作成するところから必要です。またWindowsとLinux両方対応するように書いたのでプログラムが長くなる。

(bcc32で動作確認済み)

プログラムは、最初にsocketを生成してWebサーバに接続し、テキスト形式でHTTPリクエストメッセージを作成してWebサーバに送信する。
HTTPリクエストメッセージは、複数行から成り立つ一連のデータ列。ここでいう1行とは、終端にCR(キャリッジリターン、16進の0x0d)とLF(ラインフィード、16進の0x0a)を持つデータの単位を示す。ほぼ、通常のテキスト・データの1行と等しくなる。メッセージ・ヘッダとメッセージボディ部に分かれ、両者は空行(単独のCR+LF)で分割される。

httpを理解するには、telnetで手入力でHTTPをしゃべってみるがいい方法。
https://www.softel.co.jp/blogs/tech/archives/263

まずプログラムをリストする:

#include <stdio.h> /* printf, sprintf */
#include <stdlib.h> /* exit, atoi, malloc, free */
// #include <unistd.h> /* read, write, close */
#include <string.h> /* memcpy, memset */
#ifdef __linux__
    #include <sys/socket.h> /* socket, connect */
    #include <netdb.h> /* struct hostent, gethostbyname */
    #include <netinet/in.h> /* struct sockaddr_in, struct sockaddr */
#elif _WIN32
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <windows.h>
    #pragma comment(lib,"ws2_32.lib") //Winsock Library

#else

#endif

struct hostent *server;
struct sockaddr_in serv_addr;
int bytes, sent, received;
char response[4096];
int portno;
char *host;
char *path;

void error(const char *msg) { perror(msg); exit(0); }


#ifdef _WIN32

win_send_http(char *message){
  WSADATA wsa;
  SOCKET s;

  printf("\nInitialising Winsock...");
  if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
  {
      printf("Failed. Error Code : %d",WSAGetLastError());
      return 1;
  }

  printf("Initialised.\n");

  //Create a socket
  if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
  {
      printf("Could not create socket : %d" , WSAGetLastError());
  }

  printf("Socket created.\n");

  server = gethostbyname(host);
  memset(&serv_addr,0,sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_port = htons(portno);
  memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
  //Connect to remote server
  if (connect(s , (struct sockaddr *)&serv_addr , sizeof(serv_addr)) < 0)
  {
      printf("connect failed with error code : %d" , WSAGetLastError());
      return 1;
  }

  puts("Connected");
  if( send(s , message , strlen(message) , 0) < 0)
  {
      printf("Send failed with error code : %d" , WSAGetLastError());
      return 1;
  }
  puts("Data Send\n");

  //Receive a reply from the server
  if((received = recv(s , response , 2000 , 0)) == SOCKET_ERROR)
  {
      printf("recv failed with error code : %d" , WSAGetLastError());
  }

  puts("Reply received\n");

  //Add a NULL terminating character to make it a proper string before printing
  response[received] = '\0';
  puts(response);

  closesocket(s);
  WSACleanup();

  return 0;   // everything OK
}

#endif
#ifdef __linux__

linx_send_http(message) {
  int sockfd;
  int total;

  total = strlen(message);
  /* lookup the ip address */

  server = gethostbyname(host);
  if (server == NULL) error("ERROR, no such host");
      /* create the socket */
      sockfd = socket(AF_INET, SOCK_STREAM, 0);
      if (sockfd < 0) error("ERROR opening socket");
      /* fill in the structure */
      memset(&serv_addr,0,sizeof(serv_addr));
      serv_addr.sin_family = AF_INET;
      serv_addr.sin_port = htons(portno);
      memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
              /* connect the socket */
      if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
          error("ERROR connecting");
              /* send the request */

  sent = 0;
  do {
      bytes = write(sockfd,message+sent,total-sent);
      if (bytes < 0)
          error("ERROR writing message to socket");
      if (bytes == 0)
          break;
      sent+=bytes;
  } while (sent < total);
  /* receive the response */
  memset(response, 0, sizeof(response));
  total = sizeof(response)-1;
  received = 0;
  printf("Response: \n");
  do {
     printf("%s", response);
     memset(response, 0, sizeof(response));
     bytes = recv(sockfd, response, 1024, 0);
      if (bytes < 0)
         printf("ERROR reading response from socket");
     if (bytes == 0)
         break;
     received+=bytes;
  } while (1);

  if (received == total)
      error("ERROR storing complete response from socket");

  /* close the socket */
  close(sockfd);

  return 0;   // everything OK
}

#endif

int main(int argc,char *argv[])
{
    int i;
    char message[4096];
    portno = atoi(argv[2])>0?atoi(argv[2]):80;
    host = strlen(argv[1])>0?argv[1]:"localhost";
    path = strlen(argv[4])>0?argv[4]:"/";

    if (argc < 5) { puts("Parameters: <host> <port> <method> <path> [<data> [<headers>]]"); exit(0); }

    /* How big is the message? */
    if(!strcmp(argv[3],"GET"))
    {
      if(argc>5)
          sprintf(message,"%s %s%s%s HTTP/1.0\r\nHost: %s\r\n",
              strlen(argv[3])>0?argv[3]:"GET",               /* method         */
              path,                                          /* path           */
              strlen(argv[5])>0?"?":"",                      /* ?              */
              strlen(argv[5])>0?argv[5]:"",host);            /* query string   */
      else
          sprintf(message,"%s %s HTTP/1.0\r\nHost: %s\r\n",
              strlen(argv[3])>0?argv[3]:"GET",               /* method         */
              path,host);                                    /* path           */
      for(i=6;i<argc;i++)                                    /* headers        */
          {strcat(message,argv[i]);strcat(message,"\r\n");}
      strcat(message,"\r\n");                                /* blank line     */
    }
    else
    {
        sprintf(message,"%s %s HTTP/1.0\r\nHost: %s\r\n",
            strlen(argv[3])>0?argv[3]:"POST",                  /* method         */
            path,host);                                        /* path           */
        for(i=6;i<argc;i++)                                    /* headers        */
            {strcat(message,argv[i]);strcat(message,"\r\n");}
        if(argc>5) {
          sprintf(message+strlen(message),"Content-Length: %d\r\n",(int)strlen(argv[5]));
          sprintf(message+strlen(message),"Content-Type: application/x-www-form-urlencoded\r\n");
        }

        strcat(message,"\r\n");                                /* blank line     */
        if(argc>5)
            strcat(message,argv[5]);                           /* body           */

              sprintf(message,"%s %s HTTP/1.0\r\nHost: %s\r\n",
                  strlen(argv[3])>0?argv[3]:"POST",                  /* method         */
                  path,host);                                        /* path           */
              for(i=6;i<argc;i++)                                    /* headers        */
                  {strcat(message,argv[i]);strcat(message,"\r\n");}
              if(argc>5) {
                sprintf(message+strlen(message),"Content-Length: %d\r\n",(int)strlen(argv[5]));
                sprintf(message+strlen(message),"Content-Type: application/x-www-form-urlencoded\r\n");
              }

              strcat(message,"\r\n");                                /* blank line     */
              if(argc>5)
                  strcat(message,argv[5]);                           /* body           */
    }

    printf("Processed\n");
    /* What are we going to send? */
    printf("Request:\n%s\n",message);

    #ifdef _WIN32

    win_send_http(message);

    #endif
    #ifdef __linux__

    linx_send_http(message);

    #endif

    return 0;
}

 

 

 

このプログラムを利用して、例のTinyWebDBを読み書きしてみる。

まずPostで、データを書き込む

C:\Users\chen\Documents\C\http-client>http-client-3 tinydb.work 80 POST /api/storeavalue/ “tag=presentationtimer&value=Just a TEST from C3”

Process 2
Allocating...
Processed
Request:
POST /api/storeavalue/ HTTP/1.0
Host: tinydb.work
Content-Length: 47
Content-Type: application/x-www-form-urlencoded

tag=presentationtimer&value=Just a TEST from C3

Initialising Winsock...Initialised.
Socket created.
Connected
Data Send

Reply received

HTTP/1.1 200 OK
Server: nginx
Date: Tue, 12 Dec 2017 06:56:12 GMT
Content-Type: application/json
Content-Length: 52
Connection: close
X-Powered-By: PHP/5.6.31
Vary: Cookie
Set-Cookie: wfvt_2029330401=5a2f7d8c36e15; expires=Tue, 12-Dec-2017 07:26:12 GMT; Max-Age=1800; path=/; httponly
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-cache, must-revalidate

["STORED","presentationtimer","Just a TEST from C3"]

 

次は、Getで、書き込んだデータを取得

C:\Users\chen\Documents\C\http-client>http-client-3 tinydb.work 80 POST /api/getvalue/ “tag=presentationtimer”

Process 2
Allocating...
Processed
Request:
POST /api/getvalue/ HTTP/1.0
Host: tinydb.work
Content-Length: 21
Content-Type: application/x-www-form-urlencoded

tag=presentationtimer

Initialising Winsock...Initialised.
Socket created.
Connected
Data Send

Reply received

HTTP/1.1 200 OK
Server: nginx
Date: Tue, 12 Dec 2017 06:57:10 GMT
Content-Type: application/json
Content-Length: 51
Connection: close
X-Powered-By: PHP/5.6.31
Vary: Cookie
Set-Cookie: wfvt_2029330401=5a2f7dc61d61c; expires=Tue, 12-Dec-2017 07:27:10 GMT; Max-Age=1800; path=/; httponly
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-cache, must-revalidate

["VALUE","presentationtimer","Just a TEST from C3"]

 

Dump file

DUMP で出力された内容を ダンプリスト と呼ぶ

ダンプリスト左端はアドレス(ファイル先頭からの位置)

ダンプリスト中央にある16進数(バイト)が列挙されてる部分がマシン語プログラム(バイトコード)を表している。

ダンプリスト右端は、バイトコードをキャラクタコードで表現したときの内容。ただしバイトで表現可能な数値はキャラクタコードの範疇を超えることがあるため、そのような場合はピリオドで表現される。

dump.c

#include <stdio.h>
int main(int argc, char* argv[])
{
    FILE *fp;
    unsigned char buf[16];   /* 読み込みバッファ */
    unsigned long addr = 0;  /* 先頭からのアドレス */
    int readnum, i;

    if(argc <= 1) {
        printf("usage:dump filename\n");
        return 1;
    }
    if(!(fp = fopen(argv[1], "rb"))) {
        printf("file open error.\n");
        return 1;
    }
    while(1) {
        printf("%08x ", addr);
        readnum = fread(buf, 1, 16, fp);
        /* パイナリデータの表示 */
        for(i = 0; i < readnum; i++) {
            if( i == 8)
                 printf("   ");
            printf("%02x ", buf[i]);
        }
        for(i =readnum; i < 16; i++) {
            if(i == 8)
                printf("   ");
            printf("   ");
        }
        printf("   ");
        for(i = 0; i < readnum; i++)
            printf("%c", (32 <= buf[i] && buf[i] <= 126) ? buf[i] : '.');
        printf("\n");
        addr += 16;
        if(feof(fp))
            break;
    }
    fclose(fp);
    return 0;
}

 

 

[Borland C]Error on JP programming

Hello World例

正しいhello.c。カーソルは位置を注意してください。Pは5:5の位置にある。

image

コンパイルと実行する様子

典型的なエラー

初めてCのプログラミングは なかなかうまく行かないかも知れない。
ここではHello World プログラムの典型的な間違い例をいくつか紹介する。

半角引用符「”」ではなく全角引用符「”」に

右の引用符は全角引用符「”」になっている

image

全角スペースが用いられ

全角スペースが用いられている、これはなかなか探しにくい。

カーソルは位置を注意してください。Pは5:3の位置にある。

(半角のスペースなら、Pは5:5の位置にある。)

image

セミコロン「;」の付け忘れ

セミコロン「;」の付け忘れである。

image

[GCC]C Compiler on Linux

C言語の最小限の開発環境を作る手順

  1. エディタをインストール
  2. コンパイラをインストール
  3. コンパイラにPATHを通す設定をする

エディタをインストール

Atomという新世代のエディター(Windows、Mac OS X、Linux対応)をインストールしてください。

公式サイト

コンパイラをインストール

LinuxでのC言語開発環境について解説しています。「GNU Compiler Collection」が一般的です。

それでは gcc をインストールしていきます。

Debian

Debianでは、apt-getコマンドを使ってgccをインストールします。

# apt-get install gcc

Ubuntu

UbuntuはDebianベースのディストリビューションなので、Debianと同じようにa apt-getコマンドを使います。ただ、Ubuntuにはrootユーザーという概念がないので、sudoコマンドでインストールしていきます。

$ sudo apt-get install gcc

CentOS

CentOSでは、yumコマンドを使ってgccをインストールします。

# yum install gcc

以上で、コンパイラ(gcc)のインストールは完了です。

コンパイラにPATHを通す設定をする

不要です。

ソースコードコンパイル

C言語プログラムのファイル名を「hello.c」というファイルを作成します。ファイルの中身は「Hello, World!」という文字列を出力するプログラムです。

hello.cをコンパイルします。

$ gcc hello.c 

エラーが表示されなければ、OKです。

プログラムの実行

実行します。

$ ./a.out 
Hello, World

無事に実行できましたね。

[GCC]C Compiler on Windows

WindowsでgccをインストールするにはMinGWを利用した、C言語の最小限の開発環境を作る手順

  1. エディタをインストール
  2. コンパイラをインストール
  3. コンパイラにPATHを通す設定をする

エディタをインストール

Atomという新世代のエディター(Windows、Mac OS X、Linux対応)をインストールしてください。

公式サイト

コンパイラをインストール

C言語コンパイラって幾つかありますが、visual studioはファイルサイズがデカいので却下です。gccのインストールをオススメします。gccはMacでもLinuxでもWindowsでも使えます。

コンパイラの違い一覧

システム mingw-jp Visual Studio .net Borland C++ Builder
コンパイラ名 gcc cl bcc32
オブジェクトファイルの拡張子 .o .obj .obj
実行ファイル名指定 -o ファイル名 -o ファイル名 -eファイル名
make コマンド mingw32-make nmake make
依存ファイルマクロ $^ $** $**

 

WindowsでgccをインストールするにはMinGWというソフトを使う必要があります。

MinGW | Minimalist GNU for Windows

  1. MinGWのホームページで「Downloads」をクリック
  2. sourceforgeというサイトに飛びます
  3. 「Download mingw-get-setup.exe (86.5 kB)」をクリック
  4. exeファイルをダウンロード
  5. ダウンロードしたexeファイルを起動
  6. インストール自体は「Install」ボタンとか「Continue」ボタンをクリックするだけ

MinGW インストールマネージャー画面 4

左のメニュー画面で「Basic Setup」を選択し、

  • mingw-developer-toolkit
  • mingw32-base
  • mingw32-gcc-g++
  • msys-base-32

を選んで、右クリックで「Mark for Installation」を選択します。

選び終わったら、上の「Installation」メニューから「Apply Changes」を選択すればインストールが始まります。

インストールが始まると、先ほど選択したパッケージがこのように変わります。

MinGW インストールマネージャー画面 5

これでGCCが使えるようになりました。

コンパイラにPATHを通す設定をする

事前にgcc.exeの場所を探しておいてください。
MinGWをインストールする際に設定を変更していなければ C:MinGWbin にあるはずです。

  • エクスプローラー起動
  • マイコンピューターで右クリック
  • プロパティ選択
  • システムの詳細設定
  • 「環境変数」ボタン
  • ユーザー環境変数 or システム環境変数にPathがあります
    そのPathの最後に ;C:MinGWbin を追記
    ※「;」を必ず付けてください

環境変数画面

ユーザー環境変数とシステム環境変数の違い

  • ユーザー環境変数:今ログインしているユーザーだけに有効
  • システム環境変数:全てのユーザーに有効

お好きな方をお使いください。

コマンドプロンプトで gcc --help と打ってみてください。

↓こんな感じのものが出てればgccが正常に使える状態です。

 

バージョンの確認

> gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/mingw32/5.3.0/lto-wrapper.exe
Target: mingw32
Configured with: ../src/gcc-5.3.0/configure --build=x86_64-pc-linux-gnu --host=mingw32 --prefix=/mingw --disable-win32-registry --target=mingw32 --with-arch=i586 --enable-languages=c,c++,objc,obj-c++,fortran,ada --enable-static --enable-shared --enable-threads=posix --with-dwarf2 --disable-sjlj-exceptions --enable-version-specific-runtime-libs --enable-libstdcxx-debug --with-tune=generic --enable-libgomp --disable-libvtv --enable-nls
Thread model: posix
gcc version 5.3.0 (GCC)

 

ソースコードコンパイル

C言語プログラムのファイル名を「hello.c」というファイルを作成します。ファイルの中身は「Hello, World!」という文字列を出力するプログラムです。

以下のコマンドを打ってみてください。

実行ファイルを指定することもできます。

> gcc hello.c -o hello.exe

そしたら hello.exe が作られています。

プログラムの実行

コマンドプロンプトで実行ファイル名を入力してEnterキーを押すだけです。

コマンドプロンプトで、「a.exe」を実行します。

> a.exe
Hello, World

このように「Hello, World」という文字列が出力されれば、OKです。

実行ファイルを指定した場合、指定したファイルを実行してください。

参考:

C exercises2 (3) structures

演習

1)任意二つのunsigned int型数値の論理AND, OR, XORを求めなさい(P324)

/* a9-4-1.c */
#include <stdio.h>
#include <limits.h>

int main(void)
{
  unsigned a, b;

  printf("0 〜 %u の整数を2つ入力してください。¥n", UINT_MAX);
  printf("> ");
  scanf("%u", &a);
  printf("> ");
  scanf("%u", &b);

  printf("%u(%#x) AND %u(%#x) = %#x¥n",__,__,__,__,__);
  printf("%u(%#x) OR  %u(%#x) = %#x¥n",__,__,__,__,__);
  printf("%u(%#x) XOR %u(%#x) = %#x¥n",__,__,__,__,__);

  return 0;
}

 

2)任意unsigned int型数値のビットパターンを表示(P328)

/* a9-4-2.c */
#include <stdio.h>
#include <limits.h>

void show_bit(unsigned dt);

int main(void)
{
  unsigned a;

  printf("0 〜 %#x の16進数を入力してください。> ", UINT_MAX);
  scanf("%x", &a);

  show_bit(a);

  return 0;
}

/*** ビット表示関数 ***/
/*(仮引数)dt:表示データ */
void show_bit(unsigned dt)
{
    int i, len;

    len = sizeof(dt) * CHAR_BIT;
        
    printf("%#x ---> ", dt);
    for (i = len - 1; i >= 0; i--){
        putchar(( __ >> __ & 1U) ? '1' : '0' );
    }
    putchar('¥n');
}

 

演習解説

構造体の変数

構造体とは

構造体とは,「いろいろな種類の互いに関連するデータをまとめて, 1つのかたまりにしたもの」である。 たとえば,「氏名,年齢,性別などのデータを一人分だけまとめたもの」 このようなものをいう。

構造体 構造体を構成する要素を,構造体のメンバと呼ぶ。上の例では, 「名前」「性別」「年齢」「身長」「体重」などが,メンバにあたる。

構造体の宣言

構造体は,一つのデータ型であり,その型枠をまず始めに宣言する必要がある。 そして,その型枠を型とする変数を宣言する形で構造体の実体(オブジェクト)を宣言し, それを使用することができる。

構造体の型枠の宣言と,その型枠をもつ構造体変数の宣言は次のようになされる.

struct 構造体タグ名 {メンバの並び};   /* 型枠の宣言 */

struct 構造体タグ名 構造体変数名;     /* 構造体変数の宣言 */

例えば,次図のような人のデータをまとめた構造体の定義は下のようになる。

person 構造体struct

 _person {           /* _person がタグ名 */
    char name[20];        /* 文字配列型のメンバ name */
    char sex;              /* 文字型メンバ sex */
    int age;               /* 整数型メンバ age */
    double height;         /* 倍精度実数型メンバ height */
    double weight;         /* 倍精度実数型メンバ weight */
};


struct

 _person p;      /* p という名前の struct _person 型変数を宣言 */

構造体の代入

一つの構造体変数の内容全部を 同じ型の別の構造体変数に, 通常の変数を代入するのと同じように,代入することができる.

    person_t p1 = {"Tom", 'M', 19, 175.2, 69.5};
    person_t p2;
    
    p2 = p1;

構造体の代入

構造体の配列

構造体を並べた配列も扱える.その宣言定義は通常のようにすればよい.

#define PERSON_NUM 5

typedef struct {   
    char name[20];
    char sex; 
    int age;
    double height; 
    double weight; 
} person_t;

person_t p[PERSON_NUM]

;

これで,要素数がPERSON_NUM個(5個)の person_t 構造体型配列 p ができる.

構造体配列たとえば,上の図で色のついてある p[3] の height メンバには, p[3].height でアクセスする.

サンプルプログラム2

#include <stdio.h>

#define PERSON_NUM 5

typedef struct {   
    char name[20];
    char sex; 
    int age;
    double height; 
    double weight; 
} person_t;

main()
{
    person_t p[PERSON_NUM] = {{"Bob",      'M', 19, 165.4, 72.5},
                              {"Alice",    'F', 19, 161.7, 44.2},
                              {"Tom",      'M', 20, 175.2, 66.3},
                              {"Stefany",  'F', 18, 159.3, 48.5},
                              {"Leonardo", 'M', 19, 172.8, 67.2}};
    int i;
    double height_sum, weight_sum, height_ave, weight_ave;                          
    
    height_sum = weight_sum = 0.0;
    for (i = 0; i < PERSON_NUM; i++) {
        height_sum += p[i].height;
        weight_sum += p[i].weight;
    }
    height_ave = height_sum / PERSON_NUM;
    weight_ave = weight_sum / PERSON_NUM;
    
    printf("average height = %fn", height_ave);
    printf("average weight = %fn", weight_ave);
    
    return 0;
}

構造体のいろいろな宣言の仕方

  1. 構造体の型枠と実体を同時に宣言する
  2. 初期化も同時に行う
  3. 構造体タグ名を記述しないこともできる
  4. typedefで別名をつけることができる

演習

「学籍番号、氏名、学年、クラス」を含める構造体の宣言、初期化、表示するプロフラムを作る。
演習
struct student
{
char no[10]; //番号
char name[20]; //名前
int s_year; //年
char s_class; //クラス
};

C programming 2 (3) Arrays 2

ハッカソン

ハッカソン(英語: hackathon 、別名:hack day ,hackfest ,codefest )とはソフトウェア開発分野のプログラマやグラフィックデザイナー、ユーザインタフェース設計者、プロジェクトマネージャらが集中的に作業をするソフトウェア関連プロジェクトのイベントである。

ハッカソン – Wikipedia

https://ja.wikipedia.org/wiki/ハッカソン

国内最大級のITコンテスト「JPHACK 2016」のお知らせ
——————————————————————————

こんにちは!JPHACKS運営事務局です。

突然ですが、モノづくりを仕事にしたいと考えているデザイン系、情報系学生のみなさん、
こんなお悩みはありませんか?

・「学生のうちに、アプリやプロダクトなど何か一つ形にしておきたい」
・「ただ、自分は○○はできるけど、△△ができないから、Webサービスやアプリをつくれない」
・「同世代のデザイン系学生、情報系学生と競い合い、交流したい」
・「自分のスキルがどの程度のものか確かめたい。有名企業の社会人からレビューを受けてみたい」

そんなお悩みを解決すべく今回ご紹介させていただくのが、「JPHACKS 2016」です。

http://jphacks-civic.strikingly.com/

JPHACKS2016 エントリーの歩み:

  1. JPHACKS2016 エントリー
  2. JPHACKS2016 本エントリー
    1. URL: http://ubi.daiichi-koudai.com/ – ユビキタス・クラブ
    2. github: https://github.com/
  3. JPHACKS2016追加エントリー

前回の演習

  • 演習5-4(p115) List5-6を書き換えて、配列aの要素の並びを逆順にしたものをbにコピーするプログラムを作成さよ。
#include <stdio.h>
#define NUMBER 5

int main(void)
{
    int i;
    int va[NUMBER] = {15, 20, 30};
    int vb[NUMBER];
    
    for(i = 0; i < 5; i++) {
        vb[i] = va[NUMBER - i - 1];
    }
    
    puts(" va vb");
    puts("-------");
    
    for(i = 0; i < 5; i++) {
        printf("%3d%3d\n", va[i], vb[i]);
    
    }
    
    return(0);
}

 

二次元配列の宣言

配列には同じデータ型の値を要素として管理できますが、配列そのものを要素として持つ配列を作成することが出来ます。何次元でも出来ますがよく利用される2次元を例に考えてみます。

2次元配列の書式は次の通りです。

データ型 配列名[要素数1][要素数2];

配列と単に書いた場合は1次元の配列です。1次元の配列の場合は「配列名[添字]」でそれぞれの要素を表しますが、2次元の場合は「配列名[添字][添字]」で各要素を表します。

具体的には次のように記述します。

int seiseki[2][3];

seiseki[0][0] = 72;
seiseki[0][1] = 67;
seiseki[0][2] = 84;

seiseki[1][0] = 67;
seiseki[1][1] = 92;
seiseki[1][2] = 71;

2次元配列を使う意味を考えてみます。例えば6日間の運動した時間を管理するのではあれば1行に列挙して管理するのが便利ですし、3教科の成績を2人分管理するのであれば表形式で管理した方が便利です。成績と名前などのように2つの異なるインデックスを使って要素を特定した方が便利な場合には2次元配列が有効です。

なお今回は2次元の例でしたが3次元でも4次元でも可能です。その場合は次のような書式となります。

データ型 配列名[要素数1][要素数2][要素数3];
データ型 配列名[要素数1][要素数2][要素数3][要素数4];

3次元までは利用することもありますが、4次元以上の多次元配列ともなるとあまり利用する機会はありません。

二次元配列の初期化

二次元配列の場合でも宣言と同時に初期値を設定することが出来ます。次の書式を使います。

データ型 配列名[要素数1][要素数2] = {{値00, 値01, ...}, {値10, 値11, ...}, ...};

少し分かりにくいですが上記は次のように記述したものと同じです。

データ型 配列名[要素数1][要素数2];

配列名[0][0] = 値00;
配列名[0][1] = 値01;
...


配列名[1][0] = 値10;
配列名[1][1] = 11;
...

...

要素数2の配列があたかも1つの要素のように、要素数1の分だけあるような形で指定します。具体的には次のように記述します。

int seiseki[2][3] = {{72, 67, 84}, {67, 92, 71}};

この場合は次のように記述した場合と同じです。

int seiseki[2][3];

seiseki[0][0] = 72;
seiseki[0][1] = 67;
seiseki[0][2] = 84;

seiseki[1][0] = 67;
seiseki[1][1] = 92;
seiseki[1][2] = 71;

要素数を指定せずに初期化する

配列は宣言と同時に初期化する場合は要素数を省略できました。2次元配列の場合でも最初の配列の要素数は省略が可能となっています。

データ型 配列名[][要素数2] = {{値00, 値01, ...}, {値10, 値11, ...}, ...};

具体的には次のように記述します。

int seiseki[][3] = {{72, 67, 84}, {67, 92, 71}};

二次元配列のデータの利用

では簡単なサンプルプログラムを作成して試してみます。

test5-1.c

#include <stdio.h>

int main(void){
  int seiseki[][3] = {
    {72, 67, 84}, 
    {67, 92, 71}
  };
  int i;

  for (i = 0 ; i < 2 ; i++){
    printf("%d人目の成績です¥n", i + 1);
    printf("算数の点数は%dです¥n", seiseki[i][0]);
    printf("国語の点数は%dです¥n", seiseki[i][1]);
    printf("社会の点数は%dです¥n", seiseki[i][2]);
  }

  return 0;
}

上記を「test5-1.c」の名前で保存し、実行します。

演習

test5-1.cを修正して、科目ごとの合計点を求めてください。

出力例:

算数の合計点:289
国語の合計点:293
社会の合計点:292