• 締切済み

文字列操作(終端と抽出)について

こんばんは お時間等ございましたら、ご指摘よろしくお願いします。 <背景>メインプログラムからサブプログラムに複数の数値を渡して、     文字列として編集します。     そして、その文字列から特定の文字のみを抽出し、     ファイルに出力したいと考えています。     ※下記にソースイメージを記しました。      ただ、While文の指定がうまくなく、      想定どおり処理を抜けれません。 <質問>サブプログラムでファイルに出力する文字のうち、     抽出する文字と抽出しない文字はランダムで、     メインプログラムから、渡されてきます。     ※文字列の文字数は、     メインから渡され編集した文字数>=ファイルに出力する文字数。     サブプログラムの先頭で出力する文字列の大きさを     指定しているのですが、抽出しない文字があった場合、     抽出しない文字数分ゴミが出力されてしまうのを     防ぎたいと考えています。 <イメージ> #include <stdio.h> void sub( int a, int b, int c, FILE *fp ); int main(){ FILE *fp; fp = fopen("c:\\0511.txt","w"); int a;int b;int c; a = 1; b = 0; c = 1; sub( a, b, c, fp ); fclose(fp); } void sub( int a, int b, int c, FILE *fp ){ int j = 0; char moji[4];char moji2[4]; sprintf(moji,"%d%d%d%s",a,b,c,"\0" ); while( moji[moji[*moji]] != '\0' ){ switch( moji[moji[*moji]] ){ case '1' : moji2[j] = moji[moji[*moji]]; break; case '0' : j -= 1; break; default :;break; } moji[*moji] += 1;j += 1; } fprintf(fp,"%s\n",moji2 ); }// Run-Time Check Failure #2 - Stack around the variable 'moji' was corrupted. もし宜しければ、ご指摘の程よろしくお願いします。

みんなの回答

  • dummyplug
  • ベストアンサー率58% (134/230)
回答No.6

丁寧に返答していただきありがとうございます。 だいぶやりたいこと(処理)が見えてきました。 あと一点、返答から漏れていたことを確認させてください。 sub()関数に渡すのは3つの数値、正の整数とのことですが、それぞれの数値に各々意味はありますか?プログラムや回答者の皆さんへの返答を見ている限り、3つの数字は全て同等の扱いで、単に一桁目、二桁目、三桁目という違いだけであるように見受けましたがそれで正しいですか?また、数値の個数が3つであることに意味はありますか。 回答者の方への返答や例を見ていると各数値には0または1しか入らないように想定しているようにも見えます。本当はそうなのですか。それとも、正の整数なのですか。あるいは一桁の整数(0-9)なのですか。 できれば、こうした質問に答えてもらった内容をまとめて整理し、もう一度<背景>を書いてみてもらえますか。

  • dummyplug
  • ベストアンサー率58% (134/230)
回答No.5

質問の仕方やプログラムから見受けるによく頑張っているという印象は受けます。が、厳しい言い方をすれば技術的には見るべきところがほとんどないという印象です。 まずは、何をするプログラムを書こうとしているのか(質問の文章で言うと「<背景>」のところ)を正確に記述するところから始めましょう。 >メインプログラムからサブプログラムに複数の数値を渡して、 「複数」とはいくつですか。プログラムを見ると3つのように見受けます。3つでよいですか?その3つの数字にはそれぞれ意味がありますか?例えば、一つめと二つめは抽出する数字、3つめは文字列の長さ、というような。また、それらの数値には取り得る範囲(例えば正の整数とか一桁の整数といったような)がありますか? >文字列として編集します。 「編集する」とはどのような処理ですか。例えば、渡された三つの数値がそれぞれ12と34と567だったとしたらどのような文字列になるようにしたいのですか? >そして、その文字列から特定の文字のみを抽出し、 「特定の文字」とは何ですか?どうやって指定しますか?抽出対象であるかどうかを客観的に判断できる基準がありますか?また、抽出とはどういう処理ですか? 例えば「"1234556"という文字の列から奇数("1","3","5")を抽出」と言った場合、結果が"1355"になればよいのか、"135"(ダブっている"5"を排除)、"1 3 55 "になればよいのか、"1(1)","3(1)","5(2)"(括弧内は個数)になればよいのか、など様々な可能性があります。どうなって欲しいですか? >ファイルに出力したいと考えています。 どのような形式でファイルに書かれればよいですか。抽出した数字ごとに改行とかの区切りが必要ですか。ファイル形式はテキストですか、バイナリですか。 何をしたいかを正確に書ければそれをプログラムにするのは難しいことではありません。逆に言うと何をしたいのかを書けないとプログラムにも訳のわからないものが混入するということです。 まぁ、プログラムを書くのに慣れていれば日本語で正確に記述するよりコードを書いた方が正確っていうこともありえますけれども。 >ただ、While文の指定がうまくなく、 悪い言い方ですけれど、while文の指定どころの騒ぎではないコードだと思います。あなたが(今の時点では)間違って考えてしまっていることを正しく指摘してもらう(そして理解を深める)ためにも、あなたがしようとしていることをなるべく正確に記述して伝えるのが近道だと考えます。

