C言語関係掲示板

過去ログ

No800 行ごとの文字列の並べ替え

[戻る] [ホームページ]
No.10279

行ごとの文字列の並べ替え
投稿者---senshou(2003/11/04 06:18:41)


標準入力からテキストファイルを読み込み、
行を辞書順に並べ直して標準出力に出力しなさい。
実行例

入力

Windows
Power Mac
Unix

出力

Power Mac
Unix
Windows

学校の課題で、こんなのを作りたいのですが、さっぱりわかりません。
しばらく考えて見たのですが、
学校では「少しかじったことがある」程度の事しかやっていないため、
糸口すら掴めず、お手上げ状態です。

どなたか、わかりやすく教えてください。



No.10282

Re:行ごとの文字列の並べ替え
投稿者---たか(2003/11/04 10:01:19)


>標準入力からテキストファイルを読み込み、
>行を辞書順に並べ直して標準出力に出力しなさい。

C++だとこのようになります。Cだと行の長さを制限してポインタ配列の
先にstrdup()した入力行をリンクし、qsort()でしょうね。後から時間が
あったら書いてみます。

#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
#include <algorithm>

bool lessString(const std::string& s1, const std::string& s2)
{
  return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end());
}

int main()
{
  std::ifstream ifs("input.txt");
  std::vector<std::string> vs;
  std::string str;
  
  while (std::getline(ifs, str)) vs.push_back(str);
  
  std::sort(vs.begin(), vs.end(), lessString);
  std::copy(vs.begin(), vs.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}


No.10283

Re:行ごとの文字列の並べ替え
投稿者---たか(2003/11/04 10:20:02)


すみません、あまりにも悪ふざけが過ぎました。しかし「辞書順」という
言葉でlexicographical_compareがつい浮かんでしまいました。
Cならこんな感じで。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXLINES 100
#define MAXLENS  100

int cmp(const void *s1, const void *s2)
{
  return strcmp(*(const char **)s1, *(const char **)s2);
}

int main(void)
{
  char *str[MAXLINES];
  char instr[MAXLENS];
  FILE *fi;
  int i = 0, j;
  
  if ((fi = fopen("input.txt", "r")) == NULL) {
    fprintf(stderr, "ファイルが開けません。\n");
    exit(1);
  }
  
  while (fgets(instr, MAXLENS, fi)) {
    str[i] = strdup(instr);
    str[i][strlen(str[i]) - 1] = '\0';
    i++;
  }
  
  fclose(fi);
  
  qsort((void *)str, i, sizeof(char *), cmp);
  
  for (j = 0; j < i; j++) {
    puts(str[j]);
    free(str[j]);
  }
  
  return 0;
}


No.10285

Re:行ごとの文字列の並べ替え
投稿者---たか(2003/11/04 13:08:04)


今見て気が付きました。「ファイルからの入力」ではなくて「標準入力」
からの入力ですね。

プログラムの骨格は出来上がってますから簡単に改造できるでしょう。

No.10295

Re:行ごとの文字列の並べ替え
投稿者---senshou(2003/11/05 00:38:45)


たかさん

返信ありがとうございます。
作っていただいたものを元に、本片手に頑張ってみようと思います。
つまづいてしまい、つまらない質問をしてしまうかもしれませんが、
そのときはよろしくお願いします。

No.10296

Re:行ごとの文字列の並べ替え
投稿者---senshou(2003/11/05 02:52:21)


本を片手にいじってみようとしたのはいいのですが、
どうやら私が知っているのは本当に基礎の基礎のようです(というか、学校で教わったのがそんなもん)。
fopenとからへんを、標準入力に変えれば良いのかな?と思ったのですが、
何をどうしたらいいのか・・・

また誰か助けてください。


No.10297

Re:行ごとの文字列の並べ替え
投稿者---senshou(2003/11/05 03:50:33)


たびたびすみません。
どうにかこうにかやってみた結果がこれです。
どうでしょう?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXLINES 100
#define MAXLENS  100

int cmp(const void *s1, const void *s2)
{
  return strcmp(*(const char **)s1, *(const char **)s2);
}

int main(void)
{
  char *str[MAXLINES];
  char instr[MAXLENS];
  int i = 0, j;

  while (fgets(instr, MAXLENS, stdin)) {
    str[i] = strdup(instr);
    str[i][strlen(str[i]) - 1] = '\0';
    i++;
  }

  qsort((void *)str, i, sizeof(char *), cmp);

  for (j = 0; j < i; j++) {
    puts(str[j]);
    free(str[j]);
  }
  
  return 0;
}




No.10300

Re:行ごとの文字列の並べ替え
投稿者---たか(2003/11/05 10:06:11)


>たびたびすみません。
>どうにかこうにかやってみた結果がこれです。
>どうでしょう?

そうですね。正解です。fopenを取り除き(stdinはmain()起動時には既に
自動的にopenされている)、fiをstdinに替える、ただそれだけです。

ソートの部分がよくわからないかもしれませんが、文字列のソートでは
よく使われる方法で、「文字列を指すポインタ配列をソートする」のです。
なぜかというと、文字列は大抵は長く、しかも可変長で、文字列の交換
をまともにやっていたら大変時間がかかり、しかも配列は一番長い文字列
に合わせて確保しておかなければならないなど、却って面倒になるからで
す。

C++版の方も簡単に説明しておきますと、Cとは全く異なり、STLを使用して
います。std::vectorコンテナとstd::sortアルゴリズムを利用する事によ
り、領域の確保とソートが楽で、std::stringを用いる事により文字列の
長さに事実上制限がなくなっています(実際にはありますが)。

で、この場合本当はstd::lexicographical_compare()は本当は必要なく、
std::less<std::string>()というファンクタを与えるか、デフォルトでは
'<' 比較子がstd::sortに与えられていますので何も書かないか、で済ま
せられます。しかし入力にstd::istream_iterator<std:string>(std::cin)
を使わないのは理由があり、このイテレータは '>>' を入力に使用してい
ますので文字列中にホワイトスペース文字が含まれているとそこで文字列
が分割されてしまうから、使えないのです。

もし文字列中にホワイトスペース文字が含まれない事が保証されていれば

std::copy(std::istream_iterator<std::string>(std::cin), std::istream_iterator<std::string>(), std::back_inserter(vs));

と極めて簡潔に書けます。

今は理解できなくても、C++は実務の世界でかなり使われていますから、
覚えておかれるとよいでしょう。

No.10315

入門書の次
投稿者---senshou(2003/11/06 02:46:24)


たかさん

丁寧な回答本当にありがとうございました。
まだまだ、知識すら全然ないのでこれからもがんばります。

それでC言語の本は
「C言語プログラミングレッスン 入門編」(結城 浩 / SOFTBANK)
をやったのですが、次に読むお薦めの書籍などはありますでしょうか?

No.10318

Re:入門書の次
投稿者---たか(2003/11/06 10:22:56)


>それでC言語の本は
>「C言語プログラミングレッスン 入門編」(結城 浩 / SOFTBANK)
>をやったのですが、次に読むお薦めの書籍などはありますでしょうか?

最近私はC++関連ばかり読んでいてCのお勧めの本は?と聞かれるとわから
ない状況です。しかししっかりした著者がおられます。柴田望洋先生です。
HPはここ

この先生はとても初心者寄りに丁寧に書いておられ、しかも間違いが少な
い事で有名です。「明快C言語 入門編・実践編」「秘伝C言語問答 ポイ
ンタ編 第2版」などはいかがでしょか。
柴田先生の本にはたくさん問題がついていて、それを自力で解くことによ
り力が付きます。

私も柴田先生の「プログラミング言語C++例題演習」という本を復習の為に
読んでいた事があります。

なお、私は柴田先生の回し者でもなんでもありませんので。個人的に好き
なだけです。

No.10341

Re:入門書の次
投稿者---tkc(2003/11/06 21:13:41)


アルゴリズムの本がお勧めです。
個人的にはセジウィックの『アルゴリズムC++』がお勧めです。
探せば、たぶんC言語のみで書かれているアルゴリズムの本もあると思います

No.10348

Re:入門書の次
投稿者---たいちう(2003/11/07 09:21:55)


> アルゴリズムの本がお勧めです。
> 個人的にはセジウィックの『アルゴリズムC++』がお勧めです。
> 探せば、たぶんC言語のみで書かれているアルゴリズムの本もあると思います

セジウィックの『アルゴリズムC〈全3巻〉』でしょうか?
C++の方は読んだことがないのですが、アルゴリズムCは確かに良書だと思います。
ただ質・量共に歯ごたえがあるので、私も1部しか読んでませんが。

No.10350

Re:入門書の次
投稿者---たか(2003/11/07 12:52:18)


>> アルゴリズムの本がお勧めです。
>> 個人的にはセジウィックの『アルゴリズムC++』がお勧めです。
>> 探せば、たぶんC言語のみで書かれているアルゴリズムの本もあると思います
>
>セジウィックの『アルゴリズムC〈全3巻〉』でしょうか?
>C++の方は読んだことがないのですが、アルゴリズムCは確かに良書だと思います。
>ただ質・量共に歯ごたえがあるので、私も1部しか読んでませんが。

私もセジウィックの『アルゴリズムC〈全3巻〉』を持っています。
一年ほど前に『アルゴリズムC++』に新刊として1冊にまとめられたよう
です。時代がC++なのはわかるけど、これはCとして出して欲しかったで
すね。

C++になるとclassとかreferenceとかCユーザーがすぐには理解できない
概念が出てきますし、大抵のアルゴリズムは algorithm.h の中に入って
いますからねえ。

No.10362

ありがとうございました
投稿者---senshou(2003/11/08 02:32:14)


出してもらった意見を参考に、
本屋で見てこようと思います。

ありがとうございました