質問: 簡単なプログラミングだと思うのですが,どうしてもうまくいかないので質問させていただきます. C言語またはC++において,txtかcsvファイルの内容を1行ごとに読み込んで,重複している行が複数あった場合,他を削除し1行のみにするプログラムを作成したいです. txt,csvファイルは具体的には,以下のようになっています. ``` About IN about Ada NP Ada Additional JJ additional Adventures NNS adventure Adventures NNS adventure Adventures NP ``` 上記の例においては,`Adventures NNS adventure` という行を1行削除したいです. すでにソートはされており,アルファベット順に並んでいるので,重複する行がある場合は必ず隣り合っています. 行数は30000行近くあります. ``` while(fgets(buf,20,fp)!=NULL){ strcpy(word[i], buf); printf("%s\n",word[i]); i++; } ``` などのように,何種類かファイル読み込みを試してはみましたが,2行にまたがって読み込んだり変なところで改行されたりで,うまくいきませんでした. 読み込みができたら,「次の行と比較して違った場合のみ出力する」などとすれば実現できるかなと考えています. アドバイスをよろしくお願いいたします.
回答: アドバイスをということなので問題点の指摘に留まりますがこんな感じでしょうか。 1. 読み込んだ文字列が1行分の文字列かどうかを判定しなければいけません。 * 1行に満たない場合はもう一度 `fgets()` で読み込み、バッファ(質問のコードだと`word[i]`) の末尾に連結します。 * この時、`word[i]` に確保した領域が足りてるかどうか判定が必要です。 足りなければ `realloc` を使って再割当てするなど対策をします。 2. 一行分の文字列の読み込み後、前の行の文字列(以降 前回値と書きます)と 比較します。 * 一致する場合は何もせず次のループに移ります。 * 一致しない場合は 読み込んだ文字列を出力して、前回値を指す変数に複製します。 * この時、前回値に 確保した領域が足りているかどうか判定が必要です。 メモリ領域が足りる/足りないについては、考えられる最大長のバッファサイズを固定長でとっても良いと思います。その代わり、それがプログラムの制限事項になりますので目的に有っているか注意が必要です。 前回値を指す変数に代入の部分で、文字列コピーが遅いのを気にする場合は、バッファを2つ用意し、それぞれを指すポインタを交換(Swap)すると良いでしょう。 後は UNIX の `uniq` コマンドのソースを読むと色々と勉強になると思います。 GNU coreutils もし実用性を求めてるのでしたら `uniq` コマンドを使うか、Windows なら PowerShellの`Get-Unique` を使えばいいと思います。