大学にてC言語を学んでいます。
以下、問です。
英小文字だけからなるアルファベットの文字列を a から昇順に並べ替えるプログラムを作成しなさい
なお,このプログラムは空白も無視せず並べ替えの対象となるようにしなさい
入力
- 英小文字だけからなるアルファベットの文字列(50文字まで対応)
- 標準入力から読み込む
出力
- aから昇順に並べかえられた文字列
- 標準出力に書き出す
- スペースの出力はハイフン
-
に置換する
条件として、
- 配列は2つ使用してよい
- for文やwhile文など,反復は入出力処理を除き1つまで
- 変数は配列を除き4つまで(3つでも可能)
- コードはできるだけ18行以内におさめること(コメントや空行,括弧だけの行などは除く)
- if文などの条件分岐は用いない
- 入力文字列の長さは50文字まで対応すること
- フラグを用いた処理はしない
for2つの場合はできるのですが…1つに制限されてしまって困っています。また、qsort関数などを使用せず組むやり方も可能であればよろしくお願いします。
以下のような質問にはグッドを送りましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
下記のような質問は推奨されていません。
- 間違っている
- 質問になっていない投稿
- スパムや攻撃的な表現を用いた投稿
適切な質問に修正を依頼しましょう。
2022/11/25 04:02
2022/11/25 04:05
2022/11/25 06:59 編集
回答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総合スコア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総合スコア10672
良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
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総合スコア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総合スコア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総合スコア10817
良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
関連した質問
Q&A
解決済
JavaScript forとsetTimeoutと配列を組み合わせた謎の挙動について
回答2
クリップ0
更新
2023/01/24
Q&A
解決済
整数 Nが与えられたときの2^Nを10で割った余りを計算しなさい
回答3
クリップ0
更新
2023/01/19
Q&A
解決済
最速で配列からデータを取り出し、正規表現で検索したい。
回答3
クリップ1
更新
2023/01/31
Q&A
解決済
5回、自然数を入力し、その中で最小値と最大値を除いた合計値を出力するプログラム
回答3
クリップ0
更新
2023/02/03
Q&A
解決済
while構文を使う際のbreakの位置と使い方
回答1
クリップ0
更新
2023/02/04
Q&A
受付中
自身の端末の加速度センサで計測したデータをpythonで取得したい。
回答2
クリップ0
更新
2023/02/04
Q&A
解決済
Raspberry Pi Picoの内蔵温度センサーから温度を取得したい
回答1
クリップ0
更新
2023/02/04
Q&A
受付中
文字配列のソートと空白文字の対応
回答5
クリップ0
更新
2022/11/29
同じタグがついた質問を見る
C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。