| 547 | ただ、 scanf() 関数の書式指定はクセが強いので、あまりあてにしない方が良いかも知れません。以下のプログラムを見てみましょう。 |
| 548 | |
| 549 | {{{ |
| 550 | #!c |
| 551 | #include <stdio.h> |
| 552 | |
| 553 | int main() |
| 554 | { |
| 555 | int a = 0, b = 0; |
| 556 | printf("a,b >> "); |
| 557 | scanf("%d,%d", &a, &b); /* ←注目!! */ |
| 558 | printf("a + b = %d\n", a + b); |
| 559 | return 0; |
| 560 | } |
| 561 | }}} |
| 562 | |
| 563 | scanf() 関数で指定した書式指定は "%d,%d" となっていますね。この場合、入力する側もこの通り、2つの数字をカンマ "," で挟んで入力する必要があります。ちょっと、実行して、いろいろ試してみましょう。 |
| 564 | |
| 565 | {{{ |
| 566 | $ gcc -o hoge hoge.c |
| 567 | $ ./hoge |
| 568 | a,b >> 1,3 |
| 569 | a + b = 4 |
| 570 | $ ./hoge |
| 571 | a,b >> 1 3 |
| 572 | a + b = 1 |
| 573 | $ ./hoge |
| 574 | a,b >> 1, 3 |
| 575 | a + b = 4 |
| 576 | $ ./hoge |
| 577 | a,b >> 1 , 3 |
| 578 | a + b = 1 |
| 579 | $ ./hoge |
| 580 | a,b >> 1,3,5 |
| 581 | a + b = 4 |
| 582 | $ ./hoge |
| 583 | a,b >> ,1,3 |
| 584 | a + b = 0 |
| 585 | $ ./hoge |
| 586 | a,b >> 1 |
| 587 | a + b = 1 |
| 588 | $ |
| 589 | }}} |
| 590 | |
| 591 | カンマの後ろに空白が入るのは許容されるようですが、カンマの手前に空白が入ると、 2つ目の数字は無視されてしまうようです。それから、カンマで挟んで 3つ数字を入力しようとした場合は頑張って最初の 2つを読み取ってくれますが、いきなりカンマで始まるようなケースでは 1つも数字を読み取ってくれません。さらに、数字を 1つだけ入力した場合は、 2つ目の入力を待たずに終了してしまうようです。 |
| 592 | |
| 593 | それでは、書式指定を "%d,%d" ではなく、 "%d %d" と、空白で挟んだ場合はどうでしょうか。 |
| 594 | |
| 595 | {{{ |
| 596 | #!c |
| 597 | #include <stdio.h> |
| 598 | |
| 599 | int main() |
| 600 | { |
| 601 | int a = 0, b = 0; |
| 602 | printf("a b >> "); |
| 603 | scanf("%d %d", &a, &b); /* カンマではなくスペースで挟む */ |
| 604 | printf("a + b = %d\n", a + b); |
| 605 | return 0; |
| 606 | } |
| 607 | }}} |
| 608 | |
| 609 | 実行してみましょう。 |
| 610 | |
| 611 | {{{ |
| 612 | $ gcc -o hoge hoge.c |
| 613 | $ ./hoge |
| 614 | a b >> 1 3 |
| 615 | a + b = 4 |
| 616 | $ ./hoge |
| 617 | a b >> 1,3 |
| 618 | a + b = 1 |
| 619 | $ ./hoge |
| 620 | a b >> 1 , 3 |
| 621 | a + b = 1 |
| 622 | $ ./hoge |
| 623 | a b >> 1 3 5 |
| 624 | a + b = 4 |
| 625 | $ ./hoge |
| 626 | a b >> 1 3 |
| 627 | a + b = 4 |
| 628 | $ ./hoge |
| 629 | a b >> 1 |
| 630 | 3 |
| 631 | a + b = 4 |
| 632 | $ ./hoge |
| 633 | a b >> |
| 634 | |
| 635 | 1 |
| 636 | 3 |
| 637 | a + b = 4 |
| 638 | $ |
| 639 | }}} |
| 640 | |
| 641 | 2つの数字の間に空白以外の文字が入ると、 2つ目以降の数字は無視されてしまうようですね。数字を 3つ入力した場合も最初の 2つまで受け付けてくれるのは、概ね想像通りでしょう。しかし、最初に空白を入れた場合でも問題なく 2つの数字を読み取ってくれたり、数字を 1つだけ入力しても 2つ目の数字の入力を待ってくれたり、あるいは何も入力せずにひたすら Enter を押しても数字の入力を待ち続けてくれたりする辺りは、ちょっと意外だったのではないでしょうか。 |
| 642 | |
| 643 | scanf() 関数は整数以外に、実数や文字列を受け取ることもできます。以下のプログラムを見てみましょう。 |
| 644 | |
| 645 | {{{ |
| 646 | #!c |
| 647 | #include <stdio.h> |
| 648 | |
| 649 | int main() |
| 650 | { |
| 651 | char name[BUFSIZ] = "", format[BUFSIZ]; |
| 652 | int age = 0; |
| 653 | float tall = 0, weight = 0; |
| 654 | printf("名前 >> "); |
| 655 | (void) sprintf(format, "%%%ds", BUFSIZ - 1); /* BUFSIZ == 512 の場合、 "%511s" となる。 */ |
| 656 | scanf(format, name); /* 文字列を受け取る; name は配列なので & は不要 */ |
| 657 | printf("年齢 >> "); |
| 658 | scanf("%d", &age); |
| 659 | printf("身長(cm), 体重(kg) >> "); |
| 660 | scanf("%f,%f", &tall, &weight); |
| 661 | |
| 662 | printf("%s、%d歳。身長%.1fcm、体重%.1fkg。\n", name, age, tall, weight); |
| 663 | |
| 664 | return 0; |
| 665 | } |
| 666 | }}} |
| 667 | |
| 668 | とりあえず、実行する様子を見てみましょう。 |
| 669 | |
| 670 | {{{ |
| 671 | $ gcc -o hoge hoge.c |
| 672 | $ ./hoge |
| 673 | 名前 >> 村山俊之 |
| 674 | 年齢 >> 32 |
| 675 | 身長(cm), 体重(kg) >> 161.0, 69.4 |
| 676 | 村山俊之、32歳。身長161.0cm、体重69.4kg。 |
| 677 | $ |
| 678 | }}} |
| 679 | |
| 680 | 名前、年齢、身長、体重を問われ、指示に従って入力すると、入力した通りの内容を表示する、というプログラムです。ここでは、名前として文字列を、身長や体重として実数値を入力しています。 |
| 681 | |
| 682 | 名前の入力については、ちょっと解りづらいプログラム内容になっていますね。 |
| 683 | |
| 684 | {{{ |
| 685 | #!c |
| 686 | printf("名前 >> "); |
| 687 | (void) sprintf(format, "%%%ds", BUFSIZ - 1); /* BUFSIZ == 512 の場合、 "%511s" となる。 */ |
| 688 | scanf(format, name); /* 文字列を受け取る; name は配列なので & は不要 */ |
| 689 | }}} |
| 690 | |
| 691 | 2行目の '''sprintf() 関数''' は、 3行目の scanf() 関数に渡す書式指定文字列を作っています。もしも、定数 BUFSIZ の値が 512 だった場合、この部分は以下のように記述するのと同じ意味になります。 |
| 692 | |
| 693 | {{{ |
| 694 | #!c |
| 695 | printf("名前 >> "); |
| 696 | scanf("%511s", name); |
| 697 | }}} |
| 698 | |
| 699 | 文字列を取得する場合の書式指定は "%s" ですが、 "%s" だけだと何文字でも受け取って良いことになってしまい、配列 name に確保した領域よりも長い文字列が入力されると、メモリーが破壊されてしまいます。そこで、受け付ける文字列の長さをあらかじめ制限する必要があります。 "%511s" とやると、 char 型配列の要素 511 個分までの文字列を入力し、残りは捨てる、という動作になり、とりあえず安全です。 |
| 700 | |