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

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

新規登録して質問してみよう
ただいま回答率
86.02%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

受付中

文字配列のソートと空白文字の対応

jikijikidon
jikijikidon

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

5回答

0グッド

0クリップ

458閲覧

投稿2022/11/25 03:37

大学にてC言語を学んでいます。
以下、問です。
英小文字だけからなるアルファベットの文字列を a から昇順に並べ替えるプログラムを作成しなさい
なお,このプログラムは空白も無視せず並べ替えの対象となるようにしなさい

入力

  • 英小文字だけからなるアルファベットの文字列(50文字まで対応)
  • 標準入力から読み込む

出力

  • aから昇順に並べかえられた文字列
  • 標準出力に書き出す
  • スペースの出力はハイフン - に置換する

条件として、

  • 配列は2つ使用してよい
  • for文やwhile文など,反復は入出力処理を除き1つまで
  • 変数は配列を除き4つまで(3つでも可能)
  • コードはできるだけ18行以内におさめること(コメントや空行,括弧だけの行などは除く)
  • if文などの条件分岐は用いない
  • 入力文字列の長さは50文字まで対応すること
  • フラグを用いた処理はしない

for2つの場合はできるのですが…1つに制限されてしまって困っています。また、qsort関数などを使用せず組むやり方も可能であればよろしくお願いします。

以下のような質問にはグッドを送りましょう

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

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

気になる質問をクリップする

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

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

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

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

適切な質問に修正を依頼しましょう。

jimbe

2022/11/25 03:53 編集

>for2つの場合はできるのですが 出来ているコードをご提示願えますか。 それと、用いる文字コード(シフトJIS とか Unicode とか EBCDIC とか) は何前提でしょう。
fana

2022/11/25 04:02

> 空白も無視せず並べ替えの対象となるように 空白は並べ替えた結果としてはどこに行けばいいのか? 例えば入力が "b_a" のとき(←のアンダーバーが空白なのだとして)出力は "a-b" "-ab" "ab-" のどれになるのか?
episteme

2022/11/25 04:05

> 英小文字だけからなるアルファベットの文字列 > 空白も無視せず並べ替えの対象となる 英小文字だけからなるのなら、空白を含まないのでは?
jikijikidon

2022/11/25 04:10

文字コードはASCIIコードを用います。 実行例を出すのを忘れていました。申し訳ないです。 以下、実行例です。 super califragilistic expiali docious ---aaacccdeefgiiiiiiillloopprrssstuux
jimbe

2022/11/25 06:59 編集

50文字の入力→50文字のソートでは無く、[1文字の入力→1文字(とそれまでの入力)のソート]を50回と言うのはセーフでしょうか?

回答5

0

C

1#include <stdio.h> // fgets, putchar 2#include <string.h> // strlen 3 4int main(void) 5{ 6 char s[53]; 7 fgets(s, 52, stdin); 8 int i, n = strlen(s) - 1; 9 for (i = 0; i < n*n; i++) 10 i/n < i%n && s[i/n] > s[i%n] && 11 (s[52] = s[i/n], s[i/n] = s[i%n], s[i%n] = s[52]); 12 for (i = 0; s[i]; i++) putchar((s[i]==' ')*'-' + (s[i]!=' ')*s[i]); 13}

どこが分からないのかをコメントしてください。
追記
ソートをバブルソートに変えてみると、

C

1#include <stdio.h> // fgets, putchar 2#include <string.h> // strlen 3 4int main(void) 5{ 6 char s[53]; 7 fgets(s, 52, stdin); 8 int i, n = strlen(s) - 1; 9 for (i = 0; i < n*n; i++) 10 i%n && s[i%n-1] > s[i%n] && 11 (s[52] = s[i%n-1], s[i%n-1] = s[i%n], s[i%n] = s[52]); 12 for (i = 0; s[i]; i++) putchar((s[i]==' ')*'-' + (s[i]!=' ')*s[i]); 13}

投稿2022/11/25 22:02

編集2022/11/26 07:47
kazuma-s

総合スコア8087

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

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

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

このような回答には修正を依頼しましょう。

0

条件を満たすために
main() 内は気合で27個処理を並べることでループを1個潰したけど,
F() の中身が条件に抵触するか否か…?

C

