質問: /*切り出した文字列の最後にヌル文字を代入*/ printf("%s\n", ts); /*0.2が画面表示される*/ というようなプログラムがかけるかと思います. しかし,2つ目と3つ目の実数値を取り出す際,どのように書けるかがわかりません. (初期値 i の値を変えるのかな,という想像はしているのですが...) どのように表せばいいか教えていただけたら幸いです. わかりづらい箇所があったら申し訳ないです. よろしくお願いします.
回答: うーむ・・・。 これって宿題なのかしらん。 いや、もし、実用的にこういうプログラムが書きたい、ってのならc言語じゃない方が良いでしょう。と言うか、恐らく「やりたいこと」をマトモにやるとしたら、100人中96人くらいはc言語の使用を避けるんじゃないかなぁ。 ぶっちゃけ、c言語には文字列がありません。文字列が無い言語で文字列操作をしようとするのに土台無理があります(笑)。文字列を操作する為には「素のc言語」から何個ものレイヤーを重ねてる、ってのが「実用性」で言うと現実です。 例えばc言語が生まれたunixでも、素のcでテキストファイルの中の文字列を操作するのを避けさせる為に、sedやらawk等のスクリプト言語が生まれました(ある意味perlの遠い祖先です)。それくらい文字列操作を直接cでやるのはクッソメンド臭いのです。間違いなく死にます(謎 いや、何かcで上手いことやれるライブラリ無いのかしらん、って探してみたんですが、見つからなかったんですよね。windowsを使ってるんだろうし、強力なデータ構造がてんこ盛りのglibとか、一応調べてみたんですが、多分この辺使うのは難しいでしょうねぇ。 さて、と。取り敢えず前提から。 まずはコピー先の文字配列ts[15]の問題から行きましょう。まずこれが実は問題に合いません。 どういう事かと言うと、他のスクリプト言語、と言われる言語での実行例をお見せします。 # python での例 >>> s = "0.2\t0.0\t1.0" >>> s.split("\t") ['0.2', '0.0', '1.0'] >>> ;; scheme での例 #;1> (import srfi-13) ;; 文字列ライブラリを使用 ; loading /var/lib//chicken/11/srfi-13.import.so ... ; loading /var/lib//chicken/11/chicken.fixnum.import.so ... ; loading /var/lib//chicken/11/chicken.platform.import.so ... ; loading /var/lib//chicken/11/srfi-14.import.so ... note: re-importing already imported identifier: string->list note: re-importing already imported identifier: string-copy note: re-importing already imported identifier: string-fill! #;39> (define s "0.2\t0.0\t1.0") #;70> (string-tokenize s) ("0.2" "0.0" "1.0") さて、実は元々、問題としては、これは > 実数値の文字列を切り出し と言っていましたが、実は実数値の文字列もクソも関係ないんです。そうじゃなくって、逆に「(タブ等の)区切り文字部分で文字列を分割せよ」と言うのが主題です。こういう作業を「トークンに分ける作業」、すなわち「トーカナイズ」等と呼んだりします。主役は実は「区切り文字(タブの他に例えばスペース、コンマ、ピリオド等を利用する)」の方なんですね。 んで、上で利用したスクリプト言語なんてのは、見て分かる通り、このトーカナイズをやすやすとやってのける機能を持ってるんですが、結果を見て下さい。両者とも文字列を要素に持つリスト(c言語で言う配列みたいなモノ)を返しています。 つまり、このテの機能をc言語でやる場合、「文字配列の配列」を返した方が適する、と言う事が予想出来ます。 と言う事は、最初に挙げた質問で考えると、 ts[15] ではダメで、 ts[3][5] にせなアカン、と言う事です。二次元配列ですね。それを使わないといけません。 さて、もう一つは、一応、c言語の標準ライブラリにトーカナイズが出来るライブラリが(貧弱ながらも)含まれています。それはstring.hと言うヘッダなんですが、詳しくはこちらの方を参考にしてください。 c言語関数辞典 string.h: http://www.c-tipsref.com/reference/string.html このサイトはcの標準ライブラリを調べる際にはかなり重宝します。なんか分からん時はここで調べましょう。 この内の次の2つの関数を使用します。 strtok(文字列を区切り文字で分割する): http://www.c-tipsref.com/reference/string/strtok.html strcpy(文字列をコピーする): http://www.c-tipsref.com/reference/string/strcpy.html この2つを利用して書くと以下のようになりますね。 #include int main(void) { char s[40] = "0.2\t0.0\t1.0\0"; char ts[3][5]; char* temp; int i = 1; temp = strtok(s, "\t"); strcpy(ts[0], temp); while (temp != null) { temp = strtok(null, "\t"); if (temp != null) { strcpy(ts[i], temp); } i++; } return 0; } 特に出力は噛ましてませんが、「何のファイルを読むのか」具体例もありませんし、改造する為のベースならこれで充分じゃないか、と思います。出力自体も書き足すには苦労しないでしょうしね。 まぁでも、くれぐれも「素のc言語」で、文字列操作の為の実用プログラムを書こう、なんて思わないでください(笑)。世の中にはもっと便利なツールがあるのでそっちを利用しましょう(笑)。