• 締切済み

ポインタ

質問なのですが、このソースのchar *str_copy(char *d, const char *s)関数内のchar *p=d;はなんで、*pにdを入れるか分かりません。それと、このdは、*dなのですか?どうして、while (*d++ = *s++) みたいに*dをつけないんですか?教えてください。宜しくお願いします。 #include <stdio.h> char *str_copy(char *d, const char *s) { char *p=d; while (*d++ = *s++) ; return (p); } int main(void) { char tmp[100]; char st1[100], st2[100],st3[100]; printf("文字列を入力してください:"); scanf("%s",tmp); str_copy(st1,str_copy(st2,tmp)); printf("文字列st1は%sです。\n", st1); printf("文字列st2は%sです。\n", st2); printf("文字列st3は%sです。\n", str_copy(st3,tmp)); return (0); }

みんなの回答

回答No.6

つまり、 while (*d++ = *s++); という表記は、C言語においては、「普通に考えれば条件式があるべきところに代入式がある」という特性以前に、このまま(while から、最後のセミコロンまでが)ひとつのイディオムとして存在しているのです。 これは、英文のイディオムが「知らなければわからない」のに近いですし、それぞれが、正しい文法でないこともあります。が、きっとその言い回しがないとぎくしゃくしてしまうのと同じで、まとめてひとつのイディオムなのです。 なので、英文に取り組むときにイディオムを意識するのと同じで、C言語の中には、こういった独特の言い回しが(少なくとも)存在してきた……という事実をふまえておくと、(その上で、いろいろなソースを読むと)理解が早くなるかも知れません。 この名残は、形式的には、ctype.h 系の関数にもあります。 if(isalpha(c)) ..... や、 if(! isalpha(c)) .... など。 これらの処理は、if の中身が、0 か 非0 で判断されることを利用して、(比較演算子を、表向き使うことなしに)自然な記述を可能にしています。 ※この場合、if(isalpha(c) == TRUE)... というような安全な記述は、存在していませんでした。(C99 の _Bool との比較は、安全だったかも)

  • ency
  • ベストアンサー率39% (93/238)
回答No.5

変数の定義時の初期化の話ですね。 # 自動変数ですから、宣言が定義を兼ねているわけで。。。 # 自動変数について、両者を別扱いする意味はないと思います。 詳細は、すでに何名かの方が回答されている通りです。 (char *)型のポインタ変数 p を定義して、それを(char *)型のポインタ変数 d に設定されているポインタ値で初期化しているわけですね。 # ポインタ変数 d が指している領域に格納されている char型の値では # ないことに注意してください。 定義時の初期化については、いろいろな議論があると思いますし、コーディング規約であーしろ、こーしろと決められているプロジェクトも多いと聞きます。

  • ddnp009
  • ベストアンサー率25% (15/58)
回答No.4

私からも補足いたします。 関数 char *str_copy(char *d, const char *s) 内での char *p = d; は、 char* p = d; と解釈すると納得できるのではないでしょうか。 変数の宣言における * と、間接演算子としての *、 カタチは一緒ですが、登場する場面で働きが違います。 ↑これがポインタのワケワカラン原因(のひとつ)かな while()中の *d, *s は、それぞれcharへのポインタ d, sの実体を見ています。

回答No.3

補足です。 while (*d++ = *s++); は、C言語の世界では、「イディオム」に近いので、表現としてはそう珍しいものではありません。 strcpy(); の実装例として、よく使われるソースです。 http://www.bohyoh.com/CandCPP/C/Library/strcpy.html http://www.yamdas.org/column/technique/clang.html など。 こちらは、char と char の比較なので、* (こちらは、ポインタ演算子) char *p = d; は、C言語の人だと、 char* p = d; とでも書くでしょうか。 もちろん、*p に代入しているのではなく、(char * 型の) p に代入しているものです。(こちらは、ポインタ宣言) 宣言と代入を一度に書くのも、割と多用されます。初期値が何なのか、わかりやすくなりますから。

  • rancers5
  • ベストアンサー率6% (3/43)
回答No.2

>このdは、*dなのですか? ポインタを引き継いでいるのでこうなります。 これを、*p=*dとするとdが指している中身をポインタとして代入してしまうのでdでいいのです。 変数定義と代入を一つの文にしているようですね。 あまりいいやり方では無いですが。

  • phoenix343
  • ベストアンサー率15% (296/1946)
回答No.1

char*までが型だから。 char *p=d; は、次の2行に置き換えられます。 char *p; p=d;

