メモリについての疑問

このQ&Aのポイント
  • メモリについてご質問します。char *p; p = (char *)malloc(100); とすればpに100バイトのメモリが割り当てられる・・pに文字列を代入する場合100バイトまで格納可能である。
  • ファイルからの一行のある部分の文字列を入れる場合、sについてもメモリを取得しなければなりません。その際、whileの外でメモリを取得するのか、whileの中でメモリを取得するのかどちらが適切でしょうか?
  • while文の中でメモリを作成すると、1回ごとに新たなメモリをとっているのか、それとも更新されていているのかがわかりません。
回答を見る
  • ベストアンサー

メモリ

メモリについてご質問します。 例えば char *p; p = (char *)malloc(100); とすればpに100バイトのメモリが割り当てられる・・ pに文字列を代入する場合100バイトまで格納可能である。 次にファイルからの一行のある部分の文字列を入れる場合 char *s; while(fgets(buf,1000,fp) !=NULL){ s = GetWord(・・)//何らかの文字列が返ってくる関数です とする場合このときのsについてもメモリを取得しなければなりません。 その際 s = (char *)malloc(100); while(/*省略*/){ とwhileの外でとるのか、それとも while(/*省略*/){ s = (char *)malloc(100); と中でとるべきなのかどっちでしょう? というのもwhile文の中でメモリを作成すると 1回ごとに新たなメモリをとっているのか 更新されていっているのかがわかりません。

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

  • ベストアンサー
回答No.3

ちょっと話がずれますが、 s = (char *)malloc(100); と、 s = GetWord(・・)//何らかの文字列が返っ てくるは(もしもこの通りなら)連続して 使ってはいけません。 C/C++には、文法的には、文字列とい う型はなくて、多くの場合、char * という、 ポインタです。(string の場合もある) ですから、GetWord() は、char *GetWord(); とchar * を返すと思いますが、そうすると、 s = (char *)malloc(100); で、確保した領域(の先頭)をセットしても、 s = GetWord(); とした瞬間、malloc() で確保した領域は永 久にアクセスできなくなります。 ついでにいえば、この状態で、 free(s); とすると、良くないことが起こるかもしれま せん。(GetWord() の中で、malloc() してい たらOK、GetWord の static な領域を使っ ていたらNG) もしくは、 s = (char *)malloc(100); した領域に、strcpy(); などで、コピーする 必要があります。 さて、 s = (char *)malloc(100); がループの中か外かは、 「ひとつ前のループの時、s に代入されたポ インタは、どうなるか?」で決まります。 1回のループ毎に、どこかに、ポインタその ものが保存されたりして、ひとつ前のループ の時のポインタがを保持しておく必要がある なら、ループの中で毎回確保する必要があり ます。 ひとつ前の s に入っていた内容が、上書き されてもいいなら、ループの外に置いておけ ばいいでしょう。 もしかして、 最初、 char s[100]; で作っていたら、 s = GetWord(); でコンパイラに怒られたので、 char *s; に変えてみた。 ということなら、上述の通り ・事前に s の領域を確保する必要はない  (GetWord() 内部で確保された領域を   流用すればいい) ・strcpy で GetWord() の返却値を  コピーする必要がある のどちらかでしょう。

その他の回答 (3)

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

>このときのsについてもメモリを取得しなければなりません。 必ずしもそうとはいえません。 GetWordがchar型へのポインタを返すのであれば、 sのためにmallocする必要はありません。

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.2

何か認識が違う気がします。 >pに100バイトのメモリが割り当てられる プログラム領域以外のメモリはシステム管理領域(ヒープと言う)で、 そこから100バイトのメモリが割り当てられます。mallocの戻り値は その領域のアドレスであって、ポインタ型(極端に言えばlong型)なら どんな変数に入れて使用してもかまいません。 あくまで、「pに」ではありません。 >s = GetWord(・・)//何らかの文字列が返ってくる 返ってくる文字列は誰が用意したメモリ上にあるものですか? 呼び出し元が用意した領域を返すなら、ループの外側で定義して、 使い回しをする方が効率的です。関数自体が領域を確保しているなら ループの終わりで、毎回freeしなければなりません。 >while文の中でメモリを作成すると mallocの度に新しいメモリが確保されます。解放しないで、mallocを 繰り返すと、ヒープをどんどん消費してしまいます。 更新されるのではありません。 >すると残りは90バイトでしょうか 何処に何バイト読み込むか指令するのはプログラマの責任です。 使用した部分だけ有効なのであって、「残り」を気にするのは 何か重大な勘違いをしていると思います。 ファイルの1行が最大99バイトまでなので100バイトの領域を確保した というのが正しい考えで、1行読み込む度に有効長を調べながら処理 するのが正しい態度です。

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.1

一回取った領域を使い回すならループの外で、ループのたびに新しい領域を使うならループの中で。 なお、どちらの場合も確保した領域は必要なくなったらfreeで開放しなければいけません。

minaraiH
質問者

補足

使いまわすとありますが例えば100バイトとって 最初の一行で10バイトを使用した すると残りは90バイトでしょうか?

関連するQ&A

  • 配列のメモリの確保

    先日メモリについてご質問させていただいたものですが、 今ファイルから読み込んだ文字列を配列に格納する作業を行なっています。 今は char buf[1000]; FILE fp; if((fp=fopen("○○.txt","r")) ==NULL){ printf("ファイルが開けません"); } while(fgets(buf,1000,fp) != NULL){ としてファイルを一行ずつ読み込んでその後単語ごとに配列に組み込みます このときファイルの文字列を格納する配列はbuf[1000]ですが このメモリでは足りないかもしれませんし多すぎるかもしれません。 足りない場合はエラーになるし多すぎる場合はメモリの無駄ですよね。 このような場合はメモリを取り直すべきなのでしょうか?その場合 どのような方法がありますか?調べてもint型の領域確保とかそういうのはあるんですがファイルから読み込んだ文字列の領域確保とかは見つからなかったので教えて下さい。

  • メモリ

    #include "stdafx.h" #include <ctype.h> #include <string.h> #include <stdlib.h> int check(int a[100], int n); typedef struct { char number[6]; char class_type[20]; char name[8]; char subject[5]; } my; my data[100]; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char bufG[1111]; int i; if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf,1000,fp) !=NULL){ str=buf; while(*str != '\0'){ if(*str != ','){ for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; switch(field){ case 0: strcpy(data[line].number, bufG); break; case 1: strcpy(data[line].class_type, bufG); break; case 2: strcpy(data[line].name, bufG); break; case 3: strcpy(data[line].subject, bufG); break; } field++; } else{ str++; } } line++; field = 0; } int p, q; int a[100]; int u = 0; for(p = 0; p < line; p++){ for(q = 0; q < line; q++){ if(strcmp(data[p].class_type, data[q].class_type) == 0 && strcmp(data[p].subject, data[q].subject) == 0 && p != q ){ //処理 } } } } fclose(fp); return 0; } 先日文字列入れ替えについてご質問したものですが メモリの取り方についてご質問します。 先日このプログラムにおいて my data[100]と固定してるのはいけないという意見をもらったので メモリを取得しようと思ってるのですが できればdata[i].○○の形でアクセスしたいのでこのままの形は あまりかえたくないです。この場合 while(fgets(buf,1000,fp) !=NULL){ str=buf;     int len = strlen(buf); my *o; o = (my *)calloc( len + 1, sizeof(my *)) while(*str != '\0'){ としてみたのですがこれは実際どうなのでしょうか? NULLは帰ってきてないみたいなので割り当ては出来てるとは思うんですが この一行の文字列の大きさにぴったり合うメモリを割り当てたいのですが ちゃんとなっているか調べる方法を教えて下さい。

  • ファイルの読み込みとメモリ確保について。

    ファイルから文字を読み込んで それを配列に入れて辞書順にソートさせようとしています。 それで、ソート以前の問題なのですが、ファイルから文字列を読み込んで配列にいれようとするのですが、 buffを動的にメモリ確保してその配列に入れたいと考えているのですが、なぜか入ってくれません。 whileでファイルの終わりがくるまで一行ずつ読み込んで それをsに入れていき、sをbuff[]の配列に順番にいれていこうとしているのですが・・・。 ファイルは aaaa aabc dda wer zie ced sdfe be など適当な文字の並びです。 malloc関数で動的に確保したメモリはその後普通の配列と同様に使えるのではなかったのでしょうか? なので普通にbuff[i]=s;といった処理で入れれると思ったのですが。 ファイルは一行の長さの最大が100で 行数が4000行あると仮定しています。 今は小さいファイルでテストしていますが。 以下ソースです。 #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 #define MAX_LINE 4000 main() { FILE *fp; char *buff,s[MAX_SIZE]; int i; fp=fopen("words.txt","r"); buff=(char*)malloc(sizeof(char)*MAX_LINE); i=0; while(fgets(s,MAX_SIZE-1,fp)!=NULL){ buff[i]=s; printf("%s",buff[i]); i++; } fclose(fp); } とりあえずファイルの内容を配列に入れないとソートできないので、配列に全て入れてしまいたいと考えています。 間違いがどこにあるのか指摘よろしくおねがいします。m(-_-)m

  • fgets関数を使用したときの文字あふれについて

    fgets関数を用いて文字列を入力し、その長さを測るプログラムを作っています。 #include <stdio.h> #include <string.h> #define MAX 256 int main ( int, char *[] ); int main ( argc, argv ) int argc; char *argv[]; { char buf[( MAX )]; while ( 1 ){ memset ( buf, 0, sizeof( buf )); fgets ( buf, MAX, stdin ); if( fgets == NULL ){ break; } printf("入力した文字列の長さは%dです\n" ,strlen( buf )); } return 0; } このプログラムでは、256までしか文字列の長さを測ることができません。 もしこのプログラムで256を超える文字列を入力してしまうと、文字のあふれが発生し、 「入力した文字列の長さは256です」 「入力した文字列の長さは(あふれた文字列の長さ)です」 とこのようになってしまいます。 このプログラムで256以上の文字を読み捨てて、 「入力した文字列の長さは(あふれた文字列の長さ)です」 を表示しないようにできるのでしょうか? また読み捨てた文字列の長さを知ることはできるのでしょうか? もしかしたらfgets関数を使用すると不可能なのではないか?と思っています。 分かる方が居ましたらどうか教えて下さい。 よろしくお願いします。

  • C言語におけるfgetsを用いたループ処理について

    C言語において、文章を読み込むためにfgetsを用いて下記のプログラムを書いたのですが、*において入力を受け付けなくなります。 これを解消する方法はないでしょうか? ちなみにコンパイラはBBC、開発環境はVistaです。 なお、簡略のため#include,main等は省略しています。 //以下プログラム #define SIZE 16384 char moji[SIZE] = {""}; char buf[SIZE]; //EOF(^Z)になるまで、文字列を受け取る while(fgets(buf, sizeof(buf), stdin) != NULL){ if(sizeof(moji) < strlen(moji) + strlen(buf)) break; strcat(moji, buf); }; getchar(); //* //プログラムここまで

  • 続jファイルに文字列を書く

    あれから後一歩と言うところにきました たぶんmallocのバグだと思いますがチャットのシステムを作ろうとしているのですが 読み込み時にエラーになります ソースの注目部分を見てほしいのですが、 注目部分はbuf+1 にすると 文字列が1文字ずつ消えていくバグになり bufにすると 3行目を書き込んだ時点で3行目がの頭の部分の文字列がおかしくなり4行目を書き込もうとするとエラーになります ちゃんと動作するにはどのように書けば良いですか? ---ソース--- #include <stdio.h> void main(void){ FILE *fp; char *tm[1000]; char buf[400]; int i=1,sei; fp= fopen("now.txt","w+"); fprintf(fp,"もも"); fclose(fp); //何で最初に書き込んでるんだ? //という突っ込みがあるでしょうが本当に作りたいプログラムは最初にファイルに書き込まないといけないためです。 fp= fopen("now.txt","r"); while( fgets( buf, 400, fp ) != NULL ){ tm[0]=(char*)malloc(strlen(buf)+1); strcpy(tm[0], buf); } fclose(fp); fp =fopen("moto.txt","r"); while( fgets( buf, 400, fp ) != NULL ){ tm[i] = (char*)malloc(strlen(buf+1)); strcpy(tm[i], buf+1); //ここを注目 if(i<999){ i++; } } fclose(fp); if(i<=1000){ sei=i; } else{ sei=1000; } fp =fopen("moto.txt","w"); for(i=0;i<sei;i++){ if(i==0){ fprintf(fp,"%s\n",tm[0]); } else{ fprintf(fp,"%s",tm[i]); } } } ---now.txt--- もも ---moto.txt--- オレンジ みかん

  • 配列を返す

    ファイルから読み込んだ一行の文字列を読み込みカンマごとに区切って 返すというプログラムを関数化することで効率を図りたいと思います。 int main() { char buf[1000]; char *str; char *bufG; //ファイルを読み込む  while(fgets(buf,1000,fp) != NULL){//一行ずつ読む str = buf;//先頭アドレスを指す     bufG = //文字列を返す関数  ・  ・  ・ } } //文字列を返す関数 {    for(i = 0; *str != ',' && *str != '\0'; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; return bufG; } 前の質問で自動変数でこの関数を抜けたら廃棄になるというのは わかったんですが(そういう警告がでました) ここからどのようにすれば求めるプログラムになりますか? 引数とかちょとわからないので関数定義を書きませんでした。 (1)ファイルをよみこむ (2)一行ずつ読み込み文字列をbufにいれる (3)ポインタstrをbufの先頭アドレスにする (4)get_word関数にてポインタをずらしていき カンマがあればそこまでの文字列を返す (5)main関数に戻り変数に代入する (6)終端文字があるまで(4)ー(5)を繰り返す。 (7)さらに行数分繰り返す これらの一連の流れをやりたいのですが わかりません。

  • ファイルを読み込むプログラムについて

    下のプログラムで分からない所がありますので、教えて頂ければと思います。宜しくお願い致します。 text = fgets(buf,256,fp);はfpのファイルから一行を読み込んでbufに格納するという処理ということは分かります。でも、while文内なので次にこの処理をする時に今度は、2行目(下の段)を読み込むはずですが、プログラム中のどこに2行目に移動させる処理があるのか分かりません。 予想ですが、text = fgets(buf,256,fp);の中にそのような意味の処理が含まれているのでしょうか? どなたかご教授お願い致します。 #include <stdio.h> int main(void) { FILE *fp; char buf[256]; char *text; char flname[256]; printf("ファイル名:"); gets(flname); fp = fopen(flname,"r"); do{ text = fgets(buf,256,fp); if(text != NULL){ printf("%s",text); } }while(text != NULL); fclose(fp); return(0); }

  • C言語の課題で困っています;

    C言語の課題で困ってます; 学校の課題で、キーボードから文字を入力する(最大80文字)。入力された文字列と、入力した文字列を逆順にした文字列を表示する。(malloc,freeを使って作成して下さい) ヒントで #invlude <stdio.h> void main(void){ char *buf; //入力文字列用 char *seq; //入力文字列用コピー用 char *rev; //逆順文字列用 int lec, i; buf =(char*)malloc(81); printf("文字列を入力:"); scanf("%s"buf ); for(i = 0; buf[i] ??? '\0'; i++){ } Ien = i; /* lenに文字列の長さが入る */ seq = ???(??? + 1); /* len+1文字文確保*/ for(i = 0; ???; i++){ seq[0] = buf[0]; } free(buf); rey = ???(len + 1); for(i = 0; < len; i++){ rev[len - i - 1] = seq[i]; } ren[i] ~ '\0'; printd("入力文字列 : %s\n",sep); でたんですが、全然分からなくて足りない部分の答えを教えてもらえると助かります;

  • プログラミング(関数reverseを作る)

    プログラミングの勉強会で文字列を反転させる関数(例:ABCDE→EDCBA)を作れという課題が出たのですが、以下のように書いたきり進みません。あと、何を書けばいいのでしょうか?教えてください。 #include <stdio.h> void reverse(char *); void reverse2(char *); void main(){ char buf[10]; printf("str :"); fgets(buf, 10, stdin); reverse(buf); printf("rev :%s", buf); return; } //文字列を反転させる関数 void reverse(char *s){ return; }

専門家に質問してみよう