• ベストアンサー

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

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

    以下の処理にバブルソートで小さい順からの比較結果をprintfで出力したいのですが、どこにバブルソートを追加すればよろしいですか? 追加した文を教えて頂けますか? 今は値を16進数から10進数に変換した数字を出力しているが、これを小さい順に出力したいんです。 宜しくお願いします。 #include <stdio.h> int main (void) { char data[256]; int val[100]; int i = 0; int k; printf("入力 = "); scanf("%s",data); for(i=0;i<100;i++){ val[i] = 0; } k=0; for(i = 0;i<100 ; i++){ if(data[i] == 0x00){ //data[i]がNULLだったら処理を抜ける k++; break; //enterキーでprintf出力 } else if(data[i] == ','){ //カンマだったら /*printf("%d\n",k);*/ k++; } else{ if(data[i] >= 'A' && data[i] <= 'Z'){ //data[i]にAからZが入ったら val[k] = val[k] *16 + data[i] -'A'+10; } else if(data[i] >= '0' && data[i] <= '9'){ //data[i]に0から9が入ったら val[k] = val[k] *16 + data[i] -'0'; } } } /*printf("%d\n",k);*/ for(i=0;i<k;i++){ printf("出力 = %d\n",val[i]); } }

  • c言語プログラミングHELP!

    c言語でプログラムを組んでるんですが、どうしてもわからないものがありまして、 まず一つ目がキーボードから英小文字を一つ入力し、その文字を大文字に変換して出力するプログラミングです。結果がまずひとつの英小文字を入力して、入力した文字と、大文字に変換した文字を出力するプログラミングです。 ちなみにヒントは'a'=97,'A'=65です 二つ目が二桁の16進数('41'から'49','50'から'59')を入力すると対応する文字を表示するプログラミングです。また、%xは使用しないこと。なお、入力に間違いはないものとする。(ヒントは入力は一つの数値か、二つの文字か?だそうです。) 結果は二桁の16進数('41'から'49','50'から'59')を入力して、文字コードの二桁の数字と文字を出力するプログラミングです。 お願いします。

  • C言語のプログラミングについて質問です。

    以下の文を出力して入力:に16進数を入れると10進数に変換した数値の小さい列順に並ぶプログラムを作りたいのですがうまく出来ません。 仕様は以下に記載します。 入力:__、__、__、__、__EnterKeyで結果を表示。 以下のバブルソートの文のどこをいじれば良いでしょうか? 返答宜しくお願いします。 #include <stdio.h> int main (void) { char data[256]; int val[100]; int i = 0; int work; int j; int k; printf("入力 = "); scanf("%s",data); for(i=0;i<100;i++){ val[i] = 0; } k=0; for(i = 0;i<100 ; i++){ if(data[i] == 0x00){ //data[i]がNULLだったら処理を抜ける k++; break; //enterキーでprintf出力 } else if(data[i] == ','){ //カンマだったら /*printf("%d\n",k);*/ k++; } else{ if(data[i] >= 'A' && data[i] <= 'Z'){ //data[i]にAからZが入ったら val[k] = val[k] *16 + data[i] -'A'+10; } else if(data[i] >= '0' && data[i] <= '9'){ //data[i]に0から9が入ったら val[k] = val[k] *16 + data[i] -'0'; } } } /* printf("k=%d\n",k); for(i=0;i<k;i++){ printf("出力 = %d\n",val[i]); } */ //バブルソート//     for(i=0; i<k-1; i++) { if(val[i] < val[i+1]) { } else{ work = val[i]; val[i] = val[i+1]; val[i+1] = work; } } for(i=0;i<k;i++) { printf("出力 = %d\n",val[i]); } }

  • C言語での質問です。

    何か文字を打ち、その後鍵(整数)を入力します。 すると、元の文字が暗号化されて表示。 というプログラムを作っています。 暗号化の具体的な方法は、 (1)、元の文を鍵の整数で分けます。 例:元の文「aiueo」鍵「2」→「ai」「ueo」 (2)、そして、分けた文を混ぜます。 文字数が多い方を先に混ぜていきます。 「ai」「ueo」→「uaeio」 (3)、この混ぜた文を暗号文として出力。 という感じのプログラムを作りたいのですが、上手く混ざらず困っています。 出力された時、上手く混ざってなかったり文字化けしてるような文字が出てきたりなど。 ソースは↓です。 #include<stdio.h> #include<string.h> int main(void) { char word[256]; char angou[256]={0}; char kari[1][256]={0}; int key,i,n,a=0,b,mae,ushiro; printf("単語を入力してください。:\n"); scanf("%s",word); printf("鍵となる整数を入力してください。:\n"); scanf("%d",&key); n=strlen(word); i=0; while(i<=key-1){ kari[0][i]=word[i];/*keyの文字数までの文字を入れる。*/ i++; } while(key-1<=n){ kari[1][a]=word[i];/*keyの文字数から最後までの文字を入れる。*/ a++; i++; } i=0; a=0; mae=strlen(kari[0]); ushiro=strlen(kari[1]); if(mae>=ushiro){/*どちらの方が文字数が多いかを比べる。*/ for(b=0;b<=n;b++){ if(b%2){ angou[b]=kari[1][a];/*奇数の時、文字数が少ない方を入れる。*/ a++; } else{ angou[b]=kari[0][i];/*偶数の時、文字数が多い方を入れる。*/ i++; } } } else if(mae<ushiro){ for(b=0;b<=n;b++){ if(b%2){ angou[b]=kari[0][a]; a++; } else{ angou[b]=kari[1][i]; i++; } } } printf("暗号文は%sです。\n",angou); return(0); } 何がおかしいでしょうか?

  • C言語でscanfを用いた入力

    C言語でscanfの動作を確かめる為に、次のプログラムを作成して実行してみました。 #include <stdio.h> int main(void){ int i; printf("Input1:"); scanf("%d",&i); printf("Input2:"); scanf("%d",&i); printf("Output:%d",i); return 0; } このプログラムは1回目と2回目に数値を入力すると正常に出力します。 例 1回目の入力に10、2回目の入力に20を入力した時の出力結果 Input1:10 Input2:20 Output:20 今度は1回目で数値、2回目で文字を入力してみました。 そしたら2回目の入力が無視されました。 例 1回目の入力に10、2回目の入力にAを入力した時の出力結果 Input1:10 Input2:A Output:10 今度は1回目で文字を入力してみました。 そしたら2回目の入力は要求せず、いきなりよく分からない数値が出力されました。 例 1回目でAを入力した時の出力結果 Input1:A Input2:Output:-858993460 どうして文字を入力したら正常に出力しなくなるのでしょうか?

  • C言語のプログラミングについての質問です

    C言語の課題で数値を入力したらその数に40+して二乗するプログラミングを作りたいのですがソースがいまいちわかりません どなたかご教授お願いします

  • 質問:C++のプログラミング

    次のような課題が出たのですがわかりません。 教えてください。 <課題> Main関数で3つの数をscanfで入力し、関数max(これを作る)に行ってその3つの数の最大値を求めて次のように出力するようにせよ。   data? (任意の数字3つを入力)   maximum=(一番大きな数) そもそもfor文を使えばいいのかdo while文を使えばいいのかというところから分かっていません。 どなたかよろしくおねがいします。

  • C言語のプログラミング問題(難解)について

    C言語のプログラミング問題(難解)について教えてください! C言語の勉強し始めましたが次の問題のプログラミングが分かりません 分かる方がいましたらよろしくお願いします。 以下の問題です。 次の作業を実現するためのプログラミングを描け。 機能名:リストファイルの分割処理 ■概要:部門1、部門2の商品が混合して書かれたファイルがある。 部門毎に分けたファイルを新たに作成する。 ■条件 (1)ファイルを1行ずつ読み込み、ポインタで受け取り関数で渡すこと。 (2)出力ファイルの最終行には各部門の品種数を入力すること (3)出力ファイルは固定長とし、空きが出る場合は半角スペースでレコード長を合わせること。 (4)エラー発生時にはエラーメッセージを表示し、終了すること。 ■ファイルレイアウト(入力ファイル) レコード長:26(固定長) 長さ 項目名 1 |部門コード1 1 |(区切り文字カンマ) 6 |商品名1 1 |(区切り文字カンマ) 1 |部門コード2 1 |(区切り文字カンマ) 6 |商品名2 1 | (区切り文字カンマ) 1 |部門コード゛3 1 |(区切り文字カンマ) 6 | 商品名3 ■ファイルレイアウト(出力ファイル) レコード長:20(固定長) 長さ | 項目名 6 |商品名1 1 ||(区切り文字カンマ) 6 |商品名2 1 ||(区切り文字カンマ) 6 |商品名3 (1)入力ファイル(LIST_INPUT.txt) 1,菓子A,1,菓子B,1,菓子C 2,野菜A,2,野菜B,2,野菜C 1,菓子D,1,菓子E,2,野菜D 1,菓子F,1,菓子G,2,野菜E 1,菓子H,2,野菜F,1,菓子I 1,菓子J,1,菓子K,2,野菜G (2)出力ファイル1(菓子)(LIST1.txt) 菓子A,菓子B,菓子C 菓子D,菓子E,菓子F, 菓子G,菓子H,菓子I 菓子J,菓子K 11 (3)出力ファイル2(LIST2,txt) 野菜A,野菜B,野菜C 野菜D,野菜E,野菜F 野菜G 7 *出力ファイルの最終行に品種数を追加すること。 よろしくお願い致しますm(__)m

  • C言語のプログラミングですが、

    C言語のプログラミングですが、 255文字以内の文字列をキーボードから入力して、下記の各処理を行うプログラム(※入力した文字データは配列に入力)はどのようにしたらいいでしょうか?(入力例:acFNkeexFFg) ・入力した文字列の最後の文字を出力 ・入力した文字列⇒逆に並べ替えて出力 ・入力した文字列⇒縦に出力(1文字ずつ) ・入力した文字列の中に「F」が何個あるか ただし、使えるのはfor文・配列・if文ぐらいでそれ以上レベルの高いものは使わないで下さい。 … char str[255]; int i,n,na,nb,nc; printf("Input Strings= "); scanf("%s",str); for(i=0;str[i]!='¥0';i++){ n=i; } printf("The last character= %c",str[n]); くらいまでしか分かりません…

  • プログラミングで質問があります。

    プログラミングで質問があります。 実数値を入力して、その平均を出すプログラミングを作ったのですが、うまく行きません。 どこが間違っているのか教えてほしいです #include <stdio.h> int main (void) { float a=1,sum=0; int b=0,i; while(a!=0) { printf("整数値を一つ入力してください。"); scanf("%f",&a); if(a!=0) { b=b+1; } for(i=0;i<=b;i=i++) { sum=sum+a; } } printf("平均値は%fです\n",sum/b); } 実行して、10、10、10と入力すると、90になってしまいます(..;)

専門家に質問してみよう