アプリ版:「スタンプのみでお礼する」機能のリリースについて

int型変数aとbにそれぞれ値を入力し、それらをかけた結果を出力するプログラムをつくりました。もし文字が入力されたら yarinaoshi と表示し再びaに値を入力するように指示します。しかしこのプログラムはデバグしても何のエラーもないのですが、実際に実行し文字を入力すると Microsoft C++ Debug Library というダイアログボックスが出てきて Abort, Retry, Ignore の三つのボタンがでてきます。どれを選んでも作業は止まってしまい、思ったような結果が得られません。一体どうすればいいのでしょうか? 
以下がそのプログラムのソースコードです。

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>


int kakezan(int a, int b);


int main(void)
{
int dt= 1;
int a, b;

while(dt !=0){
printf("Int1:");
scanf("%d", &a);
if(isalpha(a) != 0)
{

printf("yarinaoshi");
scanf("%d", &a);
}

printf("Int2:");
scanf("%d", &b);

dt = kakezan(a, b);
printf("Result:%d\n", dt);
}
return 0;
}

int kakezan(int a, int b)
{
int dt;
return dt = a*b;

}

A 回答 (6件)

 このプログラムはBASIC言語風に捉えているようですね。

プログラムの流れはOKですよ。自信を持って良いと思います。ただ、CがBASIC言語と違うのは型に厳しいことです。たとえば、「if(isalpha(a) != 0)」のaは、確かにint型なのですが、整数の int型ではなく文字列の int型です。Cはそこは許してくれません。
 実行時の不合理なプログラムの動きは、scanf() 関数にあると考えます。多分、他のCを学んでいる人もこの問題に悩んでいるのではないでしょうか。解決は fgets()関数を使うことです。入力の訂正にバックスペース・キーが使えるので scanf() と違和感はないと思います。一応、入力関数 input_int() を載せておきますので、動かなかったプログラムと何処が違うのか比較していただけたらと思います。一応 Mac OSX では動きますので試して下さい。




/* Sample program with input() by Mac OSX
* file name: shom.c
* compile: gcc shom.c
* execution: ./a.out
*/

#include <stdio.h>
#include <stdlib.h>/* atoi() */
#define BUFF_SIZE32
#define ERR_COMMENT"Try again!!"

void input_int(char *, int *);
int kakezan(int, int);

int main(void) {
int dt;
int a, b;

/* 出題と同じにしてあります */
do {
input_int("Int1: val=", &a);
input_int("Int2: val=", &b);
dt = kakezan(a, b);
printf("Result:%d\n", dt);
} while (dt != 0);

return 0;
}

void input_int(char *comment, int *hensu) {
char buff[BUFF_SIZE], *temp;
intc, flag;

do {
printf("%s", comment);
temp = fgets(buff, BUFF_SIZE, stdin);
/* 末尾の \n を削除 */
while (*temp !='\0') temp++;
*(--temp) ='\0';
/* スペースと最初のマイナス符号を許容 */
temp = buff;
while (*temp == ' ') temp++;
if (*temp == '-') temp++;
/* 数字のみOK */
while ((c = *temp++) != '\0') {
flag = (c >= '0' && c <= '9') ? 0 : -1;
if (flag != 0) {
printf("\t\"%s\"?? %s\n", buff, ERR_COMMENT);
break;
}
}
} while (flag != 0);

*hensu = atoi(buff);
}

int kakezan(int a, int b) {
int dt;
return dt = a*b;
}

参考URL:http://www9.plala.or.jp/sgwr-t/c/sec07.html
    • good
    • 0
この回答へのお礼

ありがとうございます。いただいたソースコードを実行してみたところ自分の希望通りに動作しました。Cの世界は奥が深いですね。まだまだ知らない関数がいっぱいありました。これからもっと勉強していきたいと思います。

お礼日時:2010/01/09 19:16

#4です。


うーん、見る限りでは間違いは無さそう。。。
まさか、全角で数値を入力してたりしないよね?。。。

ちなみに、当方の環境は以下
windows vista
visual c++ 2008 express edition
    • good
    • 0
この回答へのお礼

一応問題は解決しました。長く質問に付き合っていただいてありがとうございました。

お礼日時:2010/01/09 19:18

#1です。



見やすいように、タブの代わりに全角スペースを入れていますので、全部を半角スペース2個に置き換えてコンパイルしてみて下さい。

この回答への補足

半角スペース置き換えてコンパイルしたらエラーは無くなりました。しかし、実際入力のとき困ったことが起こります。最初に数字を入力してenterキーを押しても yarinaoshi が出てきます。そのあと何を入力しても yarinaoshi が表示され無限ループになってしまいす。一応全く同じソースコードを打ち込んだつもりですが、もしミスがあったら教えてください。以下がそのソースコードです。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int inputnum(char *);
int kakezan(int a, int b);