1int H[ 2 + 26 ] = { 0 }; //配列1個目 2int Idx( char c ){ return (c==' ')*27 + ('a'<=c && c<='z')*(c-'a'+1); } //文字cに対応する H[] のindexを返す 3 4//配列の中身を書き換える作業. 5//sの指す先からn文字をcに変えて,その次の位置を返す 6char *F( char *s, char c, int n ) 7{ 8 *s = (n<=0)**s + (n>0)*c; 9 return ( n<=0 ? s : F(s+1,c,n-1) ); //ココが「if等の条件分岐」や「反復」と見なされるならアウト 10} 11 12//これは H[] の値を用いての F を呼び出しを簡単に書くだけのヘルパ. 13void G( char **s, char c ){ *s = F( *s, c, H[Idx(c)] ); } 14 15int main() 16{ 17 char Str[50+1]; //配列2個目 18 gets_s( Str, 50 ); //入力 19 20 char *p = Str; 21 while( *p ){ ++H[ Idx(*p) ]; ++p; } //ループ 22 23 char *s = F( Str, '-', H[27] ); 24 G( &s,'a' ); G( &s,'b' ); G( &s,'c' ); G( &s,'d' ); G( &s,'e' ); G( &s,'f' ); 25 G( &s,'g' ); G( &s,'h' ); G( &s,'i' ); G( &s,'j' ); G( &s,'k' ); G( &s,'l' ); 26 G( &s,'m' ); G( &s,'n' ); G( &s,'o' ); G( &s,'p' ); G( &s,'q' ); G( &s,'r' ); 27 G( &s,'s' ); G( &s,'t' ); G( &s,'u' ); G( &s,'v' ); G( &s,'w' ); G( &s,'x' ); 28 G( &s,'y' ); G( &s,'z' ); 29 30 printf( "%s\n", Str ); //出力 31 return 0; 32}

投稿2022/11/25 08:10

編集2022/11/25 08:22
fana

総合スコア10672

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

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

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

このような回答には修正を依頼しましょう。

回答へのコメント

fana

2022/11/25 08:13 編集

> 変数は配列を除き4つまで の個数として関数引数もカウントされるとかいう話だと,もう全然ダメだが. (つーか,main関数内の pとs は同じの使えば良かったな)
fana

2022/11/25 08:16

関数Fの実装にいちゃもんが付く場合は, main内のwhileループの箇所を(怒涛のG呼び出しと同様に)怒涛の50連記述にして, Fの側を素直にループで書いて解決ってことで.
fana

2022/11/25 08:18

行数については,怒涛の記述を横に並べるとかすればおk.

0

バケットソートをかければ、頻度計量分で反復1回、頻度用にint[80]あたりをとって配列一個。
ループを多めに回すことで、頻度の計算と、結果の出力を一つのfor文にしている。スペースa-zは0x1fでANDをとるときれいいに0~27にならぶ。
if文で条件分岐できなくても、条件式の結果が1/0に成ることを利用した制御とか、ループ変数を書き換えるのは本来的には禁じ手とおもう。

C

1#include <stdio.h> 2#include <string.h> 3int main() 4{ 5 char str[51]; 6 int bin[80] = {0}; 7 int len; 8 char *wp = str; 9 int i; 10//input 11 scanf("%50s", str ); 12 13//process 14 len = strlen( str ); 15 for( i=0; i<len+27; i++){ 16 bin[ (str[i%len]&0x1f)+len] += i<len; 17 18 wp += sprintf(wp, "%*.*s", bin[i]>0, bin[i]>0, &"-abcdefghijklmnopqrstuvwxyz"[i-len] ); 19 bin[i] -= (i>=len)*(bin[i] > 0); 20 i -= (i>=len)*(bin[i] > 0); 21 } 22//output 23 printf("%s\n", str ); 24} 25

投稿2022/11/25 04:26

編集2022/11/25 10:53
matukeso

総合スコア1427

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

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

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

このような回答には修正を依頼しましょう。

0

C

1#include <stdio.h> 2#include <stdlib.h> 3 4int comp(const void* x, const void* y) { 5 // ここはアナタが考えて 6} 7 8int main(void) { 9 char str[51]; 10 gets(str); 11 qsort( /*ココは*/, /*アナタが*/, /*考えて*/, comp); 12 for ( const char* p = str; *p; ++p ) { 13 putchar( *p == ' ' ? '-' : *p); 14 } 15 return 0; 16}

投稿2022/11/25 04:22