CCLemon70
質問者

補足

dummyplugさま おはようございます。 >「複数」とはいくつですか。・・・ 3つです。抽出する文字というよりも「0」という文字を除外します。 数値としてメインより渡される値は1桁の正の整数です。 >「編集する」とはどのような処理ですか。 >例えば、渡された三つの数値がそれぞれ12と34と567だったとしたら >どのような文字列になるようにしたいのですか? 「編集する」とは、必要な文字のみ抽出(不要な文字を除外)します。 桁数は違いますがイメージとして、 「1234567」が渡された場合、「1234567」を出力しますが、 「1200507」が渡された場合は、「1257」を出力します。 >どうなって欲しいですか? 桁数は違いますがイメージとして、 「1234556」が渡された場合、「1234556」を出力します。 「1220330」が渡された場合、「12233」を出力します。 >どのような形式でファイルに書かれればよいですか。 テキスト形式で改行して出力します。 「渡された数値」→[数値を文字変換]→【処理後の文字】 「101」→[101]→【11】 「001」→[001]→【1】 「100」→[100]→【1】 この場合、ファイルでは下記をイメージしています。 11 1 1 ご指摘ありがとうございます。言葉足らずで失礼しました。 夜遅くまで、ありがとうございます。

  • phoenix343
  • ベストアンサー率15% (296/1946)
回答No.4

sprintfで出力先に指定されているmojiは文字列として渡されているので、それをそのまま数値として扱うことは出来ないのです(mojiを配列扱いしているところからして間違っている)。 型の違いをちゃんと覚えてください。 C言語の文字列は必ず最後に'\0'がつくのは確かですが、文字列を扱う標準関数にわざわざ'\0'を入れる必要はありません。

CCLemon70
質問者

補足

phoenix343さま おはようございます。 >型の違いをちゃんと覚えてください。 >C言語の文字列は必ず最後に'\0'がつくのは確かですが、 >文字列を扱う標準関数にわざわざ'\0'を入れる必要はありません。 失礼しました。

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

う~ん!何かメロメロといった感じです。 (1)sprintf(moji,"%d%d%d%s",a,b,c,"\0" ); sprintf(moji,"%d%d%d",a,b,c);とすべきです。sprintfは必ず最後に null文字が入るので、上記の記述ではnull文字が2個になります。 (2)while( moji[moji[*moji]] != '\0' ) 全く理解できません。*mojiはmojiの先頭を指している(つまり、moji[0]と同じ)ので、 例だと"1"になっています。文字の"1"はコードで0x31=49なので、moji[49]と同じ意味になります。 記述はmoji[moji[moji[0]]]→moji[moji[49]]ということです。インデックスが49は 配列の定義範囲外ですから、何が入っているか分かりません。さらにその中身が インデックスになっているのですから、これ以上のコメントは不要でしょう。 (3)case '0' : j -= 1; break; インデックスがマイナスになる場合があるので、大変キケンなコードです。 (4)moji[*moji] += 1; moji[*moji]は配列の範囲外です。スタックが破壊されます。 配列が2個あって、同期しないのだから、インデックスは2個用意すべきでしょう。 int i,j=0; while文はfor( i = 0 ; moji[i] ; i++ )とすべきと思います。 あと、ランダムと言っているのに、subの中でswitch文が出てくるのはどういうことでしょう? case文には定数を使わなければならないので、「ランダム」にならないと思いますが。

CCLemon70
質問者

補足

nda23さま おはようございます。 >sprintf(moji,"%d%d%d",a,b,c);とすべきです。sprintfは必ず最後に >null文字が入るので、上記の記述ではnull文字が2個になります。 >全く理解できません。 while文で「moji」のインデックスを+1ずつ進めて、 mojiの値をなめて、拾う文字なのかそれとも捨てる文字なのかを、 決めようと思いました。 文字をなめていき、null文字がきたらwhile文を終了しようと思いましたが、 終了しなかったので、「sprintf」にはnullが入らないと安直に思い、 「sprintf」に「"\0"」を追加しました。 >インデックスがマイナスになる場合があるので、大変キケンなコードです。 「moji」をインデックスを進めて見ていき、 「moji」から不要な文字を捨てるには、不要な文字が見つかった時、 セット先「moji2」のインデックスを「-1」しようと思いました。 >moji[*moji]は配列の範囲外です。スタックが破壊されます。 失礼しました。 >あと、ランダムと言っているのに、subの中でswitch文が出てくるのはどういうことでしょう? >case文には定数を使わなければならないので、「ランダム」にならないと思いますが。 値は固定ですが、パターンが「ランダム」です。 パターンとは、「101」「001」「010」「111」等です。

  • yokomaya
  • ベストアンサー率40% (147/366)
回答No.2

ぱっと見ですが何故配列を4と節約してはるのかな? 僕は基本的に多めに取ります。sprintfの動作覚えてないから自信はないけど…

CCLemon70
質問者

補足

yokomayaさま おはようございます。 >ぱっと見ですが何故配列を4と節約してはるのかな? >僕は基本的に多めに取ります。 「節約」という気持ちでしたが、他のみなさんの回答を見る限り、 「節約」どころの問題ではなさそうです。

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.1

とりあえず、オジさんには > while( moji[moji[*moji]] != '\0' ){ の時点で何がしたいのかサッパリだよ。 ><質問>サブプログラムでファイルに出力する文字のうち、 >    抽出する文字と抽出しない文字はランダムで、 >    メインプログラムから、渡されてきます。 void sub() は「抽出する文字」や「抽出しない文字」が 渡されている形跡はありませんが。 ><背景>メインプログラムからサブプログラムに複数の数値を渡して、 >    文字列として編集します。 >    そして、その文字列から特定の文字のみを抽出し、 >    ファイルに出力したいと考えています。 そういう場合、関数に分割するのであれば、 ・複数の数値を編集して文字列とする関数 ・文字列から特定の文字を抽出する関数 ・文字列をファイルに出力する関数 くらいが適当かと思います。 今問題になっているのは、2番目の文字列から特定文字を抽出する関数ですね。 「抽出」の意味が不明なので補足して下さい。 ちなみに、1番目と3番目は snprintf() / fprintf() で特になにもする必要はなさそう。 2番目も strchr() などで解決するような気がする。

CCLemon70
質問者

補足

koko_u_さま おはようございます。 >void sub() は「抽出する文字」や「抽出しない文字」が >渡されている形跡はありませんが。 >今問題になっているのは、2番目の文字列から特定文字を抽出する関数ですね。 >「抽出」の意味が不明なので補足して下さい。 メインプログラムからサブプログラムには、 「101」や「010」や「001」などランダムに渡されてきます。 イメージでは単純に「101」とし、 「1」を抽出する文字「0」を抽出しない文字として処理を考えています。 抽出というよりも除外かもしれません。 「110」から「0」を除外して、「11」とする・・・と考えています。 >ちなみに、1番目と3番目は snprintf() / fprintf() で特になにもする必要はなさそう。 >2番目も strchr() などで解決するような気がする。 失礼しました。

関連するQ&A

専門家に質問してみよう