• ベストアンサー

C言語を使用したプログラミング方法で質問です。

次のように数値(16進数)を入力して小さい順に並べる(scanfで入力時に数値はカンマで区切る) 例: 入力:A1,05,B1,30,29最後はenterキーで出力  出力:05,29,30,A1,B1 というように出力する方法をプログラミングを教えていただけますか? 宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

scanf()使う時には入力幅を指定した方が良いです。 例えば char input[5]; scanf( "%s", input ); とした場合に、入力者が5文字を越えて入力すると想定外のメモリ領域に入力値が上書きされる事になります。 char input[5]; scanf( "%5s", input ); として5文字以上の入力で以降のデータ領域を保護しましょう。 #include <stdio.h> int main( void ) { char buffer[256]; char *ptr; int hex[100]; int count; int out; printf( "入力:" ); if( 1 != scanf( "%256s", buffer ) ) { printf( "error!!\n" ); return 10; } for( ptr=buffer, count=0; *ptr ; ) { if( 1 == sscanf( ptr, "%x,", &hex[count] ) ) { ++count; } else { printf( "NG data\n" ); } for( ; ! ( '\0' == *ptr || ',' == *ptr ); ptr ++ ); if( *ptr ) ptr ++; } printf( "出力:" ); for( out=0; count>out+1; ++out ) printf( "%x,", hex[out] ); printf( "%x\n", hex[out] ); return 0; } 数値をscanf("%x", &val )で変換すると細かなエラー処理が難しいので、それが必要なら文字列の数値化をプログラミングした方が良い場合は多そうです。 switch( c )の解説がありましたが、ASCIIの様な0-9 a-z A-Zが連続した値になっている場合には if( '0' <= c && '9' >= c ) val=c-'0'; if( 'a' <= c && 'f' >= c ) val=c-'a'+10; if( 'A' <= c && 'F' >= c ) val=c-'A'+10; で良いと思います。

その他の回答 (3)

回答No.3

文字列のままで比較しない方が良いんじゃないかな。 scanfで文字列として受取る。 char c[256]; scanf( "%s", c ); 切り分けたり数値化したりする方法は色々。 それこそsscanf()という手もあるし。 sscanf( c, "%X,%X,%X,%X,%X", &data[0], &data[1], &data[2], &data[3], &data[4] ); ただこういった形でのsscanf()で切り分け、数値化の方法だと何個入ってくるのか分からない時に面倒なのと、 想定外の文字が入ってきた時に面倒。 なので文字列を自分で切り分けたり数値化したり、配列を動的に作ったりする。 int cnt, i; char *hex; cnt=1; for( i=0; i<strlen(c); i++ ) if( c[i]==',' ) cnt++; //カンマの個数をカウント hex=malloc(sizeof(int)*cnt); これでカンマの個数を数えて要素数を特定、そのサイズでint型の配列を作っている。 けども、こういうのは多分まだ授業で習ってないだろうと思う。 あとは「カンマを区切りとして、それぞれの値を数値化して配列hexに入れる」とすれば、 そこから先はこれまでと同じくソートして結果を出せば良い。 数値化については「先に入力チェックをしてから既存の関数にぶっ込む」か「自分でチェックしながら変換していく」の2パターンが考えられる。 先にチェックして問題無ければsscanf()やatoi()のような関数で変換しても良い。(atoi()は10進だけだけど) もしくは自分で1文字ずつ見て文字列の0-9A-Fを数字の0-15に置き換えて足していく。その場合はswitch()を使う。 例 switch( c ) { case '0': case '1':  : case '9': hoge = c-'0'; break; case 'a': case 'A': hoge=10; break;  : default: //エラー処理 break; }

回答No.2

入力する値は5個って仕様なのかな? 個人的には最初に入力された文字列をそのまま取っておきたいタイプなんだけれども、 それをしないで直接16進数値として読み込んでしまうなら以下のような1行でいけるはず。 scanf( "%X,%X,%X,%X,%X", &data[0], &data[1], &data[2], &data[3], &data[4] ); 自分で作ったように5行に分けて取りたい場合、1~4行目までは%xの後に,を付ける。 scanf("%x",&data[0]);  ↓ scanf("%x,",&data[0]); でないと間の,の行き場所が無くなって、後の数値がバグってしまう。

dezaemon1120
質問者

補足

結果としては正しいのですが、scanf使用時に入る値を16進数ではなく文字列として扱って、 比較して降順に表示させたいのですが、大変申し訳ありませんが教えていただけますか?

回答No.1

とりあえず流れだけ教えたげよう。 入力を受取る  ↓ (必要なら入力チェック、0-9A-F,以外があったらアウト)  ↓ カンマで区切って配列とかに入れる  ↓ ソートし易いよう数値化して別の配列に入れる  ↓ 並び替え、普通にバブルソートで  ↓ 結果出力 あとはこれをC言語に落としていけば良い。 「入力を受取る」を「scanf」に、「カンマで区切って~」を「strchr」や「strncpy」に、 「数値化」は既存の関数を使うより、自分で「switch」とかを使って作った方が楽かもね。 0-9はそのまま数値化、A-Fは自分で10-15に置き換えるだけ。

dezaemon1120
質問者

補足

C言語のプログラミングについて質問です。 次のように数値(16進数)を入力して小さい順に並べる(scanfで入力時に数値はカンマで区切り、最後の文字を入力したらenterキーで結果を表示) 例: 入力:A1,05,B1,30,29最後はenterキーで出力 出力:05,29,30,A1,B1 というように出力する方法をプログラミングを教えて頂けますか? 自力で以下になるようになったのですが、scanf時のカンマ入力での表示での出力方法が分かりません。 宜しくお願いします。 #include<stdio.h> int main(void) { int data[5]; int temp; int i,j; printf("入力:"); scanf("%x",&data[0]); scanf("%x",&data[1]); scanf("%x",&data[2]); scanf("%x",&data[3]); scanf("%x",&data[4]); /* 昇順(小さい順)で並び替え */ for(i=0;i<=4;i++) { for(j=4;j>i;j--) { if(data[j]<data[j-1]) { temp=data[j]; data[j]=data[j-1]; data[j-1]=temp; } } printf("%x ",data[i]); } }

関連するQ&A