I ♥ WordPress

[時間割:C言語]『はじめてのC言語完全入門』その15
2009/01/18 21:13 posted by kunkichi

火曜日は仕事だったのでしょうがないとして、金曜日は帰宅早々寝ちゃったので、その分を取り返しておきます。ということで『C言語』です。引き続き文字列とポインタです。関数の引数として文字列を渡す、その関数を呼び出す、というのをやります。

はじめてのC言語 完全入門 (標準プログラマーズライブラリ)
塚越 一雄
技術評論社
売り上げランキング: 420963


  • 引数の書式は2パターン。配列で渡すか、ポインタで渡すか。
    • 配列の場合void kansu(char str[])
      {
        printf("渡された引数は%sです。¥n", str);
      }
      配列の場合はサイズ指定できないのは通常の配列と同じ。また、この時strは配列名であり定数である点に注意。
    • ポインタの場合void kansu(char *p)
      {
        printf("渡された引数は%sです。¥n", p);
      }
      この時strはポインタであり変数である点が配列で渡す場合と異なる。
  • 配列形式、ポインタ形式のそれぞれで渡された配列の引数は意味としては異なるけど、関数内では文法上同じ扱いになる。従って、
    • 配列で渡されたものを関数内でポインタとして使っても良い。
    • ポインタで渡されたものを関数内で配列として使っても良い。

    以前にやった配列とポインタのところと全く同じ。

  • 呼び出す時は、文字列の先頭アドレスを渡してあげる。つまり、
    • 文字配列で渡す場合は配列名(配列名は配列の先頭アドレスを示す)kansu(str);
    • ポインタで渡す場合はポインタ(ポインタはそもそも先頭アドレス、サイズはポインタの型が決める)kansu(p);
    • さらにもう一つ、文字列を直接指定してあげることもできる。kansu("abcdef");というのは式の中で文字列リテラルが渡されると先頭アドレスとして評価されるから。
  • ということでサンプル。書籍にもある、エラーメッセージとリターンコードを渡して、exitしちゃうプログラム。配列指定の場合とポインタ指定それぞれの場合の関数を用意してます。mainの中で呼び出す関数を変更すればそれぞれを呼び出します。まあ結果は同じなんだけど。#include <stdio.h>
    #include <stdlib.h> /* include exit() */
     
    void fatal_p(char *errmsg, int errcode);
    void fatal_a(char *errmsg, int errcode);
     
    int main()
    {
      fatal_a("異常終了!!!",255);
     
      fprintf(stdout,"%s\n", "正常終了");
      return 0;
    }
     
    void fatal_p(char *errmsg_p, int errcode)
    {
      fprintf(stderr, "%s\n", errmsg_p);
      exit(errcode);
    }
     
    void fatal_a(char errmsg_a[], int errcode)
    {
      fprintf(stderr, "%s\n", errmsg_a);
      exit(errcode);
    }
  • さっきの例では、サンプルの関数はvoidだったので何も返さないのだけど、関数で文字列を返す場合は、関数の型を文字へのポインタとして定義する必要がある。そして呼び出す際は、返された文字列を一時的に入れておく文字列用バッファを用意しておいてそこに代入する。char *kansu(〜){
      ・・・
    }
     
    int main(){
      char str[256];
      char = kansu(〜);
    }
    とあるのだけど、んー、うまく動かない、、、最後に書いてある、文字列を渡したら最後の1文字を除いた文字列を返すサンプルスクリプトをちょっといじってみた。本の中ではループで順に1文字づつ消しているのだけど、単に1文字だけ返すように書き換えてみたのだけど、バッファに返そうとするところでコンパイラがエラーを吐いちゃう。#include <stdio.h>
    #include <string.h>
     
    char *remove_last_char(char str[])
    {
      int last = strlen(str);
     
      if( last > 0 )
        str[last-1] = '\0';
     
      return str;
    }
     
    int main()
    {
      char s[] = "1234567890";
     
      char ret[256];
      ret = remove_last_char(s);
     
      printf("%s\n",p);
    }
    ビルドするとこんな感じ。$ gcc -o str_ary2 str_ary2.c
    str_ary2.c: In function ‘main’:
    str_ary2.c:19: error: incompatible types in assignment
    本のサンプルと同様に関数の結果をそのままprintfに渡してやるとちゃんと動く。#include <stdio.h>
    #include <string.h>
     
    char *remove_last_char(char str[])
    {
      int last = strlen(str);
     
      if( last > 0 )
        str[last-1] = '\0';
     
      return str;
    }
     
    int main()
    {
      char s[] = "1234567890";
     
      printf("%s\n",remove_last_char(s));
    }
    なんでかなぁ〜、、、文字へのポインタにする意味がまったくわからない。

うーん、やっぱりポインタ、配列、文字配列とまだまだ整理できてないので、理解できてない。以前にやった、ポインタと配列のところ読み返してみたんだけどね〜、それでもだめか。一度整理しておく必要があるかな。ただまあそれは課題として置いておいて、どんどん進んで一通り終わらせることを優先とします。

次回は文字列の応用編。

コメント&トラックバック

トラックバックURL

突然ごめんなさい、アプリ開発初心者です。。。

どうしても分からないバグがあって、もし
心当たりがあれば、ヒントを頂きたいのですが・・・

incompatible types in assignment

というのは
どういった類のエラーなんでしょうか…??

2010/7/29 木曜日17:56:56 posted by EMI





このページの先頭へ