• ベストアンサー

ポインタ勉強中です。しかも実行するとおかしいです。

<本に載ってたソース> #include<stdio.h> #include<string.h> int main() { char msg[20]; char *str=NULL; int i; int cnt; str=&msg[0]; printf("文字を入力してください"); scanf("%s",&str); cnt=strlen(msg); str=msg+cnt; for(i=cnt;i>=0;i--){ printf("%c",*(str--)); } printf("\n"); return 0; } char *str=NULL;は、ポインタstrを空にするということでしょうか? いつもながらstrlenとsizeofが混じります。 sizeofがバイトの大きさで、strlenが、文字数でしたっけ?

質問者が選んだベストアンサー

  • ベストアンサー
  • hegemon
  • ベストアンサー率72% (21/29)
回答No.3

>実行するとおかしいです。 すでに指摘されてますが、どうおかしいのか明記していただかないと回答のしようがありません。 コードを見る限り、入力された文字列を逆順で表示するもののようです。 「ABC」と入力すれば、「CBA」と表示されるでしょう。 ただし、マルチバイト文字を考慮していないので、漢字などを入力すると何が起こるかわかりません。 >char *str=NULL;は、ポインタstrを空にするということでしょうか? ヌルポインタは「どこも指していない」という意味なので、「空」というのは不正確ですね。 >sizeofがバイトの大きさで、strlenが、文字数でしたっけ? sizeof()は指定した変数が占めるメモリ領域のバイトサイズを返します。 strlen()は文字列の文字数を返します。 ちなみに、sizeof()は関数ではなく演算子です。 ただし、C/C++では文字列の終端をあらわす'\0'が必ず必要なので、文字列を格納する際には文字数+1の領域が必要です。 今回の例だと、 >  char msg[20]; となっているので、実際に入力できるのは19文字以下です。 その意味で、何文字だろうと受け入れてしまうscanf()は、非常に危険な関数だといえます。

tomo_ko_n
質問者

お礼

確かにscanfは危険だと思いました。 sizeofとstrlenは理解できました。

その他の回答 (2)

  • php504
  • ベストアンサー率42% (926/2160)
回答No.2

scanf("%s",&str); は間違いですね scanf("%s", str); が正しいです

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

タイトルで書かれている「実行するとおかしい」の 具体的な内容が、本文に書いてありません。 実行すると、どのようにおかしいのでしょうか? >char *str=NULL;は、ポインタstrを空にするということでしょうか? ポインタ変数の値をNULLにするということは、 そのポインタ変数がどこも指していない状態にする、ということです。 >sizeofがバイトの大きさで、strlenが、文字数でしたっけ? char msg[20]; と定義した場合、sizeof(msg)は20です。 また、msgの内容が例えば"abcde"ならば、strlen(msg)は5です。 特殊な場合として、msgの内容が"abc\0xyz123"なら、strlen(msg)は3です。 strlenは、'\0'の直前までの長さを求めます。

tomo_ko_n
質問者

お礼

ありがとうございます。 ポインタの勉強まだまだひつようだなと思いました。 sizeofとstrlenの違い理解できました。 今後使っていこうと思います。

関連するQ&A

  • ポインタについて

    #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文字は入力しても 表示されなくなってしまうのでしょうか? よろしくお願いします。

  • どこがちがうのでしょうか?

    以下の二つのプログラムはユーザーが文字を入力し、80文字以下なら ピリオドを追加して表示するというものです。上はうまくいきますが、下はうまくいきません。なぜでしょうか? #include<string.h> #include<stdlib.h> int main() { char str[80]; int i; printf("文字列を入力してください。\n"); gets(str); if(strlen(str)<80) { for(i=strlen(str);i<79;i++) strcat(str,"."); } printf("%s",str); } #include<stdio.h> #include<string.h> #include<stdlib.h> int main() { char str[80]; int i; printf("文字列を入力してください。\n"); gets(str); if(strlen(str)<80) { for(i=strlen(str)+1;i<79;i++) str[i] = "."; } printf("%s",str); }

  • 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

  • ポインタ配列

    ポインタ配列によるひとつのプログラムを組もうと思っています。 で、以下のようなプログラムを作ってみました。 1:#include<stdio.h> 2:#define NUM 5 3:main(void){ 4: char *str[NUM]; 5: int i; 6: for(i=0;i<NUM;i++){ 7: printf("string --->"); 8: scanf("%s",str[i]); 9: } 10: for(i=0;i<NUM;i++){ 11: printf("str[%d] --> %c\n",i,str[i]); 12: } 13:} これなのですが、8行目のscanf文でコンパイルエラーではなく、実行エラーが出ます。どのようにすれば動くようになるのでしょうか? 入力する文字は、9文字以下を想定しています。

  • 動的に生成した文字列の配列を返す関数について

    動的に生成した文字列の配列を返す関数について お世話になります。 動的に文字列の配列を生成する関数を作ったのですが、 配列をうまく受け渡すことができず困っています。 以下のように入力された件数の数だけ "abc 0"~"abc n"という文字列を生成を行っています。 関数自体は期待通りの動作をしているようなのですが、 (Test1関数の最後でbfを確認しました) 呼び出し側にうまく配列を渡すことができません。 以下にソースを掲載いたしますのでどなたかご教示いただけたらと思います。 環境はVisualStudio2005です。 よろしくお願いします。 #include <stdio.h> #include <string.h> #include <stdlib.h> void Test1(char **bf, int *cnt) { int i; int kensu; int charlength; char num[10]; char **nm1 = NULL; char **nm2 = NULL; printf("件数を入力:"); scanf("%d",&kensu); for(i=0; i < kensu; i++) { nm2 = (char**)realloc(nm1, sizeof(char*) * (i + 1)); nm1 = nm2; charlength=128; nm1[i] = (char*)malloc(sizeof(char) * (charlength)); strcpy(nm1[i], "abc "); itoa(i, num, 10); strcat(nm1[i], num); } bf = nm1; *cnt = i; return ; } void main() { int cnt; char **bf = NULL; Test1(bf, &cnt); printf("START\n"); printf("全部で%d件。\n", cnt); for(int i=0;i < cnt;i++) { printf("%s\n",bf[i]); } free(bf); printf("END\n"); }

  • ポインタ配列の問題で、、。

    ポインタ配列の問題ですが、このmain関数でどこかがおかしいのですが、どこをどう変更すれば正常に動作するのかわかりません。どなたかお願いします(注)string入力文字は9文字以下です。 #include <stdio.h> #define NUM 5 main(void) {     char *str[NUM];     int i;     for(i = 0; i < NUM; i++)     {      printf("string ->"); scanf("%s", str[i]);      }      for(i = 0; i < NUM; i++)      {        printf("str[%d] -> %s\n", i, str[i]);      } }

  • 一番大きい奇数を表示する

    scanf関数を使用して、文字列を10回入力し一番大きい文字列を表示するプログラムを作ったのですが、 一番大きい「奇数」を表示するように条件を加えた場合どうすればよいのでしょうか? 偶数=割り切れる 奇数=割り切れない ということまでは分かるのですがその先が分かりません。 一応一番大きい文字列を表示するプログラムを貼っておきます。 #include <stdio.h> int main(void) { char str[1024]; char buf[10]; int i; printf("文字列を10回入力して下さい:\n"); memset(str, 0, sizeof(str)); for (i = 0; i < 10; i++) { memset(buf, 0, sizeof(buf)); printf("input>\n"); scanf("%s", buf); } if (strcmp(buf, str) > 0) { strcpy(str, buf); } printf("output>\n%s\n" , str); getchar(); }

  • ポインタ(続)

    http://okwave.jp/qa5092628.html の続きです。 #include "stdafx.h" #include <ctype.h> #include <string.h> #include <stdlib.h> typedef struct { int number[6]; char *class_type; char *name; char *subject; } my; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char *bufNum,*bufClass,*bufName,*bufSub; int i; if((fp=fopen("test.txt","r"))==NULL){ printf("ファイルが開けません"); } my *data; data = (my *)calloc(112, sizeof(my)); if(!data){ printf("memoryが足りません\n"); } while(fgets(buf,1000,fp) !=NULL){ str=buf; bufNum = (char *)malloc(strlen(buf) + 1); bufClass = (char *)malloc(strlen(buf) +1); bufName= (char *)malloc(strlen(buf) + 1); bufSub = (char *)malloc(strlen(buf) +1); while(*str != '\0'){ if(*str != ','){ for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ } else{ switch(field){ case 0: *bufNum = *Str; data[line].number[line] = atoi(bufNum); break; case 1: *bufClass= *str; data[line].class_type = bufClass; break; case 2: *bufName = *str; data[line].name = bufName; break; case3: *bufSub = *str; data[line].subject = bufSub; break; } } str++; } switch(field){ case 0: bufNum[i] = '\0'; break; case 1: bufClass[i] = '\0'; break; case 2: bufName[i] = '\0';break; case 3: bufSub[i] = '\0'; break; } field++; } else{ str++; } } line++; field = 0; } printf("%s", data[0].name); fclose(fp); return 0; } と作ってみましたがまぁこれも上手く動かないんですが・・ 1、構造体をつくる 2、構造体のメモリをとる 3、ファイルをよみこむ 4、ポインタで宣言した構造体のメンバのメモリをとり実体をつくる 5、一行ずつよみこむ 6、カンマごとに格納 7、格納後終端文字を入れる 格納の区別はカンマごとにfieldを+しfieldの値にて行なう lineは行数 8,printfでテスト表示 終わり という一連のプログラムです。 class_typeまでは正常にでるんですが nameからが入っていません。 他にもここが微妙とかいうのがあったら教えて下さい。 個人的にはbufNum~bufSubのメモリの取り方が大きすぎる とは思うんですが他にいい手もなくて・・

  • abcdとキーボードで打ったらdcbaと表示されるプログラム

    C言語に関しては初心者です。 メイン関数は変更せずに行います。 /* reverse.c: reverse a given string */ #include <stdio.h> #include <string.h> void reverse(char *); /* プロトタイプ宣言 */ int main(void) { char str[100]; scanf("%s", str); reverse(str); printf("%s\n", str); return (0); } void reverse(char *s) { char n; int i; char str; n = strlen(str) - 1; for(i=0,i++,i<=100) { s[i] = *s[n-i]; printf("%s\"s[i]); } }

  • 文字列の扱い方

    初歩的な質問ですみません… str文字列からcという文字を見つけたら添字を返すという関数を作ったのですが、 iにこの関数を代入して、if文の制御式にiを使って比較するまでは正常なのですが、 真文にiを使うと何故か偽文(という言い方でいいのでしょうか…この場合("そんな値はありません。"というところです)が実行されてしまいます。 よろしければご教授お願い致します。 #include <stdio.h> int str_char(const char str[],int c) { int len = strlen(str); int i; for (i = 0;i < len;i++) { if (str[i] == c) return i; } return -1; } int main() { char str[64] = "Fucking Brutal Death Metal"; int ch,i; printf("どの文字を調べますか?"); scanf("%c",&ch); i = str_char(str,ch); if (i >= 0) printf("その文字は%d番目にあります。",str_char(str,ch) + 1); //何故かiだと動かない else printf("そんな値はありません。"); return 0; }