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

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

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

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

Q&A

5回答

1086閲覧

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

jikijikidon

総合スコア0

C

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

0グッド

0クリップ

投稿2022/11/25 03:37

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

入力

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

出力

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

条件として、

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

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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回と言うのはセーフでしょうか?
guest

回答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

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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

総合スコア11647

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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.
guest

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

総合スコア1590

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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

総合スコア12612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問