• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:ポインタについて)

ポインタについての疑問

このQ&Aのポイント
  • ポインタを使用した文字列の処理方法について教えてください。
  • ソースコードにおいてポインタを用いて文字列を表現する方法を教えてください。
  • ポインタを使って文字列を操作する際にstrcpyを使用する必要があるのでしょうか?

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

  • ベストアンサー
  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.7

> if (strchr(delims, c)) { if (strchr(delims, c) != NULL) { と、きちんと NULL と比較しておいたほうがいいか^^; ではでは、失礼いたしました^^

その他の回答 (7)

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.8

こっちのほうがわかりやすいですね^^ /* fp から文字を読みこみ、 delims 中の文字で区切った文字列を buf に格納して返す。 最低 1 文字、最高 siz 文字を buf に設定する(buf は最低、 siz + 1 バイトの領域があるとする)。 何か設定した場合は buf を返し、何も設定しなかった場合は NULL を返す。 */ char *gettok(char *buf, size_t siz, const char *delims, FILE *fp) { int c; char *p = buf; while (p < buf + siz && (c = getc(fp)) != EOF) { if (strchr(delims, c) == NULL) { *p++ = c; } else if (p != buf) { break; } } *p = '\0'; return p == buf ? NULL : buf; }

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.6

ん?ループを一重にしたので、isdelim は不要で、char *q も不要でしたね^^; char *gettok(char *buf, size_t siz, const char *delims, FILE *fp) { int c; char *p = buf; while (p < buf + siz && (c = getc(fp)) != EOF) { if (strchr(delims, c)) { if (p == buf) continue; else break; } *p++ = c; } *p = '\0'; return p == buf ? NULL : buf; }

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.5

あぁ。。strchr() を使えば、ループが一つなくなって、見やすいかもしれませんね^^ ===== char *gettok(char *buf, size_t siz, const char *delims, FILE *fp) { int c; char *p = buf; while (p < buf + siz && (c = getc(fp)) != EOF) { const char *q; int isdelim = 0; if (strchr(delims, c)) { if (p == buf) isdelim = 1; else break; } if (isdelim) continue; *p++ = c; } *p = '\0'; return p == buf ? NULL : buf; }

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.4

> 例えばこんなソースコードがあって、(1)をポインタにして、(2)のstrcpyを使わずにポインタだけで表現するとしたらどのようになるんですか? strtok() を使うなら、コピーしないと難しいですね。自分で、単語らしきものを切り分ければいいですが。 ご参考:gettok():インデントがなくなるため、余計な中括弧もつけておきました。 ========== #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stddef.h> /* 最低 1 文字、最高 siz 文字を buf に設定する(buf は最低、 siz + 1 バイトの領域があるとする)。 何か設定した場合は buf を返し、何も設定しなかった場合は NULL を返す。 */ char *gettok(char *buf, size_t siz, const char *delims, FILE *fp) { int c; char *p = buf; while (p < buf + siz && (c = getc(fp)) != EOF) { const char *q; int isdelim = 0; for (q = delims; *q; ++q) { if (c == *q) { if (p == buf) { // 頭部のdelimsを読み飛ばす isdelim = 1; break; } else { goto end; } } } if (isdelim) continue; *p++ = c; } end: if (p != buf) { *p = '\0'; return buf; } else { return NULL; } } #define MAX 32 struct node{ char *moji; struct node *left,*right; }; typedef struct node NODE; void error(char *msg){ fflush(stdout); fprintf(stderr, "%s\n", msg); exit(1); } NODE *createNode(char *x){ NODE *new = malloc(sizeof(NODE)); char *moji = malloc(strlen(x) + 1); if (new != NULL && moji != NULL) { new->moji = strcpy(moji, x); new->left = NULL; new->right = NULL; return new; } error("メモリがありません。\n"); } NODE *insertNode(NODE *p, char *x){ if(p == NULL){ p = createNode(x); } else if(strcmp(p->moji, x) > 0){ p->left = insertNode(p->left, x); }else if(strcmp(p->moji, x) < 0){ p->right = insertNode(p->right, x); } return p; } void printTree(NODE *p){ if(p == NULL) return; printTree(p->left); printf("%s\n",p->moji); printTree(p->right); } int main(int argc, char *argv[]){ FILE *fp; char buf[MAX + 1]; char *ans; NODE *p = NULL; if( argc > 2 ){ printf("ファイルの指定は一つだけです。\n"); return 2; }else if(argc == 1){ printf("ファイルを指定してください。\n"); return 2; } fp = fopen( argv[1] , "r" ); if( fp == NULL ){ printf("ファイル読み込みに失敗しました。\n"); return 3; } const char puncts[] = " -,.\t\n\r\f\v"; /* 出現回数が多そうなものから並べておく */ while ((ans = gettok(buf, MAX, puncts, fp)) != NULL) { p = insertNode(p, ans); } printTree(p); fclose(fp); return 0; }

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.3

> char *moji = malloc(strlen(x + 1)); char *moji = malloc(strlen(x) + 1); でした^^;

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.2

createNode で文字列の領域を新たに確保しておくのが普通かな、と思います。 ===== たとえば^^ #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 32 #define TO_STRING_(s) #s #define TO_STRING(s) TO_STRING_(s) #define DEBUG struct node{ char *moji; struct node *left,*right; }; typedef struct node NODE; void error(char *msg){ fflush(stdout); fprintf(stderr, "%s\n", msg); exit(1); } NODE *createNode(char *x){ NODE *new = malloc(sizeof(NODE)); char *moji = malloc(strlen(x + 1)); if (new != NULL && moji != NULL) { new->moji = strcpy(moji, x); new->left = NULL; new->right = NULL; return new; } error("メモリがありません。\n"); /* error() で exit() するなら、以下は、いらないが… */ if (new != NULL) free(new); if (moji != NULL) free(moji); return NULL; } NODE *insertNode(NODE *p, char *x){ if(p == NULL){ p = createNode(x); } else if(strcmp(p->moji, x) > 0){ p->left = insertNode(p->left, x); }else if(strcmp(p->moji, x) < 0){ p->right = insertNode(p->right, x); } return p; } void printTree(NODE *p){ if(p == NULL) return; printTree(p->left); printf("%s\n",p->moji); printTree(p->right); } int main(int argc, char *argv[]){ FILE *fp; char buf[MAX + 1]; char *ans; NODE *p = NULL; if( argc > 2 ){ printf("ファイルの指定は一つだけです。\n"); return -1; }else if(argc == 1){ printf("ファイルを指定してください。\n"); return -1; } fp = fopen( argv[1] , "r" ); if( fp == NULL ){ printf("ファイル読み込みに失敗しました。\n"); return -1; } while(fscanf(fp,"%" TO_STRING(MAX) "s",buf) == 1){ /* fscanf(fp, "%32s", buf) としてバッファサイズを考慮する */ const char puncts[] = "-,."; /* 空白類は %s で除かれるので不要 */ for (ans = strtok(buf,puncts); ans != NULL; ans = strtok(NULL,puncts)) p = insertNode(p, ans); } printTree(p); fclose(fp); return 0; }

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.1

以前の質問に答えると…: 何をするプログラムなのか定かではないですが、出現する単語(のようなもの)を大文字・小文字を区別し、重複を除いて記憶するプログラムだろうと仮定して。。。 > char *buf = malloc(sizeof(char) * MAX); > char *ans = malloc(sizeof(char) * MAX); > NODE *p = malloc(sizeof(NODE)); char *buf, *ans; NODE *p = NULL; > while(fscanf(fp,"%s",buf) == 1){ while((buf = malloc(MAX + 1)) != NULL && fscanf(fp,"%s",buf) == 1){ と直せば動くかな?さらに、insertNode() を NODE *insertNode(NODE *p, char *x){ if(p == NULL){ p = createNode(x); } else if(strcmp(p->moji, x) > 0){ p->left = insertNode(p->left, x); }else if(strcmp(p->moji, x) < 0){ p->right = insertNode(p->right, x); } return p; } と直せば、想定通り動くんじゃないでしょうか。。。まだ、たとえば、 ・while ループの最後で余分にアロケートした領域を開放していない ・malloc() で確保した領域を分解して文字列領域として使用するのであとで free() しずらい ・fscanf() のバッファあふれを考慮していない ・区切り文字のみからなる場合を考慮していない ・malloc() した領域を開放せずにプログラムが終了している(システムに開放を任せ、なるべく速く終了したのなら、free() 処理しないほうがいいですが) など不備な点はありますが、とりあえず動くでしょう。また、insertNode() を少し改良すると、無駄な(同じポインタ値を何度も)代入もしなくてよくなると思います。 どの関数が領域を確保し、どの関数がそれを利用して自分のものにしてしまうのか、などをよく理解してプログラミングしたほうがよいのではないですか^^ === きちんと見てないのでまだバグがあるかもしれませんけど^^ #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 32 #define TO_STRING_(s) #s #define TO_STRING(s) TO_STRING_(s) #define DEBUG struct node{ char *moji; struct node *left,*right; }; typedef struct node NODE; void error(char *msg){ fflush(stdout); fprintf(stderr, "%s\n", msg); exit(1); } NODE *createNode(char *x){ NODE *new; new = malloc(sizeof(NODE)); if(new == NULL){ error("メモリがありません。\n"); } new->moji = x; new->left = NULL; new->right = NULL; return new; } NODE *insertNode(NODE *p, char *x){ if(p == NULL){ p = createNode(x); } else if(strcmp(p->moji, x) > 0){ p->left = insertNode(p->left, x); }else if(strcmp(p->moji, x) < 0){ p->right = insertNode(p->right, x); } return p; } void printTree(NODE *p){ if(p == NULL) return; printTree(p->left); printf("%s\n",p->moji); printTree(p->right); } int main(int argc, char *argv[]){ FILE *fp; char *buf, *ans; NODE *p = NULL; if( argc > 2 ){ printf("ファイルの指定は一つだけです。\n"); return -1; }else if(argc == 1){ printf("ファイルを指定してください。\n"); return -1; } fp = fopen( argv[1] , "r" ); if( fp == NULL ){ printf("ファイル読み込みに失敗しました。\n"); return -1; } while((buf = malloc(MAX + 1)) != NULL && fscanf(fp,"%" TO_STRING(MAX) "s",buf) == 1){ /* fscanf(fp, "%32s", buf) としてバッファサイズを考慮する */ const char puncts[] = "-,."; /* 空白類は %s で除かれるので不要 */ for (ans = strtok(buf,puncts); ans != NULL; ans = strtok(NULL,puncts)) p = insertNode(p, ans); } printTree(p); fclose(fp); return 0; }

関連するQ&A

専門家に質問してみよう