質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.25%

文字列の辞書順ソートで出力されない

受付中

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 163

hnk_ll

score 9

質問内容

C言語で,文字列の辞書順ソートをした一番若い者を出力したいのですが,入力をしても何も出力されませんでした。
またwhileのあとにprintf("%s\n",str[0]);としても何も起こりませんでした。
これはもう最初から入力が出来ていないということだと思うのですが,どこを直せばいいのか教えてください。
よろしくお願いいたします。

問題

英単語が1個以上の空白類(空白または改行)で区切られて並んでいるとする。入力の中で辞書順で一番若い単語(通常の英語辞書の見出しとして最も前にくる単語)を出力するプログラムを作れ。ただし,英字はすべて小文字に置き換えて扱え。

入力

標準入力がキーボードから行われるときは、入力の最後に C-d を入力する。

出力

出力は、その英単語だけを1行として書き出せ。

入力例1
first 
second third
third
出力例1
first

入力例2
one two one
three 
four
出力例2
four

書いたコード

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int scmp(const void *a, const void *b){
    return strcmp(*(char**)a, *(char**)b);
}

int main(void){
    char str[1000][1000];
    int i=0;
    while(scanf("%s",str[i])!=EOF) i++;
    printf("%s\n",str[0]);

    qsort(str,i,sizeof(char*),scmp);
    printf("%s\n",str[0]);

    return 0;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

0

  qsort(str,i-1,sizeof(char*),scmp);

qsort関数の第3引数がポインタのサイズになってしまっています
これではだめですね

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/22 21:39

    その部分はどう直せばいいのか教えていただけると幸いです。
    よろしくお願いいたします。

    キャンセル

  • 2020/05/23 18:01

    よくみるといろいろスカなところがありますが、
    それはまず横に置いといて、ここの部分だけでいうと、
    qsort(str,i,sizeof(str[0]),scmp);
    ですかね

    キャンセル

0

char str[10000][100000];
スタック領域を、大きく超えてしまいそうです。
(unix系なら大丈夫かもしれませんが、普通一般ユーザーは制限されています)

char str[10000][100000];
int main(void){
と、外部変数にしましょう。
出来ればもっと減らしましょう。

前出 qsort関数の呼び出し方が違うのもそのとおりです。
多分、第2引数の i-1 は i だけでいい気はします。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/22 15:09

    この数にする前は適当にもっと大きい数にしてたらエラーになっていたのはそういう理由だったのですね。
    数を減らして外に出すことにします。
    呼び出し方はどのようにするのがいいのか教えていただけると幸いです。
    またiについては確かにi-1だと1足りないです、ご指摘ありがとうございます。

    キャンセル

  • 2020/05/22 17:32

    >呼び出し方はどのようにするのがいいのか
    領域の確保の仕方は違いますが。
    参照範囲が一つ外になっただけですから。
    同じで大丈夫です。

    キャンセル

  • 2020/05/23 10:15

    外部変数にして、i-1をiに直したのですが,出力がなにもありませんでした。
    これの他にどこを直せばいいのか見当は付きますでしょうか?
    よろしくお願いします。

    キャンセル

0

char str[10000][100000]; を char str[1000][1000]; に変更して
領域が確保できない問題は解決されました。

でも、なぜ 1000 にしたのか説明できますか?
100000 は大きすぎるから 1000 にしただけですか?

一つの文字列(英単語) の長さが 1000 に近いことってあるでしょうか?
辞書に載っている最も長い単語とされているのが
pneumonoultramicroscopicsilicovolcanoconiosis
で、これでも 45文字です。
char str[1000][50]; で十分でしょう。

次にソートですが、並べ替えたいものは 英単語が入っている
50バイトの領域です。これが i 個あるのです。

qsort の呼び出しの第3引数には、sizeof(char[50])
または sizeof(str[0]) または sizeof(*str) と書かなければなりません。

scmp の引数の a と b は比較したい英単語の入った 50バイトの領域のアドレスです。

strcmp は const char * の引数を要求しますが、
C では void * から char * への暗黙の変換ができるので、
return strcmp(a, b); と書くことができます。

strcmp(*(char**)a, *(char**)b); と書かなければならないとすれば、
それは元のデータが char *str[1000]; と宣言された場合の話です。
その場合は qsort の第3引数も sizeof(char*) となります。
またデータの入力方法は次のようになります。

    char *str[1000];
    char buf[50];
    int i = 0;
    while (scanf("%s", buf) == 1) str[i] = strdup(buf);

ここまでは理解できましたか?
コードを修正して思い通りに動きましたか?

さて、この問題ですが、ソートは不要です。
辞書順で一番若い単語を求めるだけですから、
ひとつの単語を読み込むたびに、それまでの一番若い単語と比較して
一番若い単語を更新すれば済みます。
そういうコードを書いてみてください。

そしてそれを質問に追記してください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/23 15:22

    解説ありがとうございました。
    1000はおっしゃる通り、なんとなく0を減らしただけでした。というのも単語が実在するものとは限らず,100を超えたら,と考えてなにも工夫せず1000にしてしまいました。

    また、あまり関係のない話になるのですが大文字は小文字よりも若い扱いを受けるのですね。なので大文字を小文字に変換する部分を新たに付け加えました。

    ご助言のおかげで思い通り動かせたので、最後に書かれているやり方にも挑戦してきます。辞書順と指定されてすぐにsortに行くのは短絡的なのですね。とても勉強になります。

    コードを書くのに少々お時間を頂くことになりますが,書き終わりましたらぜひチェックの方,よろしくお願いいたします。

    キャンセル

  • 2020/05/23 15:33

    コード書き終わりました。
    よろしくお願いいたします。
    ```
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    char str[50];
    int main(void){
    char ans[50]="zzzzzzzzzzzzzz";
    while(scanf("%s",str)!=EOF) {
    if(strcmp(ans,str)>0) strcpy(ans,str);
    }
    printf("%s\n",ans);
    return 0;
    }```

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.25%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる