はじめまして、エハラと申します。
Cでファイルを読込み、ファイルの中身をソートしなおして新しいファイルを作成したいのですがどうす
ればよいのでしょうか?教えてください。
よろしくお願いします。
下記みたいな感じで今頑張ってますが、どうやってソートすればよいか分かりません。ただのバ
ブルソートなら分かるんですが、レコードの97~100まででソートして新しいファイルを作成って言
うのが???
97~100には必ず値が入っています。0001~9999までで、0000も入っています。
1レコード256+CRLFです。
元ファイル名 AA.dat
1レコード目.~0003
2レコード目.~0000
3レコード目.~0002
4レコード目.~0001
5レコード目.~0000
こんな感じです。0000以外は複数入っていません。
これを
ソート後ファイル名 BB.dat
1レコード目.~0001
2レコード目.~0002
3レコード目.~0003
4レコード目.~0000
5レコード目.~0000
の順番にしたいのです。
int main(int argc, char *argv[])
{
FILE *fin,*fout; // ファイルポインタ
char s[258];
char dum[30960];
char f[256];
int iRtn = 0;
int b,e,d,i;
int iLoop = 0;
char a;
char c;
printf(argc= %d \n,argc);
memset(&s[0], 0x00, 258);
memset(&dum[0], 0x00, sizeof(dum));
if (argc == 3){
//File open
i = 0;
if( (fin=fopen( argv[1], r ))==NULL) {
/* 入力ファイルオープン */
printf(ファイルの中身を確認して下さい。\n);
exit(1);
}
if( (fout=fopen( argv[2], w ))==NULL) {
/* 出力ファイルオープン */
printf(出力ファイルがオープンできません\n);
exit(1);
}
while(fgets(s,256,fin)!=NULL) {// 入力ファイルから読み込んだデ
ータを //
printf(out b = %d\n,b); //100byte目をチェック
fputs(s,fout); //出力ファイルに書き込み
}
printf(0 :%s \n,argv[0]);
b = 0;
while(fgets(s,258,fin)!=NULL) {
printf(inner = %x b = %d\n,s[99],b); //100byte目をチ
ェック
iRtn = (strncmp(&s[96], 0000, 4));
strncpy((char *)&dum ,&s[96],4);
if (iRtn != 0){//97~100までが0000以外の時
printf(inner = %d b = %d% d\n,dum,b,iRtn);
}
b = b+1;
}
while(fgets(s,256,fin)!=NULL) {
printf(out b = %d\n,b);
fputs(s,fout);
}
}
else{ // 引数が3以外のとき
exit(1);
}
fclose(fin);
/* 入力ファイルクローズ */
fclose(fout);
/* 出力ファイルクローズ */
return(0);
}
このソースでは、ソートを試みているようには見えないのですが。
・2つの文字列を比較してどちらが大きいかをチェックする関数を別に作る
・入力ファイルの内容を1行ずつ、全て読み込んで1つの配列に格納する
・qsort()を使ってソートする
・ソート済みの配列を出力ファイルに書き出す
という手順になると思います。
tibさんのおっしゃる通りでソートは試みてないです。T_T
ファイル開いてからどのようにソートして新しいファイルを作成すればよいかが分からないので
す。どうか教えてください。
よろしくお願いします。
一旦メモリに蓄えてqsort呼び出すのが簡単だと思いますよ。
qsort()の仕様については調べられましたか?
>・2つの文字列を比較してどちらが大きいかをチェックする関数を別に作る
この関数をqsortの引数に渡してやることで、コールバックされます。
ですので、strncmp等を使ってキーとなるオフセットの位置の文字列の大小を
比較してあげればよいのでは?
もちろん、strncmpで比較する前にキーが0000だったときの処理が必要ですが・・・
最初のハンドル名と違うけど エハラミホ さんは質問者と同一人物なんですよね
1.ファイルオープンする
2.読み込み(格納はしない) レコード件数のカウントするだけ
3.ファイル クローズ
4.件数分格納できるだけの領域を用意する
5.ファイルオープンする
6.読み込み(4で用意した領域へ格納する)
7.ファイルクローズ
8.あなたが知っているバブルソートで4で用意した領域内のデータをソートする
qsortでもいいですけどご自分の理解可能なほうでどうぞ
9.出力ファイル オープン
10.ソート結果の4で用意した領域から1レコード分づつ出力ファイルへ書き込む
11.出力ファイルクローズする
12.終了
はい、同一人物ですよ。江原美帆です。
こんなんで良いのですかね?頭がぐるぐるですT_T
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFLEN 300
int cmp(const void *c1, const void *c2);
int main(int argc, char *argv[])
{
FILE *fin, *fout;
int i, size;
char buf[BUFLEN], *line;
if (argc != 3) exit(1);
if ((fin = fopen(argv[1], r)) == NULL) { /* 入力ファイルオープン */
printf(入力ファイルがオープンできません\n);
exit(1);
}
fseek(fin,0,SEEK_END); /* ファイルの末尾にシーク */
size=ftell(fin)+1; /* 現在の位置を取得 */
rewind(fin); /* ファイル先頭にまき戻す */
if ((line = (char **)malloc(sizeof(char *) * size)) == NULL) exit(1);
for (i = 0; i < size; i++)
//sort
if ((fout = fopen(argv[2], w)) == NULL) { /* 出力ファイルオープン */
printf(出力ファイルがオープンできません\n);
exit(1);
}
fclose(fout);
free(line);
return 0;
}
qsortはこんな感じでよいのでしょうか。
って、helpに載っていたまんまなんです.........
~
qsort(line, lc, sizeof(char *), cmp);
~
int cmp(const void *c1, const void *c2)
{
return strncmp((const char *)c1 , (const char *)c2 , 4);
}
(
> qsortはこんな感じでよいのでしょうか。
やってみてはいかがです?
多分だめだね
>ソート後ファイル名 BB.dat
>1レコード目.~0001
>2レコード目.~0002
>3レコード目.~0003 ←ここと①
>4レコード目.~0000 ←ここ ②
>5レコード目.~0000
>の順番にしたいのです。
出力したい大小関係が ①と②で逆転しているでしょ
>RAPT 2003/02/07(金) 02:37:20
> http://www.bohyoh.com/CandCPP/FAQ/FAQ00047.html
参考に、多少のアルゴリズム付け加えないとだめですよ
だから私は皆さんが「qsort」と書いているのを
あえて「バブルソート」と書いたつもりだったんですけどね
実は「バブルソート」のアルゴリズムもわからないのでは?
>8.あなたが知っているバブルソートで4で用意した領域内のデータをソートする
>1レコード256+CRLFです。
この条件はどこへ行っちゃったの「size」がギガ単位だったらどうなるの?
>if ((line = (char **)malloc(sizeof(char *) * size)) == NULL) exit(1);
実際にやってみてエラーが出たり、コンパイルエラー解決できなかったら
また相談に乗りますよ
ご参考: C++版サンプル
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <functional>
int main() {
std::vector<int> v;
for ( int i = 0; i <9; ++i ) {
v.push_back(9-i);
v.push_back(0);
}
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, ));
std::cout << std::endl;
std::vector<int>::iterator position =
std::partition(v.begin(), v.end(),
std::bind1st(std::not_equal_to<int>(),0));
std::sort(v.begin(), position);
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, ));
std::cout << std::endl;
return 0;
}
--- 結果 ---
9 0 8 0 7 0 6 0 5 0 4 0 3 0 2 0 1 0
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 0 0 0
...できた^^;
この人
>Cでファイルを読込み
って きちんとC言語でって断ってますけど
エハラ さんの提示しているソースにもC++でのコーディング入っていない
とおもいますが
επιστημη さんのは 参考になるんでしょうか
答え方勘違いしてませんか?
あ....ごめんなさい。
では上記C++コードでやっていること:
[1] ソート対象外である要素を配列の端に追い詰める
[2] と同時に、ソート対象である要素は配列のどこまでかを調べる。
[3] 配列の先頭から[2]までをソートする。
これなら Cで実装する参考になるかしら。
いろいろありがとうございます。
いろんな方に教えていただき解決することができました。
また何かあった時はよろしくお願いします。
