ファイルの中身のソート – プログラミング – Home

ファイルの中身のソート
 
通知
すべてクリア

[解決済] ファイルの中身のソート

固定ページ 1 / 2

エハラ
 エハラ
(@エハラ)
ゲスト
結合: 23年前
投稿: 4
Topic starter  

はじめまして、エハラと申します。
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);
}


引用未解決
トピックタグ
tib
 tib
(@tib)
ゲスト
結合: 24年前
投稿: 468
 

このソースでは、ソートを試みているようには見えないのですが。

・2つの文字列を比較してどちらが大きいかをチェックする関数を別に作る
・入力ファイルの内容を1行ずつ、全て読み込んで1つの配列に格納する
・qsort()を使ってソートする
・ソート済みの配列を出力ファイルに書き出す

という手順になると思います。


返信引用
エハラ
 エハラ
(@エハラ)
ゲスト
結合: 23年前
投稿: 4
Topic starter  

tibさんのおっしゃる通りでソートは試みてないです。T_T
ファイル開いてからどのようにソートして新しいファイルを作成すればよいかが分からないので
す。どうか教えてください。
よろしくお願いします。


返信引用
YuO
 YuO
(@YuO)
ゲスト
結合: 24年前
投稿: 252
 

一旦メモリに蓄えてqsort呼び出すのが簡単だと思いますよ。


返信引用
暇人貴子
 暇人貴子
(@暇人貴子)
ゲスト
結合: 23年前
投稿: 11
 

qsort()の仕様については調べられましたか?
>・2つの文字列を比較してどちらが大きいかをチェックする関数を別に作る
この関数をqsortの引数に渡してやることで、コールバックされます。
ですので、strncmp等を使ってキーとなるオフセットの位置の文字列の大小を
比較してあげればよいのでは?
もちろん、strncmpで比較する前にキーが0000だったときの処理が必要ですが・・・


返信引用
wood
 wood
(@wood)
ゲスト
結合: 24年前
投稿: 895
 

最初のハンドル名と違うけど エハラミホ さんは質問者と同一人物なんですよね

1.ファイルオープンする
2.読み込み(格納はしない) レコード件数のカウントするだけ
3.ファイル クローズ
4.件数分格納できるだけの領域を用意する
5.ファイルオープンする
6.読み込み(4で用意した領域へ格納する)
7.ファイルクローズ
8.あなたが知っているバブルソートで4で用意した領域内のデータをソートする
  qsortでもいいですけどご自分の理解可能なほうでどうぞ

9.出力ファイル オープン
10.ソート結果の4で用意した領域から1レコード分づつ出力ファイルへ書き込む
11.出力ファイルクローズする
12.終了


返信引用
エハラ
 エハラ
(@エハラ)
ゲスト
結合: 23年前
投稿: 4
Topic starter  

はい、同一人物ですよ。江原美帆です。
こんなんで良いのですかね?頭がぐるぐるです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;
}


返信引用
エハラ
 エハラ
(@エハラ)
ゲスト
結合: 23年前
投稿: 4
Topic starter  

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);
}
(


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 23年前
投稿: 1301
 

> qsortはこんな感じでよいのでしょうか。

やってみてはいかがです?


返信引用
RAPT
 RAPT
(@RAPT)
ゲスト
結合: 23年前
投稿: 310

返信引用
wood
 wood
(@wood)
ゲスト
結合: 24年前
投稿: 895
 

多分だめだね
>ソート後ファイル名 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);

実際にやってみてエラーが出たり、コンパイルエラー解決できなかったら
また相談に乗りますよ


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 23年前
投稿: 1301
 

ご参考: 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

...できた^^;


返信引用
wood
 wood
(@wood)
ゲスト
結合: 24年前
投稿: 895
 

この人
>Cでファイルを読込み
って きちんとC言語でって断ってますけど
エハラ さんの提示しているソースにもC++でのコーディング入っていない
とおもいますが

επιστημη さんのは 参考になるんでしょうか
答え方勘違いしてませんか?


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 23年前
投稿: 1301
 

あ....ごめんなさい。

では上記C++コードでやっていること:

[1] ソート対象外である要素を配列の端に追い詰める
[2] と同時に、ソート対象である要素は配列のどこまでかを調べる。
[3] 配列の先頭から[2]までをソートする。

これなら Cで実装する参考になるかしら。


返信引用
エハラミホ
 エハラミホ
(@エハラミホ)
ゲスト
結合: 23年前
投稿: 2
 

いろいろありがとうございます。
いろんな方に教えていただき解決することができました。
また何かあった時はよろしくお願いします。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました