ページ 1 / 1
並び替え
Posted: 2009年6月25日(木) 12:15
by 研修生
csvファイルで書かれたファイルのデータを並び替える方法が思いつかないので教えて下さい。
生徒番号 クラス 名前 好きな教科
1 A 山田 国語
2 B 佐藤 数学
3 B 加藤 国語
4 A 渡辺 国語
・
・
・
というファイルがあるとすると
クラスと好きな教科が同じのをグループ分けをしたいです。
この例では
生徒番号の1と4,2と3が同じですので
1
4
2
3の順に並べ替えるてまとめて表示するプログラムをMFCにて今組んでいます。
後半の表示はわかりますが前半の分け方がわかりません。
アドバイスでもいいので教えて下さい。
Re:並び替え
Posted: 2009年6月25日(木) 12:45
by 山崎
こんにちは。
わからないのはどの部分でしょうか。
cvsファイルの開き方と読み込み方でしょうか、
それとも、データをソートするアルゴリズムでしょうかな?
はたまた、何をすればいいのか全くわからない、といった感じでしょうか?
具体的に何がわからないのかと、
とりあえず今まで作ってみたソースコードを見せてくれると助かります。
Re:並び替え
Posted: 2009年6月25日(木) 13:04
by 研修生
まずある程度どういうプログラムにするか理解できていないとプログラムは組めません。
その上データのソート方法がわからないのでまだイメージの段階です。
わからないのは分け方かな。値を保持し、比較しさらにソートする、これがわからないとおもいます。
比較はさすがにわかるので値の保持の仕方とソート方法です。
Re:並び替え
Posted: 2009年6月25日(木) 13:13
by non
それでは、csvファイルからデータを読み込み、構造体または配列に格納し、そのままの状態で
表示するところまでのプログラムを添付してください。
csvファイルも参考までに添付してください。
Re:並び替え
Posted: 2009年6月25日(木) 13:42
by 研修生
プログラムを添付して一緒に考えればプログラムも早くできるとは思いますが自分で組まないと
勉強になりません。私が欲しいのはアイデアです。こうすればどうかなど。
Re:並び替え
Posted: 2009年6月25日(木) 14:09
by YuO
> まずある程度どういうプログラムにするか理解できていないとプログラムは組めません。
プログラムを作成する場合,プログラムは理解する物ではなく考える物です。
考え方なので,方法はいくつもあると思いますが。
> わからないのは分け方かな。値を保持し、比較しさらにソートする、これがわからないとおもいます。
> 比較はさすがにわかるので値の保持の仕方とソート方法です。
CSVのデータは,1行を構造体にでもマッピングしてしまえばよいと思います。
あとは,それを配列やCArrayやstd::vectorにして保持するだけです。
ソート方法は,好きな方法を使えばよいです。
クイックソートでもヒープソートでも挿入ソートでもバブルソートでも……。
大小関係でソートするこれらのソートであれば,比較関数が問題になるだけです。
ところで,入力がどうみてもCSV ("Comma" Separated Values) ではないのですが。
Re:並び替え
Posted: 2009年6月25日(木) 14:09
by バグ
rowとcolumnが固定長のcsvならば、sscanfを使えば簡単ですよ。
固定長でないならば、ちょっと一捻り必要になりますが、csvってのはデータがカンマで区切られているだけのテキストなのですから、「カンマとカンマの間に存在するものが欲しいデータである」という風に考えればいいのではないでしょうか?
ソートに関しては、データ数にもよるでしょうが、そんなに大量でないのならばバブルソートで充分でしょう。
バブルソートについては、検索してみてください。
Re:並び替え
Posted: 2009年6月25日(木) 14:14
by non
>一緒に考えれば
一緒に考えようとは思っていません。
先に言ったところまで作ってくれれば下のことがわかるからです。
1 データの最大件数は?
2 データ格納は動的に行うのか、静的に行うのか?
3 構造体を使うのか?
4 csvファイルは""で囲まれているのか否か?
5 クラスはどのようなものがあるのか?またその順は?
6 好きな教科はどのようなものがあるのか?またその順は?
さて、アイデアということですから、簡単なのは
データを構造体に読み込み、先に好きな教科で並び替え、その後でクラスで
並び替えるという方法でしょうか。
Re:並び替え
Posted: 2009年6月25日(木) 15:04
by やそ
研修生さんの技術レベルはわかりませんが、
csvファイルの扱いって厳密に行おうとすると、
Cを触り始めたばかりの初心者には難しいかもしれません。
エラー処理までを考えると非常にめんどいです。
課題であれば、このcsvファイルの構造もしっかり明記されているか、データそのものがあるはずだと思います。
まずはそれをここに晒すことからはじめるべきかな。csvといいつつカンマが見えないし^^;
で、処理の流れは皆さんが挙げられたとおりソートを用いて組むことになります。
まあ、ソートはとりあえずバブルソートでいいんじゃないかな。
1、”クラス”でソートする。
2、”クラス”が同じもののなかで”教科”でソートする。
2番目のソートの実現に若干の工夫が必要です。
というか課題を出された側はそこをどう表現するかを見たいのかもしれません。
規約に則った上で、質問内容を具体的にし、自分はどこまで考えたかを晒せば有用な回答が得られるでしょう。
がんばれ~。
Re:並び替え
Posted: 2009年6月25日(木) 17:30
by dic
私でしたら・・・と言わない方がいいのかな
私のやり方のヒントでは ハードコーティングします
汎用性は失われるのでもっといい方法があると思います
Re:並び替え
Posted: 2009年6月25日(木) 19:53
by 研修生
意見ありがとうございました。
カンマの方は思いつきの例で手打ちでしたのでみすってしまいました。
今考えてた方法が却下されて構造体でいつでもアクセスできるようにとかいわれ
構造体配列を使うことを考えました。
struct test{
int student_number;
char classtype[5];
char name[20];
char subject[10];
};
struct test seito2[20] = {
{ 1,"A","山田I", "国語"},
{ 2,"B", "佐藤", "数学" },
{ 3,"B", "加藤", "数学" },
{ 4,"A","渡辺","国語"}
};
としておけばアクセスできそうですが・・
よく皆様が構造体といってる類の使い方ですが
こういうことでしょうか?少し今試せる環境にないので後日試してみます。
Re:並び替え
Posted: 2009年6月26日(金) 10:02
by 研修生
自分で組まなければ勉強にならないと大見得きっといてあれですが・・
構造体の組み方についておしえてください。。
1,"A","山田","国語"
2,"B","佐藤","数学"
3,"B","加藤","数学"
4,"A","渡辺","国語"
・
・
・
・
というようなファイルの文字列を構造体に組み込めないんですが
どのようにすればいいでしょうか?
今やってるのは
struct test{
int student_number;
char classtype[5];
char name[20];
char subject[10];
};
int main()
{
FILE *fp;
char buf[1001];
if((fp = fopen("test.csv","r")) == NULL){
return;
}
while(fgets(buf,1000,fp) !=NULL){
//struct test T[1000] = buf
でwhileから先がわからないのですがfgetsで一行ずつ代入しようとすると配列の配列にしなくてはいけないが
何行あるかはファイル次第なのでstruxt test T[1000]としようとしたが定数式ではないので無理でした。
そもそも変換が合わないのですがこのファイルから読み込んだ文字列を構造体に組み込むのはできるのでしょうか?
Re:並び替え
Posted: 2009年6月26日(金) 11:51
by バグ
ファイルのフォーマットは1行1レコードですか?
もし、そうならば、fscanfという関数を使えば楽ですよ(^-^)
Re:並び替え
Posted: 2009年6月26日(金) 13:35
by 研修生
csvの定義にレコードは各行で区切られた各値のことと書いてるので1かな?
type struct{
int number[20];
char class type[20];
char name[8];
char subject[20];
} my;
my data[100];
int main()
{
FILE *fp;
int line = 0;
char buf[1000];
if((fp = fopne("test.csv","r")) == NULL){
printf("ファイルopneerror");
}
while(fgets(buf,1000mfp) != NULL){
sscanf(buf,"%d%s%s%s",&data[line].number,data[line].class_type, data[line].name,data[line].subject);
line++;
}
fclose(fp);
return 0;
}
としてみましたが値がちゃんと入っていません。ファイルは1個上の例の内容をテキストファイルで開いたものです。
どこがおかしいのか教えて下さい。
Re:並び替え
Posted: 2009年6月26日(金) 13:42
by non
なぜ、動かしているプログラムそのままを貼り付けないのですか?
Re:並び替え
Posted: 2009年6月26日(金) 13:47
by 研修生
ネットができるPCとプログラムができるPCが別だからです。
USBなどがあれば移せますが今は手元にないので手打ちです。
Re:並び替え
Posted: 2009年6月26日(金) 13:53
by non
あきらかな打ち間違いが3カ所。
構造体のint number[20];を配列にしている意味がわからない。
>sscanf(buf,"%d%s%s%s",&data[line].number,data[line].class_type, data[line].name,data[line].subject);
これでは、分解できない。
Re:並び替え
Posted: 2009年6月26日(金) 14:25
by 研修生
sscanfは初めて使うんですがどこが間違ってるのでしょうか?
分解ということは"%d%s%s%s"のとこでしょうか
"%d,%s,%s,%s"としても値は入っていないですね
Re:並び替え
Posted: 2009年6月26日(金) 14:35
by ねこ
うろ覚えで自信ないんですがsscanfって半角スペース区切りで取得するんじゃなかったでしたっけ。
答えに近い内容を見ていいのなら最近の質問記事にCSVで1行取得後の質問あったと思いますよ。
参考にしてみては?
Re:並び替え
Posted: 2009年6月26日(金) 14:48
by non
>sscanfは初めて使うんですがどこが間違ってるのでしょうか?
使い方はscanfと同じ。
このままでは、区切りがないので、全部最初の変数に格納されようとするが最初は%dなので、
numberには数字が入るけど、次が%sなので ,"A","山田","国語" 全部がclass_typeに格納される。
,(カンマ)でデータを区切るにはテクニックが必要。
scanfを勉強のこと。
Re:並び替え
Posted: 2009年6月26日(金) 15:17
by 研修生
やっぱそうですか。ねこさんのいうようにファイルの区切りをカンマではなく半角スペースならいけました。
sscanfはカンマにはむいていないのかな。別の方法で模索してみます
type struct{
int number[20];
char class type[20];
char name[8];
char subject[20];
} my;
my data[100];
int main()
{
FILE *fp;
int line = 0;
int field = 0;
int i;
char buf[1000], *str;
char bufG[1000];
if((fp = fopne("test.csv","r")) == NULL){
printf("ファイルopenerror");
}
while(fgets(buf,1000,fp) != NULL){
str = buf;
while(*str != '\0'){
if(*str != ','){
for(i = 0; *str != ',' && *str != '\0'; i++){
bufG = *str;
str++;
}
bufG = '\0';
switch(field){
case 0:
strncpy(data[line].number, bufG , sizeof(data[line.number));
breakk;
case 1:
strncpy(data[line].class_type, bufG , sizeof(data[line.class_type));
breakk;
case 2:
strncpy(data[line].name, bufG , sizeof(data[line.name));
breakk;
case 3:
strncpy(data[line].subject, bufG , sizeof(data[line.subject));
breakk;
}
field++;
}
else{
str++;
}
}
line++;
}
fclose(fp);
return 0;
}
こちらはsscanfを薦められる前に組んでいたプログラムですが
これだと最初の一行だけ値が入っています。
次の行からはstrncpyのところでちゃんとはいっていないようです。
bufGの値はちゃんとなっているのにコピーができていません。
どうしてでしょうか?
Re:並び替え
Posted: 2009年6月26日(金) 15:31
by Mist
> 構造体のint number[20];を配列にしている意味がわからない。
nonさんの指摘のこの指摘は無視?
構造体がCSVデータとマッチしていないよ。
あと、コンマ区切りのデータ読み出しならstrtokとか調べてみればよいかと。
Re:並び替え
Posted: 2009年6月26日(金) 15:46
by non
研修生さんにお尋ねしたいのですが、「研修生」というのはほんとの事ですか。
学生ではないのですよね。
万が一、プログラマやコンピュータ関連の仕事に就くための研修生であるのなら
極力アドバイスを避けたいと思うのですが・・・バグを探すのは自分でやらないと
上達しませんので。「研修生」というのはただの、ハンドルネームで、実際は学生
または仕事に関係がない趣味だというのなら、バグをお教えしたいと思います。
どちらですか。
Re:並び替え
Posted: 2009年6月26日(金) 15:47
by 研修生
あーすいません。そこはコピペったので本プログラムではちゃんとなってます
Re:並び替え
Posted: 2009年6月26日(金) 15:55
by 研修生
学生で研修生というハンドルネームつける理由もないですし、本当に研修生ですよ。
バグは自分で見つけるのが一番いいですがやはり人に聞かなければいけないときもあります。
全部自分でやってたら研修3年ぐらいしなくてはいけません。教える教えないはnonさん次第です。
4月からやってますが覚えれば段々聞くこともへってくるのでいいんじゃないかとおもってます。
Re:並び替え
Posted: 2009年6月26日(金) 15:56
by ねこ
要らぬ一言でバグさんのレスを流す形になってしまった、申し訳ない。
sscanfのカンマ区切りの取得方法はnonさんのおっしゃるようにちょっとしたテクニックでいけました。
フォーマットさえ気を付ければスマートにいけますね。参考になりました。
Re:並び替え
Posted: 2009年6月26日(金) 15:57
by Mist
> あーすいません。そこはコピペったので本プログラムではちゃんとなってます
きちんとしたプログラムを提示しないでバグ教えては虫が良すぎるかと。
だいたい、「ちゃんと」とはどうなっているのですか?
int number;
こう定義しているなら
strncpy(data[line].number, bufG , sizeof(data[line.number));
ここはコンパイルエラーにしかならないですね。(元の定義でも変だけど)
括弧の過不足ぐらいなら何とかなりますけど、こちらは提示されたものの中からしか解析できません。
過去にも手打ちで間違いだらけのプログラムを提示する人がいましたが、問題の解決にずいぶん時間がかかっていました。
まず、打ち間違いのないプログラムを提示することが第一かと。
Re:並び替え
Posted: 2009年6月26日(金) 16:08
by non
了解しました。手を引きます。
Re:並び替え
Posted: 2009年6月26日(金) 16:09
by 研修生
まぁ家忘れてきただけなので常時というわけでもないですが気をつけましょう。
strncpy(data[line].number, bufG , sizeof(data[line].number));
こちらが正しいです。
これだとコンパイルエラーにはなりません。
なんか改行の動作が入っていない気もしますね。
Re:並び替え
Posted: 2009年6月26日(金) 16:52
by 研修生
まぁなんかこの流れだと解答してくれる人がいなくなりそうなので閉めときます。
Re:並び替え
Posted: 2009年6月26日(金) 17:56
by lbfuvab
自分で調べもせず、ソースも見せない。
これではどうしようもないですよ。
医者に行った時、症状も言わず、診断もさせない事と同じです。
どんな医者でも手の打ち様がないです。
Re:並び替え
Posted: 2009年6月26日(金) 18:38
by 研修生
確かに事情があって手打ちになり打ち間違いをしましたが既に打ち間違いは修正しているので
ソースを見せない 呼ばわりされるのも困りますね。
調べもせずとありますがどれのこといってるのでしょうか?調べたとか調べてないとか本人にしかわからない気もするので指摘内容の意味がわかりません。
sscanfはファイルの中のカンマを半角スペースに置き換えてから行なうとかまぁ色々考えてます
というより私がいったこの流れってのはnonさんの非難するわけじゃありませんが
nonさんの意見で、自分で考えさせようという人が増え解答を書くのを抑える人が増えそうなのでいっただけですよ。
Re:並び替え
Posted: 2009年6月26日(金) 18:55
by Mist
> 確かに事情があって手打ちになり打ち間違いをしましたが既に打ち間違いは修正しているので
> ソースを見せない 呼ばわりされるのも困りますね。
どこでですか?
私はnumberの定義がどうなっているな示してくれないので回答をやめていましたが。
回答者:xx間違っていますよ
質問者:打ち間違いです
という不毛なやりとりは誰もしたくないでしょう。
Re:並び替え
Posted: 2009年6月26日(金) 20:47
by バグ
このスレのやり取りにデジャヴを感じるのは私だけではないようですね(^_^;)
Re:並び替え
Posted: 2009年6月27日(土) 10:32
by ねこ
一応突っ込んでおこう。
<strncpy(data[line].number, bufG , sizeof(data[line].number));
<こちらが正しいです。
<これだとコンパイルエラーにはなりません。
strncpyの第一引数にint型配列を渡す事はできません。
Mistさんがおっしゃられてるのは括弧のミスの話じゃなくてそういうことです。
<nonさんの意見で、自分で考えさせようという人が増え解答を書くのを抑える人が増えそうなのでいっただけですよ。
構造体について教えてくださいとはあるけど
「アイディアを下さい」って言ったのは研修生さんなんだから自分で言ってておかしくないですか?
「いや、自分は途中からこういうつもりで聞いてる」と思ってたとしても、
それを明示する文章はレスからは不十分かなと。
<調べもせずとありますがどれのこといってるのでしょうか?調べたとか調べてないとか本人にしかわからない気もするので指摘内容の意味がわかりません。
・strncpyの第一引数にintを渡す
・sscanfをカンマで取得する方法
・strncpyの第三引数が何故かsizeof
これらを見てる限り「十分に調べていない」というのは分かってしまいます。
簡単な質問でも答えてくれる人が居るってのは良い事ですよ。
他所なら「ググれ」「過去ログ読め」で終わる内容だって一杯あります。
今回のだって「C++ CSV 読み込み」これで検索するだけで全部分かります。
Re:並び替え
Posted: 2009年6月29日(月) 10:53
by 研修生
確かにアイデアをくださいといってバグさんからsscanfの助言をもらいました。誤解されているのは
sscanfをカンマで取得する方法ならとっくに調べています。sscanf カンマと検索すればずらりと出てきますしね。向いていないというのはsscanfはあくまで半角スペースで区別するもので別の方法をとらなくてはいけないという軽い言い回しで、無理だから調べず他の方法を探るといったわけでもありません。ただこれ以上は聞かなかったというだけのことです。
そこまでがアイデアについて質問した所の一区切りです。上記のはバグさんから助言をいただくまえに
私が自分でアイデアを出したもの(というか自分で組み立てていたプログラム)に対する質問で、こちらはアイデアをくださいとは関係でございません。まぁ一連の流れで察するのは不可能だと思いますがそういうことです。
変な質問転換になってるので本人以外にはわかりませんね。
strncpyの事に関しては無知もいい所でしたがこちらも私のみすでした
numberの定義は
int numberです。ちゃんと書き直さなかったのが良く無かったですね。まぁこれも間違ってるわけですが。
不毛な言い争いになるのでこの件に関しては他で聞くことにします。
板を汚してしまって申し訳ありませんでした。
Re:並び替え
Posted: 2009年6月29日(月) 21:53
by リリス
なんかスレ主むかつくな・・・