

簡単なプログラミングだと思うのですが，どうしてもうまくいかないので質問させていただきます．  
C言語またはC++において，txtかcsvファイルの内容を1行ごとに読み込んで，重複している行が複数あった場合，他を削除し１行のみにするプログラムを作成したいです．  
txt,csvファイルは具体的には，以下のようになっています．

[code]

    About   IN  about
    Ada NP  Ada
    Additional  JJ  additional
    Adventures  NNS adventure
    Adventures  NNS adventure
    Adventures  NP  <unknown>
    
[/code]

上記の例においては，`Adventures NNS adventure` という行を１行削除したいです．  
すでにソートはされており，アルファベット順に並んでいるので，重複する行がある場合は必ず隣り合っています．  
行数は30000行近くあります．

[code]

    while(fgets(buf,20,fp)!=NULL){
        strcpy(word[i], buf);
        printf("%s\n",word[i]);
        i++;
    }
    
[/code]

などのように，何種類かファイル読み込みを試してはみましたが，２行にまたがって読み込んだり変なところで改行されたりで，うまくいきませんでした．  
読み込みができたら，「次の行と比較して違った場合のみ出力する」などとすれば実現できるかなと考えています．  
アドバイスをよろしくお願いいたします．


CC BY-SA 3.0
2015-11-06T04:09:21.370
18457
2015-11-06T09:39:06.970
2015-11-06T04:16:35.357
13125
question
c++ c
CまたはC++において，txtかcsvファイルを1行ごとに読み込み重複する項目を削除するプログラムを作成したい


そもそも「文字単位の読み込み」であるfgets()を使っている事が不適切ですね。  
「行単位の読み込み」の関数が複数あるのでそっちを使いましょう。


CC BY-SA 3.0
2015-11-06T07:15:37.250
18463
2015-11-06T07:15:37.250
4268
18457
answer


アドバイスをということなので問題点の指摘に留まりますがこんな感じでしょうか。

  1. 読み込んだ文字列が1行分の文字列かどうかを判定しなければいけません。 
    * 1行に満たない場合はもう一度 `fgets()` で読み込み、バッファ(質問のコードだと`word[i]`) の末尾に連結します。
    * この時、`word[i]` に確保した領域が足りてるかどうか判定が必要です。  
足りなければ `realloc` を使って再割当てするなど対策をします。

  2. 一行分の文字列の読み込み後、前の行の文字列（以降 前回値と書きます）と 比較します。 
    * 一致する場合は何もせず次のループに移ります。
    * 一致しない場合は 読み込んだ文字列を出力して、前回値を指す変数に複製します。
    * この時、前回値に 確保した領域が足りているかどうか判定が必要です。

メモリ領域が足りる／足りないについては、考えられる最大長のバッファサイズを固定長でとっても良いと思います。その代わり、それがプログラムの制限事項になりますので目的に有っているか注意が必要です。

前回値を指す変数に代入の部分で、文字列コピーが遅いのを気にする場合は、バッファを2つ用意し、それぞれを指すポインタを交換（Swap）すると良いでしょう。

後は UNIX の `uniq` コマンドのソースを読むと色々と勉強になると思います。  
[GNU coreutils](http://ftp.gnu.org/gnu/coreutils/)

もし実用性を求めてるのでしたら `uniq` コマンドを使うか、Windows なら PowerShellの`Get-Unique`
を使えばいいと思います。


CC BY-SA 3.0
2015-11-06T09:39:06.970
18472
2015-11-06T09:39:06.970
5008
18457
answer