投稿
otta777 otta777a
私も一問フチコンクイズを出してみます。入力した文字列の中のカンマの位置を全て表示しなさい。ネタバレチェックを入れてくださいね。難易度は★★★★☆かな。
5そうだね
プレイ済み
返信[1]
親投稿
ねこはち neko80001
ダイレクトモードでやってみたよ!
0そうだね
プレイ済み
返信[2]
親投稿
おかっぺ Japanese_WASABI
難し過ぎます。 PRINT ">"; WHILE TRUE B$=INKEY$() A$=A$+B$ PRINT B$; IF B$==CHR$(13) THEN BREAK WEND PRINT WHILE TRUE I=INSTR(I,A$,",") IF I<0 THEN BREAK INC I PRINT I;"もじめ" WEND
0そうだね
プレイ済み
返信[3]
親投稿
おかっぺ Japanese_WASABI
LINPUTだと!? 僕のは入力した文字列と言うのにあわないorz
0そうだね
プレイ済み
返信[4]
親投稿
けい kei0baisoku
最後の改行だけ、何か違う理由な気がする…
0そうだね
プレイ済み
返信[5]
親投稿
けい kei0baisoku
回数が動的なループ処理を考える、良い問題ですね。 だいたい基本的な命令の組み合わせでできますし。
3そうだね
プレイ済み
返信[6]
親投稿
KU kerorinU
LINPUT">";A$ FOR I=0TO LEN(A$)-1 IF MID$(A$,I,1)==","THEN ?I+1;"もじめ" NEXT INSTRを使った方法がわからなかったので、FORとMID$での強行突破でいきました。INSTRの開始位置の計算方法とかわからん
0そうだね
プレイ済み
返信[7]
親投稿
あらかたのやり方は出てしまっているのて、けいさんの使っていた裏技(?)を使ったやり方だけ書いておきます。 LINPUT">";A$ FOR I=0TO LEN(A$)-1 IF A$[i]=="," THEN ?I+1;"もじめ" NEXT マニュアル通りのやり方じゃないので危険かもしれないという可能性もありますが、添字の範囲外のエラーも出る(暴走しない)し、まあ問題ないかなと考えてきてます。 まあでもご利用は自己責任で…
0そうだね
プレイ済み
返信[8]
親投稿
pinfu ANNAININ
otta777さん、 降参!! コレが、初心者のリアルです(笑) ちと難しいデス・・・ ,の数を繰り返す??? うーん、次回があれば、 初心者には、 ネタバレでヒント・・・とか・・・
1そうだね
プレイ済み
返信[9]
親投稿
otta777 otta777a
たくさんのお答えありがとうございました。申し訳有りません。家庭の事情で回答とレスを書いている時間がとれません。後日書かせていただきます
3そうだね
プレイ済み
返信[10]
親投稿
おかっぺ Japanese_WASABI
pinfu さん向けのヒントを次の投稿にネタバレで投稿します。
1そうだね
プレイ済み
返信[11]
親投稿
おかっぺ Japanese_WASABI
PRINT INSTR(0,"ABCBD","B") PRINT INSTR(1,"ABCBD","B") PRINT INSTR(2,"ABCBD","B") PRINT INSTR(3,"ABCBD","B") PRINT INSTR(4,"ABCBD","B")
1そうだね
プレイ済み
返信[12]
親投稿
pinfu ANNAININ
おかっぺさん、 ありがとうございます!! ちょっと、考えてみます!
0そうだね
プレイ済み
返信[13]
親投稿
pinfu ANNAININ
これで!いいのかな?
0そうだね
プレイ済み
返信[14]
親投稿
otta777 otta777a
お待たせしてしまいましたが正解のプログラムを発表させていただきます。詳しい説明はPCから書き込むので以降のコメントにて。
0そうだね
プレイ済み
返信[15]
親投稿
おかっぺ Japanese_WASABI
@otta777さん 後からこの問題を楽しみたい方向けに、回答告知と回答(ネタバレ)と言うのが良いかなと思いました。 そして、自分で難しくしてしまった僕(笑)
1そうだね
プレイ済み
返信[16]
親投稿
otta777 otta777a
Ans1は1番一般的な方法だと思います。MID$で一文字ずつ 左から文字を比較していってカンマだったら表示をします。 大抵のBASICではMID$をサポートしているのでこちらの方法が 一般的だと思いますが文字列が長くなった分処理時間が 掛かります。 I+1としているのはプチコンでは開始位置の指定が0からと なっているため開始位置0=1文字目となるからです。
0そうだね
プレイ済み
返信[17]
親投稿
otta777 otta777a
Ans.2はINSTRという関数をサポートしているBASICで使用できる 方法です。文字列を左から見て指定位置以降から最初の指定 文字の位置を取得して表示する方法です。指定文字が無い 場合は-1が返ってきます。こちらも0が1文字目になるため+1を しています。そして次に検索を開始する位置を右に1つずらす 処理も兼ねていますこれをしないといつまでも同じ位置 ばかりを表示してプログラムは終了しません。 WHILE TRUE~WENDでループを組み、IF文で指定文字が無い ときにBREAKでループを抜ける仕様になっています。 メリットは一文字ずつ比較をするのでは無く検索対象の 文字の位置を調べるのでループの回数が少なくて済みます。
0そうだね
プレイ済み
返信[18]
親投稿
otta777 otta777a
Ans.3はAns.1の変則技でSHIFT関数を文字列に使用すると 左の一文字を戻り値とした上に指定した文字列の左一文字を 削除してくれるという隠れ仕様があるのを見つけたため 使ってみました。 C$=SHIFT(S$) は C$=LEFT$(S$,1):S$=RIGHT$(S$,LEN(S$)-1) と同等の処理をします。 隠れ仕様という理由はHELPには配列に対しての説明しか 書かれていないためです。
0そうだね
プレイ済み
返信[19]
親投稿
otta777 otta777a
>ねこはちさん IF文を使わずに論理式を利用してカンマが有った時だけ 表示をするようにするテクは自分も思いつきませんでした。 1行でシンプルに収まっていてさすがですね。 一つ気になった点はFOR文のLEN(A$)はLEN(A$)-1としないと ASC関数を使うような場合はエラーになってしまいます。 ASC("")はプチコンではエラーとなってしまうためです。
1そうだね
プレイ済み
返信[20]
親投稿
otta777 otta777a
>おかっぺさん INPUT命令ではカンマを入力出来ないのでINKEY$で文字入力の 処理を書いて下さいましたね。今回はLINPUT命令でカンマを 入力出来るのでここまでしなくてもOKでしたが、特定の文字 のみ入力を受け付けるようにしたい場合はこのような処理で 入力出来る文字を制限できます。 A$=A$+B$の前にB$の内容をチェックして入力出来ない文字の 場合はB$=INKEY$の前まで処理を戻します。 解析部分はAns.2のパターンですね。
1そうだね
プレイ済み
返信[21]
親投稿
otta777 otta777a
>けいさん 最後の改行が無いと表示結果とプロンプトがくっついて 見辛かったんで1行空白行を入れました。 こちらも解析部分はAns.2と同じですね。 お見事です。プチコンにはINSTR関数という指定文字が 何文字目に有るかを返してくれる関数が有るためこのように 効率よく検索をすることが出来ます。
1そうだね
プレイ済み
返信[22]
親投稿
otta777 otta777a
>でんぺんさん プチコン3号では文字列変数と文字配列変数に密接な 関係があることと変数と同名の配列変数が使えない のは詳しく説明はされていませんが仕様だと思います。 自分もAns.3では取説やヘルプには記載されていない 文字列変数にSHIFT関数を使って処理をしています。 解析部分はAns.1のパターンですね。
0そうだね
プレイ済み
返信[23]
親投稿
otta777 otta777a
>pinfuさん 苦労された後がうかがえます。この問題は見方を変えると 入力した文字の中にカンマがあるかどうか1文字ずつ チェックをしてカンマが有ったらその位置を表示する と言う処理を入力した文字列の文字数分繰り返せば OKでした。コメントアウトしたMID$を使った方法は かなり正解に近かったですよ。INSTR関数を使う場合は カンマを見つけた位置以降の検索方法だと思います。 次に検索を始める位置は検索する文字列の文字数を プラスしたい力行えばOKです。 再投稿して頂いた方ではループ回数をLEN(A$)として 全文字検索文字列だった場合でも文字数分ループ するようになっています。この場合のFOR命令の指定は I=1 TO LでOKですよ。
1そうだね
プレイ済み
返信[24]
親投稿
otta777 otta777a
今回のポイントはINPUT命令ではカンマは入力出来ないので どう入力をするかという事とカンマの位置をどのように解析 するかということでした。プチコンではINSTR関数という 便利な命令のおかげで一文字ずつ調べなくても目的の 文字の位置を取得できます。更にこの関数を使うと 2文字以上の文字列も検索が出来ます。 ユーザーが入力したコマンドの解析や入力項目数が 不定の複数のパラメーターを一度に入力させて処理が 出来るので便利な使い方が考えられると思います。 今回は皆様にお付き合い頂きまして嬉しく思いました。 つたない説明ではありますが皆様のお役に立てれば 嬉しいです。また機会がありましたらこのような クイズを出させて頂きます。 ありがとうございました。
3そうだね
プレイ済み
返信[25]
親投稿
otta777 otta777a
>次に検索を始める位置は検索する文字列の文字数を >プラスしたい力行えばOKです。 は 次に検索を始める位置は検索する文字列の文字数を プラスした位置から行えばOKです。 に読み替えて下さい。
1そうだね
プレイ済み
返信[26]
親投稿
pinfu ANNAININ
皆さんの解答+otta777さんの解説、とても勉強になりました!! otta777さん、 問題作成お疲れ様です!! ありがとうございました!!
1そうだね
プレイ済み
返信[27]
親投稿
けい kei0baisoku
丁寧な解説、ありがとうございました。 同じ目的でも色々アプローチがありますね。 ちなみに私が、自分で見つけていたのにMSG$[I]を使わなかったのは………単に忘れていたからです(°∀°) 「文字列内検索=INSTR」という思い込みでした。 多分、巨大データが対象だと1文字ずつFORを回す方が速そうですが、探すのが二文字以上のワードだとINSTRを使わないと途端に複雑になりますね。
0そうだね
プレイ済み
返信[28]
親投稿
otta777 otta777a
FOR~NEXTで一文字ずつ調べていると文字数分オーバーヘッドが あるためINSTR関数が時間が掛かるような仕様で無ければ INSTR関数を使った方が処理時間は早いと考えます。 2文字以上の検索はMID$のみで処理をする場は二重ループで 検索する文字列を左から1文字ずつチェックして 途中で不一致だったらBREAKしてループを抜けたときに ループで使っている変数がループ回数と同じなら一致と判断 すればいいと思います。時間は掛かりそうですけど^^;;; @ANS_4 FOR I=0 TO LEN(S$)-1 FOR J=0 TO LEN(SE$)-1 IF MID$(S$,I,1)!=MID$(SE$,J,1) THEN BREAK NEXT IF J==LEN(SE$) THEN ? I;”もじめ” I=I+LEN(SE$) NEXT
0そうだね
プレイ済み
返信[29]
親投稿
otta777 otta777a
>IF J==LEN(SE$) THEN ? I;”もじめ” >I=I+LEN(SE$) は IF J==LEN(SE$) THEN ? I;”もじめ”: I=I+LEN(SE$) に読み替えて下さい。 うっかりしていました。
0そうだね
プレイ済み
返信[30]
親投稿
けい kei0baisoku
FORとINSTRの違いについて、INSTRの中でも結局1文字ずつ探さないといけないのは同じなので、はじめから1文字だけにターゲットを絞って自前で組んでる方が速いだろう、という考えでした。 せっかくですので、実際に検証してみました。
0そうだね
プレイ済み
返信[31]
親投稿
けい kei0baisoku
検証に組んだプログラムです。
0そうだね
プレイ済み
返信[32]
親投稿
けい kei0baisoku
結果です。
0そうだね
プレイ済み
返信[33]
親投稿
けい kei0baisoku
INSTRの方が速い上に上に全然違う!(°Д°) (環境は3DSLLです) 一応、自前の方は速度も多少気にして無駄はなく組んだつもりなのですが。 INSTRなど用意されている命令は、中で文字列のアドレスに直接アクセスして処理しているのでしょうか。もしくはS$[I]が実際にはMID()とかに置き換えられていて、関数コールのオーバーヘッドもかかっているとか………
0そうだね
プレイ済み
返信[34]
親投稿
otta777 otta777a
>けいさん 内部的なお話になってしまいますが、INSTR関数の場合は 目的の文字列が見つかるまでINSTR関数用のワークエリアを 使用して検索をしてると考えています。 FOR~NEXTでループを組んだ場合は中で使用している変数を 参照する場合に変数名から変数格納アドレスを検索して 参照するため、専用のワークエリアで計算するより遙かに 時間が掛かると思います。
0そうだね
プレイ済み
返信[35]
親投稿
けい kei0baisoku
>otta777さん ありがとうございます。何となく理解しました。 両方同じ「変数にアクセス」に見えるけど、BASIC上でのIやS$へのアクセスは、変数名をキーに、存在している変数テーブルからのサーチが毎回入っているような感じなのですね。 見た目上1命令に見えても、BASICとしての解釈自体の処理も入ってくるから見た目通りとは限らないのですね。
0そうだね
プレイ済み
返信[36]
親投稿
おかっぺ Japanese_WASABI
pinfu さん向けのヒント、INSTR だけでなく、MID$版があればもっと良かったですね。 プログラミングは目的を達成する方法の1つ。 色んな正解があるよ。と言うのが面白かったです。
1そうだね
プレイ済み