• ベストアンサー

文字列の引数を元に名前を変えて返す関数

基本名と拡張子名と番号を引数として、連番ファイル名の文字列を返す関数を作っています。 例えばfor文で10回ループさせる場合、Name1に"画像"、Name2に".jpg"、Numにiを渡せば、文字列"画像00.jpg"~"画像10.jpg"が返ってくるという仕組みです。しかし、試行錯誤してもポインタの仕組みが根本的に理解できてないようなので、下に示すコードの修正と解説をお願いしてもよろしいでしょうか。ちなみにこのコードではstrcatの部分でエラーが起きます。 char FileRename(char *Name1,char *Name2,int Num) { char *FileNumber[100]; FileNumber[0] = "00"; FileNumber[1] = "01"; FileNumber[2] = "02"; FileNumber[3] = "03"; FileNumber[4] = "04"; FileNumber[5] = "05"; FileNumber[6] = "06"; FileNumber[7] = "07"; FileNumber[8] = "08"; FileNumber[9] = "09"; FileNumber[10] = "10"; FileNumber[11] = "11"; FileNumber[12] = "12"; FileNumber[13] = "13"; FileNumber[14] = "14"; FileNumber[15] = "15"; char *str; str = Name1; char *add = FileNumber[Num]; strncat(str,add,2); add[30] = *Name2; strncat(str,add,strlen(Name2)); return *str; }

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

  • ベストアンサー
  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.4

