- ベストアンサー
C言語・ファイルと文字列の操作プログラムについて!
- ファイルのデータを1行ずつ読み込み、","で区切られた要素に分割して配列に格納するプログラムの作り方を教えてください。
- ファイルを読み込み、3つめの要素を配列に格納する方法について教えてください。
- プログラムの実行結果として、3つ目の要素が正しく配列に格納されない問題について解決策を教えてください。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
#4です。 >1行の長さ,行数ともに制限はありませんので、実際に読み込みたいファイルは行数,各行の長さはバラバラです。 >大丈夫です。目的達成できるプログラムであれば、言語,関数などは自由です。 何を参考にしても良いとのことで、自前でなくても大丈夫です。 1行の長さ、行数に制限がないということは、コーディング時に、制約をつけてはいけない とうことを意味します。 これを厳密にC言語で実装するのは、非常に大変になります。 しかしながら、C言語以外のスクリプト言語(perl,ruby)などであれば、 実質的は、(ほぼ)制限のない形で、実装できます。 行数が非常に大きい場合、時間はかかりますが・・・ 以下は、perlで作成したスクリプトです。(スクリプト名をgoo.plとします) コマンドプロンプトで perl goo.pl test.txt と入力してください。 ソート結果が表示されます。 (perlがインストールされていない場合はperlが必要になります) -------------------------------------------- use strict; use warnings; #ソートルーチン sub mysort{ $a->[0] cmp $b->[0]; } my $file = shift(@ARGV); #入力ファイルのオープン open FHA,$file or die("can't open $file"); my @linfo = (); #入力ファイルの読込 while(<FHA>){ # 3列目の取得 my @elm = split(/,/,$_); # 3列目と1行全体を配列に確保する my $ref = [$elm[2],$_]; push(@linfo,$ref); } # 入力ファイルのクローズ close FHA; # 読み込んだ行を第3列目でソート @linfo = sort mysort @linfo; foreach my $lin (@linfo){ print $lin->[1]; } -------------------------------------------------- 実行結果は以下の通り C:\goo>perl goo.pl test.txt 2013/08/01,15:55,20130801155519-119072194140,,,山田,東京,mail 2013/08/01,16:19,20130801161906-210164001071,,,川口,神奈川,,電話番号 2013/08/01,11:32,20130802003256-116091178056,鈴木,埼玉,mail,電話番号 ------------------------------------------------
その他の回答 (4)
- tatsu99
- ベストアンサー率52% (391/751)
補足要求です。 1.OSはなんでしょうか。windowsですか、それともlinuxですか。 もし、linuxならsortコマンドで望んだ結果が得られます。 sort -t "," -k 3,3 test.txt とすると、以下の結果が表示されます。 -------------------------------------- 2013/08/01,15:55,20130801155519-119072194140,,,山田,東京,mail 2013/08/01,16:19,20130801161906-210164001071,,,川口,神奈川,,電話番号 2013/08/01,11:32,20130802003256-116091178056,鈴木,埼玉,mail,電話番号 ------------------------------------------------------- 2.それとも、コマンド等で結果を得るのが本当の目的ではなく、 (勉強などもかねて)C言語で作成するのが目的なのでしょうか? その場合、 1)1行の長さに制約はありますか?(必ず1行は300バイト以内ですか) 2)又、行数に制約はありますか?(例えば、必ず1000行以内と考えてよいですか) 3)ソートは、標準ライブラリで提供されているqsort関数を使用してよいですか、 それとも、必ず、自前で作らないとだめなのですか? 以上、補足をお願いします。
補足
ご回答ありがとうございます。 1 windowsを使用しております。コマンドの方法も参考にさせていただきます。ありがとうございます。 2 プログラム(言語、関数等は自由)を作成するのが目的です。インターン課題でしております。 ここに質問してよいと許可を得たので質問いたしました。 1)2) 1行の長さ,行数ともに制限はありませんので、実際に読み込みたいファイルは行数,各行の長さはバラバラです。 3) 大丈夫です。目的達成できるプログラムであれば、言語,関数などは自由です。 何を参考にしても良いとのことで、自前でなくても大丈夫です。 よろしくお願いいたします。
- KEIS050162
- ベストアンサー率47% (890/1879)
cp = data words[len] = strtok() s[i] = words[2] これらはポインター(格納アドレス)をコピーしているだけなので、配列の要素をコピーしている訳ではありません。 最初の cp = data では、gets()で読み取った、data の格納アドレスが、cp にコピーされただけですので、cpが指し示すアドレスは、data と同じになります。 後に、strok() の引数として cp が渡されますが、実体は data と同じことになります。(なのであまり意味があると思えません) 次の words[len] = strtok() も同様に、デリミターで分割された、配列 data の場所(格納アドレス)が渡されるだけなので、words[len] は、data[] のどこかの場所を指し示しているだけになります。 最後の s[i] = words[2] は、data の2番目に分割された文字列の格納アドレスが、s[i] に格納されるだけです。 while() では、テキストデータがなくなるまでループを続けることになりますが、毎回 data[] は上書きされ、結果として、s[]のデータは上書きされた、data[] の 2番目に分割された文字列が格納されたアドレスを指し示しているだけになります。 たまたまテキストファイルの2番目の文字列前が固定長なので、結果として毎回同じ格納アドレスがs[0]~s[2]に格納され、そのアドレスが参照しているのは、最後に取り込んだ data のデリミタで区切られた2番目の文字列、ということになります。 試しに、各行の最初の 2013/08/01 を各行ごとに一文字ずつ文字数を変えると、これが良く分かります。 もし、data[] の実体をそれぞれの配列 (cp[]、words[]、s[]など)にコピーしたいのであれば、それらを二次元配列として要素数を data[] と同じにして定義する必要があります。 strcpy をどの様に記述したか分かりませんが、恐らく、ポインター(ポインター配列)として定義して要素数文だけのエリアを確保していない変数に、data[] の実体をコピーしたのでしょう。 その為、ユーザーが使用出来る領域外にまで、データを書き込んでしまい、強制終了となったと思われます。 文字列の定義、配列、二次元配列、ポインターの操作の辺りをもう一度しっかり復習してみてください。 初心者がはまり易いところです。 ご参考に。
お礼
ご回答ありがとうございました。 詳しいご指摘と解説大変助かりました。参考に改善をしていきたいと思います。 やはり文字列、ポインタ、配列の勉強不足ですね…。 もう一度学校のテキスト等で基礎しっかり復讐しておこうと思います。
- tsunji
- ベストアンサー率20% (196/958)
ポインタのコピーを利用しているようだけど、そのポインタが差す実態は何処にあるのか というのを考えると、理解しやすいかも。(初心者が間違いやすい) まず各データを2次元配列にコピーするプログラムを作ってみるといいよ。
お礼
ご回答ありがとうございます。 配列とポインタの理解が曖昧なままプログラムをつくっておりました。 ご指摘された部分を理解して改善していきたいと思います。
- Tacosan
- ベストアンサー率23% (3656/15482)
確認ですが, そのプログラムでなぜそのような結果になるのかわかっていますか? また, 「strcpy を用いた」ときにプログラムが強制終了した理由は理解できていますか?
補足
ご回答ありがとうございます。 実行結果の、s[]の内容が全ていっしょになる理由、strcpyを用いた際に強制終了になった理由をよくわかっておりせん…。 その原因と対策を教えていただきたく質問いたしました。
お礼
補足にまでご回答ありがとうございます。 自前のプログラムを改善し動かせるようになりましたが、ご指摘の通り、行数と要素数がもっとランダムなほかのファイルではうまく動きませんでした…。C言語では難しいのですね…。 いただいたプログラムをもとにPerlとrubyの勉強をしたいと思います。 本当に助かりました。ありがとうございました。