int main(void){
int dt = 1;
int a, b;

while(dt != 0){
a = inputnum("Int1:");
b = inputnum("Int2:");

dt = kakezan(a, b);
printf("Result:%d\n", dt);
}
return 0;
}

int inputnum(char *outstr){
char buf[256];
int ilp, iflg;
int iret;

for(;;){
iflg = 0;
printf("%s", outstr);
gets(buf);
for(ilp = 0; buf[ilp] != '\n'; ilp++){
if(!isdigit((unsigned char)buf[ilp])){
iflg = 1;
break;
}
}
if(iflg){
printf("yarinaoshi\n");
continue;
}
iret = atoi(buf);
break;
}
return iret;
}

int kakezan(int a, int b)
{
int dt;
return dt = a*b;
}

補足日時:2010/01/06 19:44
    • good
    • 0

こんにちは。



C言語を始めて使ったときは、scanfに苦労しました。(汗)
すでに回答されている方がおりますが、私なりの補足です。

○scanf( 書式, 入力値の保存先 );
この関数では、入力した値を書式に従い変換し、入力値保存先に
設定します。
しかし、書式にあった入力しないと、この関数以降で入力値チェッ
クするどころか、この関数内で強制終了させられます。

○回避策
回答された方のソースを見ていただくと、「文字列として受け取り、
数値に変換」の流れとなり、結局はこのロジックをコーディングす
ることになります。

○参考例
同じ結果を求めても、人それぞれ表現が異なります。
私的には以下な感じです。(関数化等の詳細は省きます。)
#include <stdio.h>
#define INPUT_AREA_SIZE 511
#define INPUT_AREA_SIZE_SZ INPUT_AREA_SIZE+1
char str[ INPUT_AREA_SIZE_SZ ];
int num;

/* ここで、str変数を初期化 */

fgets( str, INPUT_AREA_SIZE, stdin );

/* ここで、str の内容をチェック (A)*/

num = atoi( str ); /* 文字列 → 数値 */
printf( "結果=%d\n" , num );
fflush( stdin ); /* 入力文字数超過分を消去 */

補足1:(A)に「数字以外のチェックと桁数」を組み込んで下さい。
補足2:gets関数を使う方法もありますが、入力文字数を超過する
とこの関数内で強制終了されますのでご注意を。
補足3:stdinは、予約語です。

○新入社員時代の先輩からの教え
「scanf関数関係は使うな~」でした。
一時的な利用であれば良いのですが、長期的な利用の場合は、時限
爆弾となる為です。
    • good
    • 0

アドバイスなのですが


scanfの戻り値をデバッグライトしてみたり
ブレークポイントを使って変数の中身をウォッチしながら
ステップ実行してみると良いと思います
    • good
    • 0

あまりにC言語に不慣れなのが丸分かりしてしまい、助太刀します。


scanf関数の一応の使い方は問題ないのですが、これでは数値のみの入力を前提としています。
したがって、文字を入力して文字かどうか判断する事は出来ないのです。
http://ja.wikipedia.org/wiki/Scanf

ちなみに同じ目的のプログラムを私が作った場合は以下のようにします。(文句は飛んできそうですが。。。)
---------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int inputnum(char *);
int kakezan(int a, int b);

int main(void)
{
 int dt= 1;
 int a, b;

 while(dt != 0){
  a = inputnum("Int1:");

  b = inputnum("Int2:");

  dt = kakezan(a, b);
  printf("Result:%d\n", dt);
 }
 return 0;
}

int inputnum(char *outstr)
{
 char buf[256];
 int ilp,iflg;
 int iret;

 for(;;) {
  iflg = 0;
  printf("%s" ,outstr);
  gets(buf);
  for(ilp = 0 ; buf[ilp] != '\0' ; ilp++) {
   if(!isdigit((unsigned char)buf[ilp])){
    iflg = 1;
    break;
   }
  }
  if(iflg) {
   printf("yarinaoshi\n");
   continue;
  }
  iret = atoi(buf);
  break;
 }
 return iret;
}

int kakezan(int a, int b)
{
 int dt;
 return dt = a*b;

}

この回答への補足

記述していただいたソースコードを実際そのままコピーしてデバグしたのですが、大量にエラーが出ていました。 エラーの内容はsyntax error, undeclared identifier, unicode identifiers are not yet supported, identifiler not found even with argument-dependent lookup, fatal error です。一文字も逃さないようにコピーしているのですが、何度やってもやはりエラーが出てきます。失礼ですがソースコードのどこかが間違ってはいないでしょうか?それともこちらの処理系に問題があるのでしょうか? 私はVC++2003を使っています。

補足日時:2010/01/06 14:38
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!