• ベストアンサー

入力された2つの整数の差を絶対値を出力するプログラム

2整数の差を絶対値を出力するプログラムをつくりました. 入力される数値は、正数の場合は最大8桁まで有効とし、9桁目以降を無視、負数の場合は '-'を含め、最大9桁まで有効とし,10桁目以降を無視するようにしたい。 2番目の数値入力で9桁以降に数字以外の文字を入力すると,うまく動きません.なぜ動かないかとどのように直したらよいか教えてください. お願いします. #include <stdio.h> #include <stdlib.h> #define BUFFERSIZE 10 #define PLUS_MAX 8 #define MINUS_MAX 9 #define C_NULL ('\0') #define RC_OK 0 #define RC_ND -1 #define RC_ID -2 #define RC_MD -3 int absolute( int n1, int n2 ) ; main() { char n[ 2 ][ BUFFERSIZE ]; int i ; int a[ 2 ] ; int ab ; int count ; int n_pos ; char c ; for( i = 0 ; i < 2 ; i ++ ){ printf( "%d番目の数値 :", i + 1 ) ; for( count = 0 ; count <= BUFFERSIZE ; count ++ ){ c = getchar() ; if( c >= '0' && c <= '9' || count == 0 && c == '-' ){ n[i][ count ] = c ; continue ; } if( c == '\n' ) break ; printf( "Error!\n" ) ; return( RC_ID ) ; } if( count == 0 ){ printf("Error!\n"); return( RC_ND ); } else if( n[ i ][ 0 ] == '-' && count < 2 ){ printf("Error!\n"); return( RC_ID ) ; } if( n[ i ][ 0 ] == '-' && count > MINUS_MAX ){ n_pos = MINUS_MAX ; }else{ if( count > PLUS_MAX ){ n_pos = PLUS_MAX ; }else{ n_pos = count ; } } n[ i ][ n_pos ] = '\0' ; a[ i ] = atoi( n[ i ] ) ; } ab = absolute( a[ 0 ], a[ 1 ] ) ; printf( "絶対値は %d \n", ab ) ; return( RC_OK ); } int absolute(int n1, int n2) { int i ; i = n1 - n2 ; return i >= 0 ? i : -i ; }

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★ソースを覗いた感想は main 関数が長すぎます。 ・上手く動かないようですが、バグを探る前に main 関数のソースを整理します。  下に main 関数のサンプルを載せます。→これを元に main 関数とサブ関数を作ります。 ・入力部は『MyUserInput』関数にお任せしています。→main 関数に記述しません。  この関数は1つの整数文字列を入力してから、その文字列を整数変換して引数 input へ代入します。  戻り値は、正常(RC_OK)、エラー(RC_ND,RC_ID,RC_MD)を返します。  この戻り値は、main 関数で受け取って処理します。→エラーメッセージも main 関数の担当にします。 サンプル: int main( void ) {  int a[ 2 ];  int i, ret;    for ( i = 0 ; i < 2 ; i ++ ){   printf( "%d番目の数値 :", i + 1 ) ;      if ( (ret = MyUserInput(&a[i])) != RC_OK ){    printf( "Error!\n" );    return( ret );   }  }  printf( "絶対値は %d \n", absolute(a[0],a[1]) ); ←『ab』に代入しなくても可能  return( RC_OK ); } /* 1つの整数文字列を入力(整数変換も含む) */ int MyUserInput( int *input ) {  char n[ BUFFERSIZE + 1 ];  int c; ←『char』ではなくて int 型で宣言(EOF=-1 が戻る事もあるので)  int count;    for ( count = 0 ; count < BUFFERSIZE ; ){ ←回答者 No.1 さんのアドバイスより( <= ではありません)   if ( (c = getchar()) == EOF ){    break;   }   if ( c == '\n' ){    break;   }   if ( isdigit(c) ){ ←'0'~'9'ならば『真』    n[ count++ ] = (char)c; ←キャストが必要!   }   else if ( c == '-' ){    if ( count != 0 ){     return( エラーを返す ); ←最初以外の『-』入力エラー    }    n[ count++ ] = (char)c; ←キャストが必要!   }   else{    return( エラーを返す ); ←数字と『-』以外の入力エラー   }  }  if ( count == 0 ){   return( RC_ND ); ←入力されていないエラー  }  n[ count ] = '\0'; ←入力の最後の NULL 文字    if ( n[0] == '-' ){ ←先頭が『-』文字   n[ MINUS_MAX ] = '\0'; ←負ならば 10 桁以降を無視  }  else{   n[ PLUS_MAX ] = '\0'; ←正ならば 9 桁以降を無視  }  *input = atoi( n ); ←整数変換して input にセット  return( RC_OK ); ←この関数の戻り値は(RC_OK,RC_ND,RC_ID,RC_MD)を返す } 最後に: ・main 関数とサブ関数の作り方も含めて『サンプル』を掲示してみました。 ・これからプログラミングしていくにあたり、main 関数はあまり長くならないように気をつけて下さい。  またサブ関数に出来る場合は、関数機能を整理してから作成して下さい。→今回は整数の入力のみを  担当する『MyUserInput』関数がそのサブ関数です。 ・あとサブ関数のエラーは『戻り値』として main 関数に戻して、main 関数の中で『printf("Error!\n");』  などのエラー処理を行います。→この方がすっきりとして分かりやすくなります。→バグにならずにすむ。 ・上記の注意点として『BUFFERSIZE』定数は『9』にして下さい。  『for』文のときに『9』でないとまずいから。  宣言では『char n[ BUFFERSIZE + 1 ];』と『+1』していますので大丈夫です。 ・サブ関数『absolute』には問題はありません。 ・以上。おわり。→上記のサンプルを参考に今回の問題点を整理してみましょう。