関連するQ&A

  • C言語 説明文

    C言語(文字列のコピーについて) /* 文字列のコピーを行う関数の実現例 動作原理のコメントを書き入れる */ #include <stdio.h> /*-----文字列のコピー(1)-----*/ char *scpy1 (char *d, const char *s) { int i = 0; while ((d[i] = s[i]) != '\0') { i++; } return(d); } /*-----文字列のコピー(2)-----*/ char *scpy2 (char *d, const char *s) { char *p = d; while ((*d = *s) != '\0') { d++; s++; } return(p); } /*-----文字列のコピー(3)-----*/ char *scpy3 (char *d, const char *s) { char *p = d; while ((*d++ = *s++) != '\0') { ; } return(p); } /*-----文字列のコピー(4)-----*/ char *scpy4 (char *d, const char *s) { char *p = d; while (*d++ = *s++) { ; } return(p); } int main(void) { char astr[] = "ABC"; char bstr[8], cstr[8], dstr[8],estr[8]; scpy1 (bstr, astr); scpy2 (cstr, astr); scpy3 (dstr, astr); scpy4 (estr, astr); printf("astr = %s\n" , astr); printf("bstr = %s\n" , bstr); printf("cstr = %s\n" , cstr); printf("dstr = %s\n" , dstr); printf("estr = %s\n" , estr); return (0); } ----------------------- このプログラムに、この行で何をやっているのかわかるように 一言くらいの説明文を入れる問題です。 ところどころはわかるのですが、わからないところの方が多いです。 プログラムが長くて大変かとは思いますが、どうかよろしくお願いいたします。 このプログラム自体はちゃんとコンパイルでき、実行もできたので おそらく間違いないと思います。

  • ポインタについて

    下記<コード1>ではエラーが出ないのに、 <コード2>のように変更すると、 ”error C2105: '++' には左辺値が必要です。” とエラーが出ます。 どうしてなのか教えて下さい。 <コード1> char *str_copy(char *d , const char *s){ char *t=s2; while(*d++=*s++) ; return (t); } int main(void) { char s1[128]="ABCD"; char s2[128]="EFGH"; str_copy(s2,s1); <コード2> int main(void) { char s1[128]="ABCD"; char s2[128]="EFGH"; // str_copy(s2,s1); while(*s2++=*s1++) ;

  • sscanfでフォーマットに合っているかを調べるには。

    今,Cの関数で0-9,A-Zの4文字以内の文字列かどうか を調べたいのですが, int main() { int i; char str[] = "ABCD" /* 調べたい文字列1 */ char str1[]= "ABC@" /* 調べたい文字列1 */ char str2[]= "ABCDE" /* 調べたい文字列1 */ char *p; p = str; /* ここをstr1,str2に変える */ if (strlen(p) != 4) printf("エラーです\n"); for (i = 0; i < 4; i++) { if (!isupper(p[i]) && !isdigit(p[i])) { printf("えらーです\n"); return EXIT_FAILURE; } } printf("すべてOKです\n"); return EXIT_SUCCESS; } というようにすれば,strとstr1とstr2がフォーマットに合うかわかるのですが,これをsscanfの正規表現を使用して実装したいのですが,可能でしょうか。 int main() { int ret; char str[] = "ABCD" /* 調べたい文字列1 */ char str1[]= "ABC@" /* 調べたい文字列1 */ char str2[]= "ABCDE" /* 調べたい文字列1 */ char *p; chat tmp[30]; p = str; ret = sscanf(p, "%4[0-9A-Z]", tmp); if (ret != 1) { printf("エラーです\n"); return EXIT_FAILURE; } printf("すべてOKです\n"); return EXIT_SUCCESS; } といしょうとするならば,str1のときは,@までのABCの文字列がとれて,retには1が帰ってきてしまいます。 なにか4文字以内ということを実装できる正規表現の使い方はあるのでしょうか? ちなみに sscanf(str, "%1[0-9A-Z]%1[0-9A-Z]%1[0-9A-Z]%1[0-9A-Z]", tmp1, tmp2, tmp3, tmp4) という以外でわかる方,よろしくおねがいします。

  • C言語のポインタと配列について

    下のコードについて2つ質問があります。 (1) char *p; p = str; ならわかるのですが、なぜ型が違う char *p = str; のような代入がOKなのでしょうか。文字列をコピーするときの   *p = *str; と比較して、とても違和感があります。  str は引数で受けた文字列の先頭アドレス。 (2)   char *str;   str = " 1 23 4 5"; と   char str[] = " 1 23 4 5"; との違いがよくわかりません。 #include <stdio.h> #include <ctype.h> void TrimSpace(char *str) {   char *p = str;        // (1)型が違うのになぜこんな代入をするのか?      while (*str != '\0') {     if ( !isspace(*str) ) {       *p = *str;      // この代入は自然       p++;     }     str++;   }   *p = '\0'; } int main(void) {      //char *str;   //str = " 1 23 4 5";     (2)これでは空白を詰めた後の文字列が表示されないのはなぜか?      char str[] = " 1 23 4 5"; //これで OK   printf("空白を詰める前:\"%s\"\n", str);   TrimSpace(str);   printf("空白を詰めた後:\"%s\"\n", str);   return 0; }

  • ポインタの問題です

    学校の課題である文字列をポインタを使って逆順に表示するというプログラムを作ったのですが、「問題で引数で与えられた文字列を逆順とする関数を作成せよ.ただし文字数が最大256文字であると仮定して良い.」ということなんですが、課題が求めている答えと自分が作ったプログラムがあっているか確認お願いします。 #include <stdio.h> void reverseWord(char *str); void main(void) { char *str = "sapporo"; char *p, *q; printf("元: %s\n", str); p = q = str; while (*q != '\0') q++; printf("逆順:"); while (q >= p) putchar(*q--); printf("\n"); } よろしくお願いします。

  • ポインタについて

    #include<stdio.h> int main(void) { char str[10]; char *ptr = str; printf("文字列を入力してください。\n"); scanf("%s",ptr); printf("文字列は%sです。",str); return 0; } 上記のプログラムのscanf("%s",ptr);の ptrに&をつけるとなぜ先頭の4文字は入力しても 表示されなくなってしまうのでしょうか? よろしくお願いします。

  • C言語 ポインタと配列

    #include <stdio.h> /* scanf("%c", &search); ではなく scanf(" %c", &search); であることに注意する */ char *str_chr(const char *str, char c) { char *find; find = NULL; do { if(*str == c) { find = (char*)str; break; } } while(*str++); return(find); } int main(void) { char str[100] = {0}; char search; char *find; printf("文字列を入力してください:"); scanf("%s", str); printf("検索する文字を入力してください:"); scanf(" %c", &search); find = str_chr(str, search); if(find == NULL) { puts("検索した文字は見つかりませんでした。"); } else { printf("検索した文字 %c は\"%p\"にあります。\n", *find , find); } return(0); } このコードのfind = (char*)str;の (char*)str;の部分がどうなっているのかわかりません。 あとこのfindというのは&find[0]という解釈でいいでしょうか? 教えてくださいm(_ _ )m

  • C言語に詳しい方お願い致しいます

    文字列Aから文字列Bを除いた結果を表示するプログラムなのですが 一ヶ所分からない部分があります。 #include <stdio.h> #include <string.h> int main(void){  char str1[] = "abcdefg";  char str2[] = "cde";  char str3[128] = "";  char *p1 = str1, *p2;  size_t len;  len = strlen(str2);  while((p2 = strstr(p1,str2)) != NULL) {   strncat(str3,p1,p2 - p1);   p1 = p2 + len;   printf("----\n");   printf("p2=%s\n", p2);   printf("str3=%s\n", str3);   printf("p1=%s\n", p1);  }  strcat(str3,p1);  printf("%s\n",str3);  return 0; } while文中の p1 = p2 + len; なのですが、何故これでp1の内容が「fg」になるのでしょう。

  • 困っています

    前に質問したのですが、a s d fと入力すると、asdfと表示されます。(スペースを取り除きます)何回やってもa s d fと入力すると、すぐ終了してしまいます。本当に分からないので教えてください。宜しくお願いします。 #include <stdio.h> char *str_del(char *st) { char *ptr=st; while(*st!='\0') { if (*st != ' ') { *ptr++=*st; } } *st='\0'; return(ptr); } int main(void) { char str[21]={'\0'}; int i=0; char ch; printf("文字列を入力してください:"); while(i<21) { ch=getchar(); if (ch=='\n') {break; } else if (ch != '\0' && ch != '\n') { str[i] =ch; i++; } } str[i] = '\0'; printf("%s",str_del(str)); return(0); }

  • C言語のポインタにの動作について

       以下のコードで、DelHalfSpc() において引数 str は str++ でカウントされ、ループを抜けた時点では文字列の末尾を指しているはずですが、なぜ呼び出し側の main()の char str[] には正しい値が入るのでしょうか? char *DelHalfSpc(char *str) {   //char *dmy = str; → char * という型の変数 dmy の宣言   char *dmy, *Res;   Res = dmy = str; // Res は常に先頭アドレスを指す   while (*str != '\0') {     if ( *str != ' ' ) {       *dmy = *str;       dmy++;     }     str++;   }   //ループを抜けたこの時点で str は文字列の末尾を指しているはず   *dmy = '\0';   return Res;   //ここを return str とするとヌル文字列を返す } int main(void) {   char str[] = " 1 23 4 5";   printf("空白削除前:\"%s\"\n", str);   printf("空白削除後:\"%s\"\n", DelHalfSpc(str));   printf("str も変化:\"%s\"\n", str); //なぜ正しい結果が表示されるのか?   return 0; } 【結果】 ----------------------- 空白削除前:" 1 23 4 5" 空白削除後:"12345" str も変化:"12345"

専門家に質問してみよう