> char *FileNumber[100] = { #3では見落としてましたが、一般的に配列を初期化付きで宣言する場合は要素数は指定しません。書かれている要素の分だけ自動的に確保されるためです。 まぁ処理そのものに影響はしませんが。 char *FileNumber[] = { ... }; で、本題ですが。 #3を書いたときにはうっかりしていたのですが、現在のコードでは return result; で警告が出ていませんか? 自動変数の中身は関数を抜けたあとは保証されないので、実は char result[30]; では駄目(動いてしまう処理系も多いのが厄介)で、 static char result[30]; として静的変数にするか、もしくはこれも関数引数として呼び出し元から渡す形にするのが正しい形です。 #一応関数内部で動的確保する選択肢もありますが、関数内部で動的確保するやり方は不具合の温床になりやすいのでここでは除外します。 使われ方を見る限りだとstatic char result[30];が楽そうですが、これでも駄目な場合は一度戻り値の文字列が正常か確認してみてください。

sanato
質問者

お礼

完璧です。 その回答がなくてはいつたどり着けるか分からなかったと思います。 これからも精進させていただきます。的確な回答ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.3

「ポインタの仕組みが根本的に理解できていない」という自覚があるのであれば、まずは理解できるようになりましょう。 ポインタを利用した文字列操作は若干応用寄りなので基本固めをしてからでも遅くはありません。 「2桁の任意の数値を加えたファイル名を返す」ということなら#1の方法(sprintf())が簡単ですが、それはとりあえず置いておいて。 > char FileRename(char *Name1,char *Name2,int Num) 戻り値で変更後のファイル名(文字列)を渡すことを期待しているはずなのに型がcharではまずいですね。char *にしましょう。 char *FileRename(char *Name1,char *Name2,int Num) > char *str; > str = Name1; > char *add = FileNumber[Num]; > strncat(str,add,2); 止まるのはここでしょうが、 char *str = "画像"; strcat(str, FileNumber[Num]); ができないのと全く同じで、書き換えてはいけないメモリを書き換えようとしているためです。 詳しく説明するのはめんどいので「文字列リテラル」について調べてください。 これは処理用のバッファを作って対処します。 char result[30]; strcpy(result, str); strcat(result, FileNumber[Num]); > add[30] = *Name2; > strncat(str,add,strlen(Name2)); なぜ唐突にadd[30]なのかが不明ですし、その後も何をやっているのかが不明です。また確保されていないadd[30]を使おうとする事によりほぼ確実に動作異常が発生します。何もおきなかったとしてもそれはたまたまに過ぎません。 strcat()の意図を汲むとしても、ここは普通に strcat(str, Name2); だけでいいはずです。 もっともこれでは前で指摘していることと全く同じ結果になるので、前段と併せて strcat(result, Name2); となります。 > return *str; 最初でも触れてますが「文字列の先頭の文字」だけ返しても意味がありませんよね?文字列の先頭アドレスを返します。 return result; とりあえずこれだけ変更すれば元のコードでも動作はするはずです。 あとはNumの閾値チェック(0~15)を忘れずに。

sanato
質問者

お礼

詳しい説明付きでどうもありがとうございます。 おかげさまでコンソールアプリでは成功したんですが、ウィンドウズアプリで独自の画像読み込み関数の引数(const char* pFileName)に渡すとなぜか上手く表示されません。これはこの関数ネイティブの問題と見てよろしいでしょうか。 現状のリネーム関数を示します。 char* FileRename(char* Name1,const char* Name2,int Num) { char *FileNumber[100] = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15" }; char *str; str = Name1; char result[30]; strcpy(result, str); strcat(result, FileNumber[Num]); strcat(result, "."); strcat(result, Name2); return result; } 今までは画像の読み込みに テクスチャ[0] = CreateTextureFromFile("画像00.jpg"); テクスチャ[1] = CreateTextureFromFile("画像01.jpg"); このような形で行っていたので、現在はforループにより テクスチャ[i] = CreateTextureFromFile(FileRename("画像","jpg",i)); こうしています。 何か根本的な要因があればご教示いただけると有難いです。

全文を見る
すると、全ての回答が全文表示されます。
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.2

string.h をインクルードする必要はなかったですね。 先ほどの例を参考にして、FileRename関数を作ってみてください。

全文を見る
すると、全ての回答が全文表示されます。
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

ちょっとした例です。 なお、00~10の分だけループするのであれば、10回ではなく11回です。 #include <stdio.h> #include <string.h> int main(void) { char Filename[40]; int i; for (i = 0; i <= 10; i++) { sprintf(Filename, "画像%02d.jpg", i); printf("%s\n", Filename); } return 0; }

sanato
質問者

お礼

回答ありがとうございます。 なるほどポインタを使わなくてもこんな簡単にできるんですね。 今後の参考にさせていただきます。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 文字列の連結

    ポインタ変数で宣言された3つ以上の文字列を連結したいのです。 そこで char *str1 = "Hello,"; char *str2 = "Mr."; char *str3 = "Brown."; char msg[100]; strcat(msg,strcat(str1,strcat(str2,str3))); printf(msg); としたがやっぱり駄目でした。 strcat(str2,str3)からして駄目なんだとはなんとなくわかるのですが どうしたら解決できるのかわかりません。 結果的には printf(msg); ->Hello,Mr.Brown. としたいのです。解決案をご教授いただけないでしょうか。 お願いいたします。

  • 文字列に関する関数

    現在C言語の勉強をしております。 そこで、以下の関数の作成について質問させてください。 【関数の仕様】 引数の文字列から、'-'(ハイフン)と'P'以降を排除した文字列を返す。 自分なりに作成してみたのですが、コンパイルで警告が出てしまう状況です・・・。 もっとスマートに書けるんだろうとは思っているんですが、精一杯でした・・・。 どなたか教えていただけませんでしょうか? char *getDelStr(char *str) { int len = strlen(str); int count; char targetStr[32]; for(count = 0; count < len; count++){ if(str[count] != 'P'){ if(str[count] != '-'){ strcat(targetStr,str[count]); } }else{ return targetStr; } } return str; } 以上、よろしくお願いいたします。

  • strcat関数

    学校の課題で strcat関数と全く同じ働きをするmy_strcatを実装せよ という課題がでています。 strcatは char* strcat(char *dest, const char *str) で表され、文字列 strを文字列 dest に合成して 合成された新しい文字列として dest を返します。 例えば、dest = Japan, str = Korea だったら, 関数処理後に、 dest = JapanKorea を戻り値とします。 ********************************************* my_strcat実装について 実装段階で一番の問題になるのが、文字列のサイズです。 とりあえず、私の書いたコードを示します↓ char* my_strcat(char *dest, const char *src) { int i=0; int j=0; while(*dest) { dest++; i++; } while(*src) { *(dest+i) = src[0]; i++; src++; } *(dest+j) = src[0]; //put null at the end of dest return dest; } 試しにdest=Japan,str=Koreaでやってみたのですが、動きませんでした。 原因はdest の文字サイズを無視した無理やりなりな実装だと考えます。 C言語では文字のサイズを一度宣言したら、変えられないと思うので、困っています。 どなたかアドバイスをいただけないでしょうか。 よろしくお願いします

  • 文字列をうまく返してくれない

    数値を文字列として呼び出し元に渡し、呼び出し元で文字列を数値に変えようとしたのですがatoi関数(strtolを使うと最初の文字のみ帰ってくるため2桁以上の数値に対応できない)を使うとうまく行きませんでした。 どのように変更したらatoiが使える文字列になりますか? #include <stdio.h> #include <stdlib.h> static struct{   char *name; }kuda[5]={   { "もも" , "りんご" , "みかん" , "バナナ" , "パイナップル" } } char *re_3( void ){   int a = 3;   char str_h[100];   char *str;   sprintf_s( str_h , 100 , "%d" , a );   *str = *str_h; //原因はおそらくここ   return str; } void main( void ){   printf( "%s" , kuda[ atoi( re_3() ) ].name ); }

  • 文字列を引数にしたがって置換するプログラムを作りました。

    文字列を引数にしたがって置換するプログラムを作りました。 test.txtを新規作成、abcdefghijklmnopqrstuvwxyz を書き込みセーブ 引数 : abc=zz mnopq=u - 出力結果 - zzdefghijklurstuvwxyz というような結果になるプログラムを作ったのですが、これをstr系とmem系の関数を使わずにポインタを使って組みなおしたいと思うのですが、全くわからないので質問させて頂きました。 よろしくお願いします。 質問下手なので質問でダメな点があれば随時補足していきたいと思います。 #include"stdafx.h" #include<stdio.h> #include<string.h> #include<stdlib.h> #define BUF 128 #define MOJI 128 #define MAX 128 #pragma warning(disable : 4996) using namespace System; int main(int argc, char *argv[]) { FILE *fp; char txt[BUF]; char hiki_mae[MAX][MOJI]; char hiki_ato[MAX][MOJI]; int i = 0, n = 0, j = 0; int hiki_num = 0; char txt_mae[BUF], txt_ato[BUF]; char *p; char sagyou_txt[BUF], sagyou_argv[MAX][MOJI]; if(argc < 2){ printf("argc = %d >>> パラメータ不足です\n", argc); exit(1); } if( (fp = fopen("test.txt", "r")) == NULL ){ printf("ファイルがオープンできません\n"); exit(1); } for(i = 1; i < argc; i++){ if( strchr(argv[i], '=') != NULL && strlen(argv[i]) > 2){ strcpy(sagyou_argv[hiki_num],argv[i]); p = strstr(sagyou_argv[hiki_num],"="); *p = '\0'; strcpy(hiki_mae[hiki_num], sagyou_argv[hiki_num]); strcpy(hiki_ato[hiki_num], sagyou_argv[hiki_num] + strlen(hiki_mae[hiki_num]) + 1); hiki_num++; } } while( fgets(txt, BUF, fp) != NULL){ printf("変換前>%s\n",txt); } for(n = 0; n < hiki_num; n++){ while( strstr(txt, hiki_mae[n]) != NULL ){ strcpy(sagyou_txt, txt); p = strstr(sagyou_txt, hiki_mae[n]); *p = '\0'; strcpy(txt_mae, sagyou_txt); strcpy(txt_ato, sagyou_txt + strlen(txt_mae) + strlen(hiki_mae[n])); strcat(txt_mae, hiki_ato[n]); strcat(txt_mae, txt_ato); strcpy(txt, txt_mae); } } printf("変換後>%s\n",txt); fclose(fp); return 0; }

  • 文字列について

    適当な文字列をキーボードから入力し、次に別の適当な整数numをキーボードから入力する。次に先に入力した文字列のnum番目からnum個の文字だけ逆順になるように文字列を並び替えた文字列を新たな文字列変数に代入し、その結果を画面に出力するプログラムを下記で作成したのですが、文字列時代が逆になってしまいます。どうしたら、 結果    文字列を入力      My name is Taro Sandai.    整数を入力     10    My name isdnaS oraT になるのですか? import java.io.*; class mojiretu4 { public static void main(String args[]) throws IOException { System.out.println("文字列を入力"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str1 = br.readLine(); System.out.println("整数を入力"); String str2 = br.readLine(); int num = Integer.parseInt(str2); StringBuffer sb = new StringBuffer(str1); sb.reverse(); System.out.println(sb);

    • ベストアンサー
    • Java
  • C言語での文字列ソート動作について

    任意の文字列を入力し、その文字列を昇順にソートするプログラムを作ったのですが、入力する文字の文字数が大きく異なると期待した結果が得られません。 文字数が少なくなったり、他の配列の文字が混ざったりと言う結果に成ってしまっています。 何が原因か分からない状態です。 以下にサンプルを記載させて頂きますので、助言よろしくお願いします。 /*----------------------------------------- 入力例 CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC BBBBBBBBBBBBBBBB AAAAAA -----------------------------------------*/ #include <stdio.h> #include <string.h> #include <stdlib.h> void swapc(char *cx , char *cy){ char tmp[100]; strcpy(tmp, cx); strcpy(cx, cy); strcpy(cy, tmp); } int main(){ char *num[100]; char str_tmp[100]; //文字列一時格納 int moji_cnt; //入力した文字列のカウント int n , m; // 文字列入力処理開始 printf("文字列を入力してください\n"); for( moji_cnt = 0 ; moji_cnt != 3 ; moji_cnt++){ scanf("%s", str_tmp); *(num+moji_cnt) = (char *)malloc(sizeof(char) * (strlen(str_tmp)+1)); //メモリ確保 strcpy(*(num+moji_cnt), str_tmp); } puts("\n"); // 文字数ソート処理 for(n = 0 ; n < moji_cnt-1 ; n++){ for(m = 1 ; m < moji_cnt-n ; m++){ if(strcmp(*(num+n) , *(num+n+m)) > 0){ swapc(*(num+n) , *(num+n+m)); // 文字列入れ替え } } } puts("\n"); for(n = 0;n != moji_cnt;n++){ printf("%s\n" , *(num+n)); } free(num); }

  • (C言語)関数の中で文字列比較できない。

    全体のソースコード省略させていただきます。 問題のある点だけあげたいと思います。 あるstr型:"初恋の人からの手紙" その文字列から助詞にあたるものを取得したいとする。 Phrase p_load(Phrase *p, char *str){ ....「省略」 str->particle[n] = get_jyoshi(js);//助詞番号取得 1。 printf("助詞:%d,jyoshi:%d\n", str->particle[n],get_jyoshi(js)); ===>>>get_jyoshiの関数はこんな感じです。 int get_jyoshi(char* js){ int num; if(strcmp(js,"の")==0){ return num = 1;} if(strcmp(js,"からの")==0){ return num = 2;} .......「省略」 else return 0; } 1。と書いてあるところに助詞の番号を表示しようとしたら助詞番号は"0"、つまりget_jyoshiの関数で文字列比較するときに失敗ということですね。。余談ですが、作ってるソースコードけっこう大きめですいくつかの再利用ソースコードと依存してます。そのため、試しで助詞番号を取得するための簡単な単体プログラムを作りました。そしたら、うまく行きましたが。問題はなんなんでしょうか?さっぱりわからないです。ご教授よろしくお願いします。

  • 文字列関数をうまく表示させたい

    今、文字列関数をしています。参考書通りにしたのですが、ブラウザでは思い通りに表示されません。 <?php $str = "PHPの絵本"; $length = strlen($str); ?> を表示させたいのですが、 <?php $str = "PHPの絵本"; $length = strlen($str); print $length; ?> で良いのではと思って、ブラウザで表示させたのですが、参考書では 「9」が表示されるみたいなのですが、「12」が表示されます。 さらに <?php $str = "PHPの絵本"; $length = mb_strlen($str); ?> も表記させたいのですが、同様に <?php $str = "PHPの絵本"; $length = mb_strlen($str); print $length; ?> と書きこんだのですが、参考書では「6」が出るみたいのなのですが 自分のブラウザでは「12」が表示されます。どうしてなのでしょうか?

    • 締切済み
    • PHP
  • 文字列の削除

    char str[]="/home/name/file.c"; という文字列から"file.c"の部分を削除したいのですが どのようにすればできますでしょうか? 教えて下さい。お願いします。