編集2022/11/25 04:24
episteme

総合スコア16007

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

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

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

このような回答には修正を依頼しましょう。

0

ソートの中には、"実際には元のデータは並び替えずに、並び替えたデータを作り出す" ソートというのもあります。


c で行数制限などほぼ無意味なのに…。

c

1#include <stdio.h> 2#define M 50 //処理可能最大文字列長 3#define N 27 //ソート対象文字(b)の文字数 4int main(void){ 5 int i, j, c; //(配列以外の)変数 6 char a[N+1]={0}, b[N+1]=" abcdefghijklmnopqrstuvwxyz"; //配列 7 for(i=0; i<M && (c=getchar())!=EOF; i++) //入力(これは入力の為のループなのです!) 8 { for(j=0; j<N && b[j]!=c; j++); a[j]++; } //処理 9 for(i=0, b[0]='-'; i<N; i++) for(j=0; j<a[i]; j++) putchar(b[i]); putchar('\n'); //出力 10}

plain

1brick quiz whangs jumpy veldt fox. 2-----abcdefghiijklmnopqrstuuvwxyz

plain

1super califragilistic expiali docious 2---aaacccdeefgiiiiiiillloopprrssstuux

matukeso さんの『 0x1f で AND 』を用いれば、処理の行は a[c & 0x1f]++; だけになるので、ループの制限は問題無さそうで、そしたらいっそ b も無くして出力もfor(i=0; i<N; i++) for(j=0; j<a[i]; j++) putchar(i+(i?0x60:0x2d)); putchar('\n'); ですかねぇ。


分布数えソート。
a に入力して b の後半にカウントして a に並べて(もしくは直接)出力。並べる部分が処理だと言われそう。

c

1#define __STDC_WANT_LIB_EXT1__ 1 2#include <stdio.h> 3#define M 50 //処理可能最大文字列長 4#define N 27 //ソート対象文字(b)の文字数 5int main(void) { 6 char *t, *p; //(配列以外の)変数 7 char a[M+1], b[N+1+N]=" abcdefghijklmnopqrstuvwxyz"; //配列 8#ifdef __STDC_LIB_EXT1__ 9 gets_s(a, M+1); //入力 10#else 11 gets(a); //入力 12#endif 13 for(t=a, p=b; *p; *++t||(t=a,p++)) p[N+1]+=(*t==*p); //処理 14 for(t=a, p=b, b[0]='-'; *p; p++) while(p[N+1]--) *t++=*p; *t='\0'; printf("%s\n", a); //a に展開して出力 15 //for(p=b, b[0]='-'; *p; p++) while(p[N+1]--) putchar(*p); putchar('\n'); //直接出力(こっちの方が出力のためのループっぽい) 16}

選択(外部)ソート(?)。
a に入力して並び順に選んで b に溜めて出力。

c

1#define __STDC_WANT_LIB_EXT1__ 1 2#include <stdio.h> 3#define M 50 //処理可能最大文字列長 4int main(void) { 5 char a[M+1], b[M+1]; //配列 6#ifdef __STDC_LIB_EXT1__ 7 gets_s(a, M+1); //入力 8#else 9 gets(a); //入力 10#endif 11 //(配列以外の)変数: i=入力文字, p=並び順文字+転記文字, o=出力先 12 char *i=a, *p=" -aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz", *o=b; 13 for(; *p; *++i||(i=a,p+=2)) *p==*i&&(*o++=p[1]); *o='\0'; //処理 14 printf("%s\n", b); //出力 15}

選択ソート(コード依存)。

c

1#define __STDC_WANT_LIB_EXT1__ 1 2#include <stdio.h> 3#define M 50 //処理可能最大文字列長 4int main(void) { 5 char a[M+1]; //配列 6#ifdef __STDC_LIB_EXT1__ 7 gets_s(a, M+1); //入力 8#else 9 gets(a); //入力 10#endif 11 char *p=a, *q=p+1, c; //(配列以外の)変数 12 for(; *p&&(*q||(*p==' '&&(*p='-')&&0)); *++q||(q=++p+1)) *p>*q&&(c=*q,*q=*p,*p=c); //処理 13 printf("%s\n", a); //出力 14}

投稿2022/11/25 03:46

編集2022/11/29 11:28
jimbe

総合スコア10817

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

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

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

このような回答には修正を依頼しましょう。

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。