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