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

コマンドライン引数についての質問です。

コマンドライン引数に適当な数字をいれ、金種別にわけるプログラムですが、
コマンドライン引数に負の値や、文字列を入力したときにはエラーが表示させるようにしているのですが、
数字と文字を混合したもののときはエラーが表示されずにそのまま処理されてしまいます。

初めの一文字目が数字だったらそのあとに文字を入れても実行されてしまうようです。

全て数字の場合のみ実行させてそれ以外はエラーメッセージを表示させたいのですが、どのようにすればいいでしょうか?


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

int syubetu(int money,int *kinsyu);
int *kinsyu;

int main(int argc,char *argv[])
{
int *p,a;

p=(int*)malloc(sizeof(int)*9);
if(p==NULL){
printf("メモリ確保失敗\n");
exit(1);
}

a=atoi(argv[1]);

if(a>0){
syubetu(a,&p[0]);
printf("1万円 %d枚\n",p[0]);
printf("5千円 %d枚\n",p[1]);
printf(" 千円 %d枚\n",p[2]);
printf("5百円 %d枚\n",p[3]);
printf(" 百円 %d枚\n",p[4]);
printf("50円 %d枚\n",p[5]);
printf("10円 %d枚\n",p[6]);
printf(" 5円 %d枚\n",p[7]);
printf(" 1円 %d枚\n",p[8]);
}
else{
printf("入力エラー\n");
exit(1);
}
}
int syubetu(int money,int *kinsyu)
800字以上になるため、処理は省略します。

A 回答 (6件)

#3です。



>それを試したのですが、期待通りの結果になりませんでした。
>う~ん、なぜでしょう。
失礼! タイプミスがあったようです。
以下をコンパイル、実行してみてください。

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

int isnumstr(char *s)
{
int c;
while(c=*s++){
if((c<'0') || ('9'<c))
return(0);
}
return(1);
}


void main(int argc, char *argv[])
{
int num;
if(argc < 2) {
printf("No args!\n");
exit(1);
}

num = atoi(argv[1]);
printf("argv[1]=[%s], num=[%d]\n", argv[1], num);
if(isnumstr(argv[1]))
printf(" OK!\n");
else
printf(" NG!\n");
}
    • good
    • 0
この回答へのお礼

実行できました!
これを元にしてがんばろうとおもいます。

回答ありがとうございました。

お礼日時:2003/09/19 20:44

文字を指定してもエラーにならないのは、atoiの仕様のためです。


atoiは数値として有効なところまでしか、解析せず、エラーも報告しません。
例として、
123A -> 123を返す
1A2 -> 1
A12 -> 0
という具合です。

実際の改善方法は#2さんのやり方に一票ですが、
課題としての扱いなら、自前で数字以外が含まれるかを
判定するのもいいのかも。


蛇足ながら、結果の格納先をmallocしてますが、
プログラム内容を見る限りでは、mallocの必要性はなく、単純に、
int p[9];
...
syubetu(a, &p[0]); /* or syubetu(a, p); */
でOKですよ。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

そうですね、mallocする必要はないですね。
ご指摘ありがとうございました。

お礼日時:2003/09/17 17:32

こん**は



atoiを使っているから、aにはint型の値しか入ってきませんね。
a=atoi(argv[1]);
の代わりに、判定プログラムを書けば良いですね。
型宣言はあらかじめしておいてください。
int i ;

if ( argc > 1 ){
  a = 0 ;
  i = 0 ;
  while ( argv[1][i] != '\0' && argv[1][i] >= '0' && argv[1][i] <= '9' && a*10+argv[1][i]-'0' > a ){
    a *= 10 ;
    a += argv[1][i]-'0' ;
    i++ ;
  }
  if ( argv[1][i] != '\0' ){
    printf("入力エラー : ");
    if ( argv[1][i] < '0' || argv[1][i] > '9' ){
      printf("文字が含まれています。");
    } else {
      printf("int型を超えています。");
    }
    exit(1);
  }
} else {
  printf("引数が足りません");
  exit(1);
}

とか、適当なものを作れば良いですね。

がんばってください。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

前回の処理の部分に引き続きありがとうございます。

えーっと、まずwhileの所は一体なにをやっている処理なのでしょうか?
argv[1][i]なんて初めて見ました。
これはどういう意味なのでしょう???

あとint型を超えるというのはどういう意味でしょうか?

お礼日時:2003/09/17 17:30

>全て数字の場合のみ実行させてそれ以外はエラーメッセージを表示させたい



それなら、文字列が数字のみかどうかをチェックすればOKです。
具体的には次のような関数を作って呼び出し判定します。

/* 全てが0~9のとき1、それ以外が含まれるとき0を返す */
int isnumstr(cahr *s)
{
 int c;
 while(c=*s++){
  if((c<'0') || ('9'<c))
   retuen(0)
 }
 return(1);
}
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

それを試したのですが、期待通りの結果になりませんでした。
う~ん、なぜでしょう。

お礼日時:2003/09/17 17:26

atoi より strtol のほうが高機能です。

(詳細は参考 URL)

char *endptr;
long x;
x = strtol("123abc", &endptr, 10);
if (*endptr != '\0') {
 puts("だめ!");
}

これに加えて,
strtol に渡す文字列が空でないこと,
strtol の戻り値が「LONG_MAX または LONG_MIN」でないこと,
int の範囲に収まっていること,を確認しておけばよいでしょう。

あと,そこまでやるなら,argc のチェックもしておいたほうがいいと思います。
(argc !=2 だったらメッセージを出すとか。)

参考URL:http://www.microsoft.com/japan/msdn/library/defa …
    • good
    • 0
この回答へのお礼

回答ありがとうござます。

なんか授業でならった所までで出来るらしいので
聞いたことの無いstrtolは使わないでおこうと思います。

お礼日時:2003/09/17 17:24

>int main(int argc,char *argv[])



と、char 型で扱っているせいではないですか?

xxxxx 12
xxxxx 1-1
と入力されても、"1"しか受け取れないと思います。

string 型で受け取って、数値かどうかチェックするするのが普通では?
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

お礼日時:2003/09/17 17:23

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