その他の回答 (2)

回答No.3

これでどうでしょうか? #include <stdio.h> #include <stdlib.h> #define BUFFERSIZE 10 #define PLUS_MAX 8 #define MINUS_MAX 9 #define C_NULL ('\0') #define RC_OK 0 #define RC_ND -1 #define RC_ID -2 #define RC_MD -3 int absolute( int n1, int n2 ) ; main() { char n[ 2 ][ BUFFERSIZE ]; int i ; int a[ 2 ] ; int ab ; int count ; int n_pos ; char c ; // 初期化 memset( n , 0x00 , sizeof(n) ); for( i = 0 ; i < 2 ; i ++ ) { printf( "%d番目の数値 :", i + 1 ) ; for( count = 0 ; count <= BUFFERSIZE ; count ++ ) { c = getchar() ; //if( c >= '0' && c <= '9' || count == 0 && c == '-' ){ //{ // n[i][ count ] = c ; // continue ; //} // マイナスの符号の時 if( count == 0 && c == '-' ) { n[i][ count ] = c ; continue ; } // 負のとき else if( n[i][0]=='-' ) { if( c >= '0' && c <= '9' ) { n[i][ count ] = c ; continue ; } } // 正のとき else if( n[i][0]!='-' ) { // 9桁目以降は無視なので if( count>=8 ) continue; else if( c >= '0' && c <= '9' ) { n[i][ count ] = c ; continue ; } } if( c == '\n' ) break ; printf( "Error!\n" ) ; return( RC_ID ) ; } if( count == 0 ) { printf("Error!\n"); return( RC_ND ); } else if( n[ i ][ 0 ] == '-' && count < 2 ) { printf("Error!\n"); return( RC_ID ) ; } if( n[ i ][ 0 ] == '-' && count > MINUS_MAX ) { n_pos = MINUS_MAX ; } else { if( count > PLUS_MAX ) { n_pos = PLUS_MAX ; } else { n_pos = count ; } } n[ i ][ n_pos ] = '\0' ; a[ i ] = atoi( n[ i ] ) ; } ab = absolute( a[ 0 ], a[ 1 ] ) ; printf( "絶対値は %d \n", ab ) ; return( RC_OK ); } int absolute(int n1, int n2) { int i ; i = n1 - n2 ; return i >= 0 ? i : -i ; }

  • php504
  • ベストアンサー率42% (926/2160)
