- ベストアンサー
戻り値の取得が出来ません
- ファイルを抽出するプログラムを作成しています。
- 関数の中で検索処理を行い、ファイルパスを返そうとしたのですが、関数の呼び出し先で値が取れなくなってしまいました。
- 当方JAVA経験はあるものの、ポインタなどもまだ把握し切れていないC初心者なので、不勉強で申し訳ないですが、ちょっと急ぎの用事のため、質問させて下さい。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
>char* SearchPastFile(CString strFolder,int imageFlag,char transTime[15]); って事は、SearchPastFileは「どこか、文字列が入ってるメモリの、先頭アドレスを返す」って事です。 この「どこか、文字列が入ってるメモリ」は、SearchPastFileを抜け、mainに帰って来た時も「消えずに残っている必要がある」のです。 その為には、 ・SearchPastFileの中でmallocして、mallocした領域に文字列をコピーし、mallocした領域の先頭アドレスを返す ・mainで領域を確保し、SearchPastFileの中で、その領域にコピーしてもらう などの方法を取らなければなりません。 方法1 char *SearchPastFile(CString strFolder,int imageFlag,char transTime[15]); void main( void ){ char *prevFile; // 転送元ファイル名 prevFile = SearchPastFile(cTransPath,iImageFlag,transTime); // 過去ファイルの取得【現状NULL】 MessageBox(NULL,prevFile,"パス",MB_OK);【←(確認用)空の状態】 if (prevFile) { free(prevFile); // prevFileが指す領域は、SearchPastFileの中でmallocされたので、使用後に必ず開放する } } **関数** char *SearchPastFile(CString strFolder, int imageFlag, char transTime[15]){ CFileFind FileFind; // すべてのファイルを検索します CString strSearchFile = strFolder + _T("\\*.*"); if(!FileFind.FindFile(strSearchFile)) { Log("ファイルが見つかりませんでした。"); return NULL; } char *p; // ファイルパス char *mp; // 戻り値格納用 BOOL bContinue = TRUE; while(bContinue){ (検索処理中略) // 24時間前のファイル if(imageFlag==1 && spanDays==-1){ Log("ファイルが見つかりました。"); MessageBox(NULL,p,"パス",MB_OK);【←(確認用)ここではパスが取れている】 mp=malloc(strlen(p)+1); // 戻り値返却用の領域を確保 if(!mp) { Log("メモリが確保できません。"); return NULL; } strcpy(mp,p); // 戻り値返却用の領域に戻り値をコピー return mp; // 48時間前のファイル } else if(imageFlag==2 && spanDays==-2){ Log("ファイルが見つかりました。"); mp=malloc(strlen(p)+1); // 戻り値返却用の領域を確保 if(!mp) { Log("メモリが確保できません。"); return NULL; } strcpy(mp,p); // 戻り値返却用の領域に戻り値をコピー return mp; } } }; return NULL; } 方法2 char* SearchPastFile(CString strFolder,int imageFlag,char transTime[15],char *strResult); void main( void ){ char Result[MAX_PATH]; char *prevFile; // 転送元ファイル名 prevFile = SearchPastFile(cTransPath,iImageFlag,transTime,Result); // 過去ファイルの取得【現状NULL】 MessageBox(NULL,prevFile,"パス",MB_OK);【←(確認用)空の状態】 } **関数** char* SearchPastFile(CString strFolder, int imageFlag, char transTime[15],char *strResult){ CFileFind FileFind; // すべてのファイルを検索します CString strSearchFile = strFolder + _T("\\*.*"); if(!FileFind.FindFile(strSearchFile)) { Log("ファイルが見つかりませんでした。"); return NULL; } char *p; // ファイルパス char *mp; // 戻り値格納用 BOOL bContinue = TRUE; while(bContinue){ (検索処理中略) // 24時間前のファイル if(imageFlag==1 && spanDays==-1){ Log("ファイルが見つかりました。"); MessageBox(NULL,p,"パス",MB_OK);【←(確認用)ここではパスが取れている】 if(strlen(p) >= MAX_PATH) { Log("パスが長過ぎます。"); return NULL; } strcpy(strResult,p); // 戻り値返却用の領域に戻り値をコピー return strResult; // pが指す領域はreturnしたら消滅する // 48時間前のファイル } else if(imageFlag==2 && spanDays==-2){ Log("ファイルが見つかりました。"); if(strlen(p) >= MAX_PATH) { Log("パスが長過ぎます。"); return NULL; } strcpy(strResult,p); // 戻り値返却用の領域に戻り値をコピー return strResult; // pが指す領域はreturnしたら消滅する } } }; return NULL; }
その他の回答 (5)
pはポインタですので、実態はpが指しているアドレスの先にパスの文字列のデータがある訳ですが、この文字列のデータが関数内の自動変数に格納されていると関数を抜けるときに破棄されますので、pが指す先のデータは関数を抜けた時点で無くなります。 ってのが原因な気がします。 (検索処理中略)で何をやっているのかがわからないのですが、 勝手な想像をすると、CString型の変数にパスの文字列が入っていてその文字列へのアドレスをpに代入しているとか? おそらく、手っ取り早い解決法は可能で有れば関数の戻り値の型をCStringにする。 その他はmallocでメモリを確保して文字列をそのメモリ内にコピーして、そのアドレスを返すとか、 関数内にstaticなchar型配列を作ってそこに文字列をコピーして、その配列へのアドレスを返す等。
- yuu_yuu
- ベストアンサー率41% (34/81)
#2です。 #3のasuncion様に指摘を受けて、気が付きました^^; 開放されるのは、アドレスが入っている領域ですね。。。 勘違いとは言え、嘘をついてしまいました。申し訳ありません。 asuncion様、的確なフォローありがとうございます。 で、、、 >>(検索処理中略) 内に記述されていると思いますが、char *p;に設定している charの実体がどのように宣言されているのか、気になります。 そこに答えが隠れているように思います。 以上です
- asuncion
- ベストアンサー率33% (2127/6290)
> その開放されてしまう、変数のポインタを関数の外で参照している 関数内のローカル変数のポインタを、その関数の外で参照しているわけではありません。 SearchPastFile()の中のpに入っているのは、どこかを指しているという「値」です。 変数のポインタではなく、ポインタ変数の値です。
- yuu_yuu
- ベストアンサー率41% (34/81)
はじめまして。 >>char *p; // ファイルパス は内部変数です。内部変数は、その関数が終わると開放されます。 その開放されてしまう、変数のポインタを関数の外で参照しているので 起きている現象と思われます。 MessageBox関数を使用しているところを見ると、 マイクロソフトのC++でデバッグ実行している最中起きる現象と思ってよいでしょうか?? ここからは、うろ覚えなのですが、デバッグだと変数の初期クリアが自動で行なわれると 記憶してます。コンパイルして実行すると、ゴミが表示されたような気がします。 外していたら、すみません^^;
- ww-_-ww
- ベストアンサー率51% (46/89)
こんにちわ。 >prevFile = SearchPastFile(cTransPath,iImageFlag,transTime); // 過去ファイルの取得【現状NULL】 のところで文字列の代入を行ってるからじゃないですか? strcpy()を使えばできるのでは?