秘密基地、どこに作った?

こんばんは。
大変お世話になっています。
このコミュニティーでの質問ではないかもしれませが・・・

テキストファイルに出力された、1番から10000番までの番号の中で重複している番号を抜き出すツールや方法はありますでしょうか?
また、プログラムとして、記述可能でしょうか?
よろしくお願い致します。

A 回答 (4件)

★プログラムとして記述するのですか?


・ソートされたデータならば、もしくはソートできるデータならば簡単に重複行をカットまたは、抽出できます。
・でも、データ位置を保存したままで重複行をチェックするには少し工夫が必要です。
・一番簡単な重複行チェックのアルゴリズムを教えます。

●アルゴリズム(一例)
・テキストファイルを行単位でメモリへ格納します。→10,000行
・メモリへ格納した行データは、文字列のポインタ配列で管理します。
・この配列を『qsort』などでソートします。分かりますか?
・そしたら、1行目から順番に次の行データが『重複』している番号かをチェックします。
・チェックした結果、同じ番号ならばその行を『抜き出す』処理をします。

●サンプル(一例)
void main( void )
{
 char *alloc;
 char *line[ 20000 ]; ←テキストの最大行数(2万行)
 char buff[ 1024 ]; ←1行の最大バイト数
 int max = 0;
 int now;
 FILE *fp;
 
 if ( (fp = fopen("filename.txt","r")) != NULL ){
  while ( fgets(buff,sizeof(buff),fp) != NULL ){
   if ( (alloc = malloc(strlen(buff) + 1)) == NULL ){
    printf( "メモリ不足です.\n" );
    break;
   }
   if ( max >= 20000 ){
    printf( "行数が多すぎます.\n" );
    break;
   }
   line[ max++ ] = strcpy( alloc, buff );
  }
  line[ max ] = NULL;
  fclose( fp );
  
  qsort( line, max, sizeof(char*), MySortComp ); ←ソート比較関数(自作しましょう)
  MyDoubleExtract( line, max ); ←ここで重複行チェック(printfで出力)
  
  for ( now = 0 ; now < max ; now++ ){
   free( line[now] ); ←メモリ解放
  }
 }
}

最後に:
・上記のサンプルは、テキストファイルを行単位で読み込む部分のみです。
・ソート部分と、重複行チェックは質問者さんが作って下さい。→頑張ってね。
・『MySortComp』関数は、ソートするときの比較関数です。→qsort関数の使い方を参照。
・『MyDoubleExtract』関数が、重複行をチェックして出力する関数です。→上記のアルゴリズム参照。
・以上。おわり。

参考URL:http://www.bohyoh.com/CandCPP/FAQ/FAQ00047.html
    • good
    • 0
この回答へのお礼

こんばんわ。
返信ありがとうございます。
ソートはしていませんが、テキストファイルを1行ずつ読み込み、int型配列を用いて番号をいれ、重複箇所をチェックし、カウントするというプログラムを作りました。

Oh-Orangeさんのおっしゃるとおりの方法(ソートはできていませんが)で解決できました。

ありがとうございました。

お礼日時:2007/01/15 03:50

プログラムとして書くことができなければツールも存在しないわけで、


もちろん記述は可能です。

残念ながらひとつのツールで済ませることはできませんが、#1の方の仰るとおり
複数のツールを組み合わせて実現できます。
sort/uniq/sed はUNIXであれば間違いなくあるはずですが、Windowsでも
移植されたものや同等のものがあります。

またプログラムを書くとして、それはCまたはC++で書くことが必須なのでしょうか? awkだとかPerl/Ruby/Pythonといったものを使って済ませることができます。
これもUNIXならほぼインストールされていると考えられますし、Windowsでも
移植されているものがあります(それをインストールする手間がありますが)。

1~10000の番号がどのようにテキストファイルに置かれているのかが不明なのですが、
一行にひとつの番号という前提を置いていいなら awkで

{
numbers[$1]++
}
END {
for (i in numbers) {
if (numbers[i] > 1)
print i
}
}

重複している番号を抜き出せばいいだけならこれだけです。
どれぐらい重複していたとか、番号順で並べたいというなら
もうちょっと手間がかかりますがそんなに行数は増えません。

sortf (win)(Windows95/98/Me / ユーティリティ)
http://www.vector.co.jp/soft/win95/util/se000882 …
コマンドラインツール - WindowsをUNIXっぽく
http://qwerty777.s57.xrea.com/winunix/command.htm
    • good
    • 0
この回答へのお礼

返信ありがとうございます。
1から10000までの番号順は1から10000まで、番号順にならんでいます。
Cでプログラムを作り解決することができました。
ありがとうございました。

お礼日時:2007/01/15 03:52

std::sortで整列してからstd::unique(またはstd::unique_copy)で重複要素を取り除くというのは?

    • good
    • 0

どのように出力されているかとかどのような環境なのかにもよりますが, 「普通の UNIX の環境でかつ各行に 1個ずつ番号がある」と

いう状況だと sort + uniq + sed でいけますね.
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報