回答No.1

気づいた点を一つ for( count = 0 ; count <= BUFFERSIZE ; count ++ ){ これだと(BUFFERSIZE + 1)回ループします

関連するQ&A

  • 構造体

    下記プログラムの2次元配列を構造体の配列に作り変え,構造体を利用して生年月日の項目を追加し,形式は日を除いたYYYY/MMで持ち,生年月日の入出力は,YYYY/MM形式で行い,西暦が数字4桁で,西暦と月の間に'/'があり,月が01~12の範囲の数字の2桁になっている7文字の入力のみ受け付け,正しく入力されるまでそれ以外は再入力させたい。あとdo-while文をつかっている箇所をwhile文に直したいです.自力でやったのですが,わかりませんでした. どのようにしたらよいか教えてください. お願いします. include <stdio.h> #define BUFFERSIZE 11 #define MAX_PERSON 10 #define MAX_CHARS 10 int main(void) { char name[10][BUFFERSIZE]; int c; int count = 0; int i; int j; for (i = 0; i < MAX_PERSON; i++) { printf("氏名入力 : "); j = 0; /* 氏名の1文字目が'0'なら入力を終了 */ if ((c= getchar()) == '0'){ break; } if (c == '\n') { /* 改行のみの入力は再入力 */ do { printf( "再入力\n" ); /*再入力*/ printf("氏名入力 : "); } while ((c = getchar()) == '\n'); } name[i][j++] = c; /*1文字目を格納*/ if (name[i][0] == '0') { break; } while ((c = getchar()) != '\n' && c != EOF) { if (j < BUFFERSIZE - 1) { name[i][j++] = c; } } name[i][j] = '\0'; count++; /* 実際に入力した人数を記録*/ printf("累計 : %d \n", count); } /* 氏名と生年月日を出力したいです */ for (i = 0; i < count; i++) { for (j = 0; j < MAX_CHARS; j++) { if (name[i][j] == '\0'){ break; } putchar(name[i][j]); } putchar('\n'); } return 0; }

  • 二分法のプログラムについて

    下の用なプログラムを作ったのですがどうしても正しい答えを導くことができません。自分でもいろいろ調べてみましたがわかりません。誰かご教授宜しくお願いします。 #include<stdio.h> #include<stdlib.h> #define MAX 10 int n , count; double c[MAX+1]; double a,b,e; void nyuuryoku(void) { int i; printf("nの入力>"); scanf("%d",&n); if(n>MAX){printf("最大次数を超えている");exit(1);} else if(n<0){printf("nが負");exit(2);} else{for(i=0;i<=n;i++){printf("係数の値>");scanf("%lf",&c[i]);} }} double f(double x) {double y; int i; y = c[0]; for(i=1;i<=n;i++){ y=y*x+c[i];} return y; } void hani(void){ printf("aの値>");scanf("%lf",&a); printf("bの値>");scanf("%lf",&b); printf("eの値>");scanf("%lf",&e); if(e<=0){printf("eが0または負"); exit(3);} if(f(a)==0){printf("%f",f(a)); exit(4);} if(f(b)==0){printf("%f",f(b)); exit(5);} if(f(a)*f(b)>0){printf("初期値異常"); exit(6);}} double nibun(void) {double c; if(b>a){ while(b-a>e){ count++; c=(a+b)/2; if(f(c)==0){ return c;} if(f(a)*f(c)<0){b=c;} if(f(b)*f(c)<0){a=c;} } return a;} if(a>b){ while(a-b>e){ count++; c=(a+b)/2; if(f(c)==0){ return c;} if(f(b)*f(c)<0){a=c;} if(f(a)*f(c)<0){b=c;} } return a;} } void syutsuryoku(double x){ printf("x=%lf\n",x); printf("f(x)=%lf\n",f(x)); printf("繰り返し回数=%d\n",count); } int main(void){ double ans; count=0; nyuuryoku(); hani(); ans = nibun(); syutsuryoku(ans); }

  • 迷路作成のプログラミング

    迷路作成のプログラミングをC++で作ったのですが、エラーが出ます。 どのように直せば良いか教えてください。 エラー内容は 'randoomize': 識別子が見つかりませんでした。 16 進型定数には、少なくとも 1 桁の 16 進数が必要です。 'kbhit': 識別子が見つかりませんでした 'getch': 識別子が見つかりませんでした です、、お願いします。 #include <stdio.h> #include <stdlib.h> #include <time.h> #define YOKO_MAX 200 #define ESC '\xlb' int n; int map[YOKO_MAX],count[YOKO_MAX]; int rr() { return rand() % 10>3; } void tate() { int i,j,k; printf("■"); for (i=0; i<n-1;i++) if(map[i]!=map[i+1] && rr()) { k=map[i+1]; count[k]=0; for(j=0; j<n; j++) if(map[j]==k) { map[j]=map[i]; count[map[i]]++; } printf(" "); } else printf("■"); printf("■\n"); } void last_tate() { int i,j,k; printf("■"); for (i=0; i<n-1;i++) { if(map[i]==map[i+1]) printf("■"); else { k=map[i+1]; for (j=0; j<n; j++) if (map[j]==k) map[j]=map[i]; printf(" ",map[i]); } } printf("■\n"); } void yoko() { int i,j; for (i=0; i<n; i++) if (count[i]>1 && rr()) { printf("■■"); for(i=0; i<n; i++) { if (count[j]==0) { count[j]=1; count[map[i]]--; map[i]=j;break; } } } else { printf("■"); } printf("■\n"); } void enter() { int i,k; k=rand() % n; for (i=0; i<n; i++) if(i==k) { printf("■"); } else { printf("■■"); } printf("■\n"); } void initialize() { int i; for (i=0; i<n; i++) { map[i]=i; count[i]=1; } randoomize(); } int main() { printf("無限に大きな迷路\n"); do { printf("\n迷路の横幅(2~200)?"); scanf("%d",&n); } while (n<2||n>=YOKO_MAX); printf("\n ESCキーを押すと止まる。\n"); initialize(); enter(); do { tate(); yoko(); } while (!kbhit()||getch()!=ESC); last_tate(); enter(); }

  • C言語のプログラムについて。

    C言語のプログラミングについて質問です。 入力されたデータの配列とデータ数を渡すと配列に格納された値を逆順にして、格納し直す関数reverse関数を書き結果を出力せよ、というものなのですが下のように書いたのですが、うまく作動しません。どこがいけないのでしょうか...?教えていただきたいです。 #include <stdio.h> void reverse(int *data[], int n); #define MAX 100 int main() { int data[MAX]; int n, i; scanf("%d", &n); if (n >= MAX) n = MAX; for (i = 0; i < n; i ++){ scanf("%d", &data[i]); } reverse(data, n); for (i = 0; i < n; i ++) { printf("%d\n", data[i]); } return 0; } void reverse(int *data[], int n) { int c, i; for (i = 0; i < n; i ++) { c = *data[i]; *data[i] = *data[n - (i + 1)]; *data[n - (i + 1)] = c; } }

  • プログラムのことで

    次のプログラムの変数の説明と処理の流れを素人でも理解できるように説明してもらえないでしょうか。 #include <stdio.h> #define MAX 128 int str_comp(char nx[], char ny[]){ int i, j, k=0; for(i=0; i<=MAX; i++){ if( nx[i]=='\0' ){ return 0; } else if( nx[i]==ny[0] ){ for( j=0; nx[i]==ny[j]; j++ ){ i++; } if( ny[j]=='\0' ){ return 1; } } } } int main(void) { char namex[MAX}; char namey[MAX}; int n; int i; printf("文字列x(64文字まで)? "); scanf("%s",namex); printf("文字列y(64文字まで)? "); scanf("%s",namey); n=str_comp(namex,namey); if(n==1){ printf("'%s'に'%s'は含まれます\n",namex,namey); } else if(n==0){ printf("'%s'に'%s'は含まれません\n",namex,namey); } return 0; } 実効結果 文字列x(64文字まで)? Katatsumuri  文字列y(64文字まで)? ta 'Katatsumuri'に'ta'は含まれます. エラーは出ないはずです。 よろしくお願いします。

  • プログラムについて(UNIX)

    以下のプログラムを部分的で結構ですので 解説していただけないでしょうか? 打ち込んだ数字を10進法に変換して、 その後どうなっているのかがよく分かりません。 よろしくお願いします。 #include<stdio.h> #include<stdlib.h> #include<time.h> #include<math.h> #define N 127 #define M 121 #define LENGTH 45539 int C[N] ; int d[LENGTH/N]; int b[LENGTH/N]; float r[LENGTH]; char message[LENGTH/N/7]; int PNread(int); int PXread(void); int main() { int i, m; /* Insert the process to input the user No. m here. */ printf("Input the user No. : "); scanf("%d", &m); if (m < 0 || m > M) { printf("You input a wrong user No.\n"); exit(-1); } printf("\nThe user No. m is %d. \n", m); /* Read the spread code for user No. m from data file */ if(PNread(m) == -1) exit(-1); /* Display the spread code. */ /* Here is an example to display the first 10 numbers */ if(PXread()== -1) exit(-1); int t,k; float hatD[LENGTH/N]; for(t=0; t < LENGTH/N; t++){ hatD[t]=0; for(k = t*N; k < (t+1)*N; k++) hatD[t]+= ((float)r[k]*C[k%N])/((float)N); d[t] = (hatD[t] >= 0)?1:-1; /*?はif文の省略形である*/ } for(t = 0; t < LENGTH/N; t++) b[t] = (d[t] >= 0) ? 0 : 1; /* 文字に変換する */ for(i = 0; i < LENGTH/N; i += 7) message[i/7] = b[i]*64 + b[i+1]*32 + b[i+2]*16 + b[i+3]*8 + b[i+4]*4 + b[i+5]*2 + b[i+6]; /* メッセージの表示 */ printf("Message:\n%s\n", message); return 0; } /* Function of spread code reading */ int PNread(int m) { FILE *in; /* Verify the data file */ if ((in = fopen("PN7.dat", "r"))== NULL) { /* Error message */ printf("Error: Cannot find the data file. \n"); return -1; } if(m>1) /* Set the file pointer to the m-th user's spread code */ fseek(in,(m-1)*N*sizeof(int),SEEK_SET); /* Read the spread code to array C */ fread(C,sizeof(int),N,in); fclose(in); return 1; } int PXread(void) { FILE *in; int count; float rtemp; if((in = fopen("Rx7_51.dat", "r"))== NULL) { printf("Error; Cannot find the date file. \n"); return -1; } for(count = 0; count < LENGTH; count++){ fscanf(in, "%f", &rtemp); r[count] = rtemp; } fclose(in); return 1; }

  • C言語<素数を求めるプログラム>

    #include<stdio.h> int j; int prime(int n) { int i; if(n < 2) return 0; if(n == 2) return 1; if(n%2 == 0) return 0; for(i = 3; i*i<= n; i += 2){ if(n%i == 0) return 0; } return 1; } int main(void) { int n; for(n=1; n <= 1000; n++) { if(prime(n)){ printf("%d\n",n); j++; } } printf("素数の個数は全部で %d 件見つかりました。\n",j); return 0; } このプログラムは1から1000までの素数のみを表示させるプログラムでありますが、このアルゴリズムが全くわかりません。 int prime(int n)の中身のアルゴリズムがどういう仕組みになっているのかお分かりになりますでしょうか?

  • 並べ替えのプログラム

    整数を20個入力し、まずそのまま表示してその後大きい順に並べ替えて表示するプログラムを作っているのですが、最大値しか表示されません。多分for文の3重ループの中がおかしいと思うのですがよくわかりません。 #include <stdio.h> int main(int argc, char* argv[]) { int c,i,x,max; int sav = 0; int before[20]; int after[20]; int check[20] = {0}; printf("整数を20個入力してください: "); for(i = 0; i < 20; i++) { scanf("%d",&before[i]); } printf("\n"); printf("BEFORE\n"); for(i = 0; i < 20; i++) { printf("%d\n",before[i]); } printf("\n"); max = 0; for(c = 0; c < 20; c++) { for(x = 0; x < 20; x++) { for(i = 0; i < 20; i++) { if(before[i] > max && check[i] == 0) max = before[i]; sav = i; } if(check[sav] == 0) check[sav] = 1; after[19 - x] = max; } } printf("AFTER\n"); for(x = 0; x < 20; x++) { printf("%d\n",after[x]); } return 0; } よろしくお願いします。

  • C言語のプログラムでおかしな動作をするのですが教えて頂けないでしょうか?

    VisualStudio2008使用しています。 問題は、サイコロを200回振ってその出た目の数の個数分*を表示するプログラムです。 サイコロの目はランダムで出しています。 次のプログラムは正常に動作するものです。 /* #include <stdio.h> #include<stdlib.h> #include<time.h> #define N 200 int DICE(int min,int max); int main() { int n,i,j; int y[7]={0}; srand((unsigned int)time(NULL)); for(i=0;i<N;i++){ n=DICE(1,6); y[n]++; } for(i=1;i<7;i++){ printf(" %2d: ",i); for(j=0;j<y[i];j++){ printf("*"); } printf("\n"); } return 0; } int DICE(int min,int max) { return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } */ 次のプログラムが問題で、授業で先生が配列にはstaticをおまじないとしてつけないと暴走すると言われたので、つけて見ると明らかに間違ってると思われるプログラムで動作するのですが原因を教えて頂けないでしょうか? 以下問題のプログラム! 配列の前にstaticをつけたら、添え字をいくつにしても正常に動作します。普通は添え自分しか領域って確保されないですよね??? /* #include <stdio.h> #include<stdlib.h> #include<time.h> #define N 200 int DICE(int min,int max); int main() { int n,i,j; //以下が問題の配列宣言 static int y[2]={0}; srand((unsigned int)time(NULL)); for(i=0;i<N;i++){ n=DICE(1,6); y[n]++; } for(i=1;i<7;i++){ printf(" %2d: ",i); for(j=0;j<y[i];j++){ printf("*"); } printf("\n"); } return 0; } int DICE(int min,int max) { return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } 質問の意味が正確に伝わらなかった場合は補足しますので、ご回答よろしくお願いします。

  • c言語 スタックの標準入力の課題です

    c言語のスタックについての質問です。 実装したのですが、標準入力の部分を i 9 o i 8 i 7 o i 6 i 5 o i 4 o o i 3 i 2 i 1 o o e といったように指示を一括してやるために直す方法を教えていただきたいです。 iはプッシュ oはポップ eは終了 sは入力時点でのスタックに格納された全体の内容表示 となってます。 #include<stdio.h> #define MaxSize 100 //スタックサイズ int stack[MaxSize];//スタック int sp;//スタックポインタ int push(int); int pop(int *); void show_stack(); void main(void) { int c,n; while(printf("]"),(c=getchar())!=EOF){ rewind(stdin); if(c=='i'||c=='I'){ printf("data--> "); scanf("%d", &n); rewind(stdin); if(push(n)==-1){ printf("スタックがいっぱいです\n"); } } if(c=='o'||c=='O'){ if(pop(&n)==-1) printf("スタックは空です\n"); else printf("stack data-->%d\n",n); if(c=='e'||c=='E') break; } if(c=='s'||c=='S') show_stack(); } } int push(int n)//スタックにデータをつむプッシュ { if(sp<MaxSize){ ++sp; stack[sp]=n; return 0; } else return -1; } int pop(int *n) { if(sp>0){ *n=stack[sp]; sp--; return 0; } else return -1; } void show_stack() { int i; puts("スタックの内容"); if(sp<0){ printf("スタックは空です。\n"); } else for(i=sp;i>=1;i--) { printf("%11d\n",stack[i]); printf("\n"); } }

専門家に質問してみよう