位分け
位分け
早速ですが、再び質問させていただきます;;
位分けってありますよね?例1000000000⇒1,000,000,000(位分けというのかわかりませんが;)
十桁までの数字を入れれば位分けをしてくれる関数を作りたいのですが、自分なりに作ってみたのですが途中でわからないところがあるのでご教授下さい。
数字を受け取る(例:1852078004)
↓
4つに分ける。(1と852と78と4に分ける)
1000000000未満、1000000以上なら3つにわける。
1000000未満、1000以上なら2つにわける。
1000未満ならそのまま(負数は考えません)。
↓
間に「,」を加えて数値は数字として文字配列に格納する。(a[0]:'1' a[1]:',' a[2]:852 a[3]:','・・・・・a[7]:'4')
↓
0をつけて格納する(1⇒1、852⇒852、78⇒078、4⇒004)
【↑この方法がいまいち分かりません;ご教授お願いします!】
↓
文字を返す
以上です。もしも回りくどいことをしているならもっと簡単な方法を教えて欲しいのですが、基本的なことしかわからないため、あまり高度な技は理解しにくいかもしれませんので、よろしくお願いします。
位分けってありますよね?例1000000000⇒1,000,000,000(位分けというのかわかりませんが;)
十桁までの数字を入れれば位分けをしてくれる関数を作りたいのですが、自分なりに作ってみたのですが途中でわからないところがあるのでご教授下さい。
数字を受け取る(例:1852078004)
↓
4つに分ける。(1と852と78と4に分ける)
1000000000未満、1000000以上なら3つにわける。
1000000未満、1000以上なら2つにわける。
1000未満ならそのまま(負数は考えません)。
↓
間に「,」を加えて数値は数字として文字配列に格納する。(a[0]:'1' a[1]:',' a[2]:852 a[3]:','・・・・・a[7]:'4')
↓
0をつけて格納する(1⇒1、852⇒852、78⇒078、4⇒004)
【↑この方法がいまいち分かりません;ご教授お願いします!】
↓
文字を返す
以上です。もしも回りくどいことをしているならもっと簡単な方法を教えて欲しいのですが、基本的なことしかわからないため、あまり高度な技は理解しにくいかもしれませんので、よろしくお願いします。
Re:位分け
> 数字を受け取る(例:1852078004)
入力を数値で受け取ると、1つ問題点があります。
10桁までに対応するということは、0~9999999999
(99億9999万9999まで)に対応したいのですよね。
ところが、コンピュータの(32ビットの)世界では、
unsigned long型の最大値でも43億に満たない値です。
入力を文字列で受け取るようにすれば、少なくとも
この問題点からは解放されます。
入力する文字列は、通常、'0'~'9'の数字からなる長さが1~10の文字列です。
このルールに反する場合の対応も考えておく方がよいでしょう。
正しい仕様の文字列を受け取り、それを3桁ずつカンマで区切るには、
文字列の長さが
・1~3の場合
・4~6の場合
・7~9の場合
・10の場合
となるケースについて考えるか、または、文字列の長さを3で割ったあまりが
・0の場合
・1の場合
・2の場合
となるケースについて考えるか、あるいは両者を組み合わせるか、でありましょう。
入力を数値で受け取ると、1つ問題点があります。
10桁までに対応するということは、0~9999999999
(99億9999万9999まで)に対応したいのですよね。
ところが、コンピュータの(32ビットの)世界では、
unsigned long型の最大値でも43億に満たない値です。
入力を文字列で受け取るようにすれば、少なくとも
この問題点からは解放されます。
入力する文字列は、通常、'0'~'9'の数字からなる長さが1~10の文字列です。
このルールに反する場合の対応も考えておく方がよいでしょう。
正しい仕様の文字列を受け取り、それを3桁ずつカンマで区切るには、
文字列の長さが
・1~3の場合
・4~6の場合
・7~9の場合
・10の場合
となるケースについて考えるか、または、文字列の長さを3で割ったあまりが
・0の場合
・1の場合
・2の場合
となるケースについて考えるか、あるいは両者を組み合わせるか、でありましょう。
Re:位分け
もし、コンマを表示したいだけなら下のように考えました。
数字で受りたいのならLONGLONG型を使ってみてはいかがでしょう。
windows.hをインクルードする必要がありますが。
また、文字列に格納してから必要なときにコンマをうちながら表示すれば簡単ではないでしょうか?
サンプル作ってみました。
きっともっといい方法があるのでしょうけど、パッと考えてこんな感じはどうかなと思ったので書きました。
用意した配列の数より多くなりそうなら処理をやめたり、他必要なエラー処理は必要に応じて行ってください。
質問内容でよくわからないとおっしゃっている部分もサンプルにでてくる
「
st[i++]='0'+n%10; //一桁ずつ格納
」
この辺見ていただければ解決するのではないでしょうか。
数字で受りたいのならLONGLONG型を使ってみてはいかがでしょう。
windows.hをインクルードする必要がありますが。
また、文字列に格納してから必要なときにコンマをうちながら表示すれば簡単ではないでしょうか?
サンプル作ってみました。
きっともっといい方法があるのでしょうけど、パッと考えてこんな感じはどうかなと思ったので書きました。
#include <stdio.h> #include <windows.h> void conma(LONGLONG n){ int i=0,j,s; char st[20]; while(1){ st[i++]='0'+n%10; //一桁ずつ格納 if(n<10) break; n/=10; } i--; for(j=i,s=0;j>=0;j--,s++){ printf("%c",st[j]); if(i%3==s%3 && j!=0)//iは桁数。3桁ずつコンマをうつ、かつ最後の行ではコンマをうたない printf(","); } } int main(){ int i=0; LONGLONG n; n=10000000000; conma(n); return 0; }
用意した配列の数より多くなりそうなら処理をやめたり、他必要なエラー処理は必要に応じて行ってください。
質問内容でよくわからないとおっしゃっている部分もサンプルにでてくる
「
st[i++]='0'+n%10; //一桁ずつ格納
」
この辺見ていただければ解決するのではないでしょうか。
Re:位分け
返信が遅くなってすいません><;
boxさんの言うとおり一回文字列に直して格納したほうが安全ですね!ルールに反した場合のエラー処理は一応elseの時という感じで用意してます。
管理人さんのプログラムをそのまま貼り付けてコンパイルしてみたら
warning:integer constant is too large for "long" type
という警告が表示されたんですが、これはLONGLONG型がlong型と読みとられたから格納しきれなかったのですか??
あと警告だけだったので実行できると思って実行したら、ほんの一瞬だけ10,000,000,000と出てすぐ消えてしまいました。この前にもこんなことがあって、その時は¥nで改行を入れたらちゃんと消えずに表示されたので、今回もforを出た後にprintf("\n");で改行を入れたらちゃんと表示されました。これはどういうことなんでしょうか??
boxさんの言うとおり一回文字列に直して格納したほうが安全ですね!ルールに反した場合のエラー処理は一応elseの時という感じで用意してます。
管理人さんのプログラムをそのまま貼り付けてコンパイルしてみたら
warning:integer constant is too large for "long" type
という警告が表示されたんですが、これはLONGLONG型がlong型と読みとられたから格納しきれなかったのですか??
あと警告だけだったので実行できると思って実行したら、ほんの一瞬だけ10,000,000,000と出てすぐ消えてしまいました。この前にもこんなことがあって、その時は¥nで改行を入れたらちゃんと消えずに表示されたので、今回もforを出た後にprintf("\n");で改行を入れたらちゃんと表示されました。これはどういうことなんでしょうか??
Re:位分け
それ不思議なんですよ~^^;
一回LLつけてやってみますね!
あと次々と質問攻めで失礼ではあると思うのですが・・・
#include<stdio.h>
#include<string.h>
char place(int number,char buf[7][10]);
int main()
{
int x;
char y[7][10];
x=123456;
place(x,y);
printf("%s\n",y[0]);
return 0;
}
char place(int number,char buf[7][10]){
int a,b;
char num[7][10];
a=number*1000;
b=number-a*1000;
sprintf(num[0],"%d",a);
strcpy(num[1],",");
sprintf(num[2],"%d",b);
}
このプログラムを実行したら何も表示されないんですが、何故でしょうか?
あと今printfにy[0]を出力させているんですが、ひとつの%sに一気にy[0]とy[1]とy[2]を出力させることはできますか?
やはりfor文を使ったり、"%s%s%s",y[0],y[1],y[2]と書くしかないのでしょうか?
一気に質問してしまいましたが、よろしくお願いします!!
一回LLつけてやってみますね!
あと次々と質問攻めで失礼ではあると思うのですが・・・
#include<stdio.h>
#include<string.h>
char place(int number,char buf[7][10]);
int main()
{
int x;
char y[7][10];
x=123456;
place(x,y);
printf("%s\n",y[0]);
return 0;
}
char place(int number,char buf[7][10]){
int a,b;
char num[7][10];
a=number*1000;
b=number-a*1000;
sprintf(num[0],"%d",a);
strcpy(num[1],",");
sprintf(num[2],"%d",b);
}
このプログラムを実行したら何も表示されないんですが、何故でしょうか?
あと今printfにy[0]を出力させているんですが、ひとつの%sに一気にy[0]とy[1]とy[2]を出力させることはできますか?
やはりfor文を使ったり、"%s%s%s",y[0],y[1],y[2]と書くしかないのでしょうか?
一気に質問してしまいましたが、よろしくお願いします!!
Re:位分け
>>えと、main内のprintfでyに入った物を全部表示させたいのですが、y[0]から一個ずつ%sで出していくしかないんですよね?
うーん、2次元配列を1次元配列に変更すればいいかと思いますよ。どうしても2次元配列でないといけないのであれば、別に1次元のバッファを用意して、strcat関数等で文字列を連結させるとか…どうでしょう?
下記サンプルは前者の方法を採用したものです。
うーん、2次元配列を1次元配列に変更すればいいかと思いますよ。どうしても2次元配列でないといけないのであれば、別に1次元のバッファを用意して、strcat関数等で文字列を連結させるとか…どうでしょう?
下記サンプルは前者の方法を採用したものです。
#include <windows.h> #include <stdio.h> #include <string.h> void place(LONGLONG number, char buf[4096]); int main() { LONGLONG x; char y[4096]; x = 123456; place(x, y); printf("%s\n", y); return 0; } void place(LONGLONG number, char buf[4096]) { LONGLONG a, b; a = number * 1000; b = number - a * 1000; sprintf(buf,"%d, %d",a, b); }
Re:位分け
もう1つのサンプルです(^-^)
#include<stdio.h> #include<string.h> void place(unsigned long number,char buf[7][10]); int main() { unsigned long x; char y[7][10], z[70]; x=123456; place(x,y); sprintf(z, "%s%s%s", y[0], y[1], y[2]); printf("%s\n", z); return 0; } void place(unsigned long number,char buf[7][10]) { unsigned long a, b; a = number * 1000; b = number - a * 1000; sprintf(buf[0], "%d", a); strcpy(buf[1], ","); sprintf(buf[2], "%d", b); }
Re:位分け
書式文字列を決める際の参考になるでしょうか。 #include <stdio.h> int main(void) { int i, j, k; for (i = 0; i <= 1000; i += 1000) { for (j = 0; j <= 99; j++) { k = i + j; if (k < 1000) printf("%3d ", k); else printf("%d,%03d ", k / 1000, k % 1000); if (k % 10 == 9) putchar('\n'); } putchar('\n'); } return 0; }
Re:位分け
>実際、今回のも普通に表示されていますし、これまでも不具合とか無かったので…(^^ゞ
まぁ、実際のところ sizeof(int) == sizeof(unsigned long)なら「大抵」は大丈夫ですが、
そうとも符号の有無も違うので内部の挙動が若干変わりますし、
long型が 8バイトな環境も多く存在しますので出来るだけフォーマット指定は
実際の型に合わせておいた方がいいかと思います。
http://www.itmedia.co.jp/enterprise/art ... 003_2.html
まぁ、実際のところ sizeof(int) == sizeof(unsigned long)なら「大抵」は大丈夫ですが、
そうとも符号の有無も違うので内部の挙動が若干変わりますし、
long型が 8バイトな環境も多く存在しますので出来るだけフォーマット指定は
実際の型に合わせておいた方がいいかと思います。
http://www.itmedia.co.jp/enterprise/art ... 003_2.html
Re:位分け
こんなの作ってみました。
char buff[256]; int len; int i; for(;;) { fgets(buff, sizeof(buff), stdin); /* 後ろの余計な制御文字を除去 */ for(i = (int)strlen(buff) - 1; i >= 0 && buff < ' '; i--) { buff = '\0'; } /* 終了条件は改行のみ入力 */ if(*buff == '\0') { break; } /* 頑張って表示して見る */ len = (int)strlen(buff); for(i = 0; i < len; i++) { if((len - i) % 3 == 0 && i > 0) { printf(","); } printf("%c", buff); } printf("\n\n"); }
Re:位分け
ほぼ与太話として見ていただければよいです。
えーっと,国際化対応のために<locale.h>というものがありまして,
その中に,localeconvという関数があります。
で,これで得られるstruct lconvには
・decimal_point
・thousands_sep
・grouping
という金額以外の値を整形出力するためのメンバが存在します。
# setlocaleされたLC_NUMERICで変更されます。
わかりやすいのはdecimal_pointで,アメリカや日本なら.ですが,フランスやドイツなどでは,だったりします。
# これは,printfでも確認できます。
ところが,これを実際に使うと死ぬほど面倒なことになります。
# groupingの取り扱いが面倒……。
で,便利な方法は……標準ライブラリには用意されていません。
時間があれば,挑戦してみるのも面白いと思いますよ。
ちなみに,別の掲示板の過去ログに,私が昔格闘した結果 (通貨なのでもっとややこしい) があったりします。
まぁ,退屈しのぎにでもなれば。
→http://f4.aaa.livedoor.jp/~pointc/log679.html
えーっと,国際化対応のために<locale.h>というものがありまして,
その中に,localeconvという関数があります。
で,これで得られるstruct lconvには
・decimal_point
・thousands_sep
・grouping
という金額以外の値を整形出力するためのメンバが存在します。
# setlocaleされたLC_NUMERICで変更されます。
わかりやすいのはdecimal_pointで,アメリカや日本なら.ですが,フランスやドイツなどでは,だったりします。
# これは,printfでも確認できます。
ところが,これを実際に使うと死ぬほど面倒なことになります。
# groupingの取り扱いが面倒……。
で,便利な方法は……標準ライブラリには用意されていません。
時間があれば,挑戦してみるのも面白いと思いますよ。
ちなみに,別の掲示板の過去ログに,私が昔格闘した結果 (通貨なのでもっとややこしい) があったりします。
まぁ,退屈しのぎにでもなれば。
→http://f4.aaa.livedoor.jp/~pointc/log679.html