プログラムがバグっている箇所を教えて下さい

このQ&Aのポイント
  • C++初心者のため、以下のソースコードでバグっている箇所を教えていただけると助かります。
  • int型整数を格納するスタックを、配列を用いて実現するプログラムです。
  • メモリ確保処理回数を少なくするため、512*N個の格納時にメモリを確保しています。
回答を見る
  • ベストアンサー

プログラムがバグっている箇所を教えて下さい(2)

C++初心者です。 以下のソースコードでバグっていると思われる箇所を教えていただけるとありがたいです。 /* LIFO_04.cpp * * int型整数を格納するスタックを、配列を用いて実現する * メモリ確保処理回数を少なくするために、512*N個の格納時にメモリを確保する * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "LIFO_04.h" #define DEBUG #ifdef DEBUG static int newCount = 0; /* mallocのコール回数 */ static int resizeCount = 0; /* reallocのコール回数 */ static int deleteCount = 0; /* freeのコール回数 */ #endif LIFO_04::LIFO_04() : m_pStack(0), m_stored(0) { #ifdef DEBUG newCount = 0; resizeCount = 0; deleteCount = 0; #endif } LIFO_04::~LIFO_04() { /* nop */ } int LIFO_04::LIFO_push_array(const int push_value) { int result = PreProcess(); if (result == EXIT_SUCCESS) { m_pStack[m_stored++] = push_value; } return result; } int LIFO_04::LIFO_pop_array(int *pop_value) { int result; if (m_stored <= 0) { /* スタック空 */ result = EXIT_FAILURE; } else { *pop_value = m_pStack[--m_stored]; result = PostProcess(); } return result; } /* 指定バイト境界に値を切り上げる */ int LIFO_04::RoundUp(int val, int align) { if (val > 0) { return (((val - 1) / align) + 1) * align; } else { return val / align * align; } } /* 事前処理 */ int LIFO_04::PreProcess(void) { int result; if (m_stored == 0) { /* スタック新規作成 */ m_pStack = new int[m_blockLen]; #ifdef DEBUG newCount++; #endif } else if (m_stored % m_blockLen == 0) { /* スタック領域拡大 */ int resize = RoundUp(m_stored, m_blockLen * sizeof(int)); int* pBuf = ResizeBlock(m_pStack, resize); if (pBuf != 0) { m_pStack = pBuf; } } else { /* nop */ } return (m_pStack != 0) ? EXIT_SUCCESS : EXIT_FAILURE; } /* 事後処理 */ int LIFO_04::PostProcess(void) { int result; if (m_stored <= 0) { /* スタックが空になった */ delete m_pStack; #ifdef DEBUG deleteCount++; #endif m_pStack = 0; result = EXIT_SUCCESS; } else if (m_stored % m_blockLen == 0) { /* 領域縮小 */ int* pBuf = ResizeBlock(m_pStack, m_stored); if (pBuf != 0) { m_pStack = pBuf; result = EXIT_SUCCESS; } } else { result = EXIT_SUCCESS; } return result; } /* ブロックサイズを変更する */ int* LIFO_04::ResizeBlock(int* pBlock, int resize) { int* pBuf = new int[resize]; /*int* pBuf = (int*)(realloc(m_pStack, sizeof(int) * resize));*/ #ifdef DEBUG resizeCount++; #endif if (pBuf != 0) { /* 新たに確保したメモリへコピーして、元の領域を開放 */ memcpy(pBuf, pBlock, resize); delete pBlock; } return pBuf; } /* 以下評価用 */ #ifdef DEBUG static void Check(bool result, int line) { if (result == false) { printf("ERROR Line:%d\n", line); } } static void TestNormal(void) { int result; LIFO_04 stack; result = stack.LIFO_push_array(10); Check((result == EXIT_SUCCESS), __LINE__); Check((newCount == 1), __LINE__); result = stack.LIFO_push_array(20); Check((result == EXIT_SUCCESS), __LINE__); int val = 0; result = stack.LIFO_pop_array(&val); Check((result == EXIT_SUCCESS), __LINE__); Check((val == 20), __LINE__); result = stack.LIFO_pop_array(&val); Check((result == EXIT_SUCCESS), __LINE__); Check((val == 10), __LINE__); Check((deleteCount == 1), __LINE__); Check((resizeCount == 0), __LINE__); } static void TestLimit(void) { int result; LIFO_04 stack; /* 空の状態でPOP */ int val = 0; result = stack.LIFO_pop_array(&val); Check((result == EXIT_FAILURE), __LINE__); /* m_blockLen値までPUSH */ for (int i = 0; i < 512; i++) { result = stack.LIFO_push_array(10 + i); Check((result == EXIT_SUCCESS), __LINE__); } Check((deleteCount == 0), __LINE__); Check((resizeCount == 0), __LINE__); /* m_blockLen値を超えてPUSH */ result = stack.LIFO_push_array(20); Check((result == EXIT_SUCCESS), __LINE__); Check((resizeCount == 1), __LINE__); result = stack.LIFO_pop_array(&val); Check((result == EXIT_SUCCESS), __LINE__); Check((val == 20), __LINE__); result = stack.LIFO_pop_array(&val); Check((result == EXIT_SUCCESS), __LINE__); Check((val == 10 + 511), __LINE__); } #endif int main() { #ifdef DEBUG printf("TestStart\n"); TestNormal(); TestLimit(); printf("TestEnd\n"); #endif return 0; }

noname#160888
noname#160888

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

  • ベストアンサー
  • wormhole
  • ベストアンサー率28% (1622/5659)
回答No.2

LIFO_04のコンストラクタでnewCount,resizeCount,deleteCountを0にしてること。

noname#160888
質問者

お礼

回答ありがとうございます。参考になりました。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

ResizeBlock の引数が何を表すのか説明してください. 細かいけど delete pBlock; もおかしい.

noname#160888
質問者

お礼

回答ありがとうございます。参考になりました。

関連するQ&A

  • プログラムがバグっている箇所を教えて下さい(1)

    C++初心者です。 以下のソースコードでバグっていると思われる箇所を教えていただけるとありがたいです。 /* 02_LIFO.cpp * * int型整数を格納するスタックを、配列を用いて実現する(格納上限1000個) * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "02_LIFO.h" /* スタック格納要素最大数実装 */ const int LIFO::m_maxSize = 1000 * sizeof(int); /* コンストラクタ */ LIFO::LIFO() { memset(m_stack, 0, m_maxSize); } /* デストラクタ */ LIFO::~LIFO() { /* nop */ } /* プッシュ */ int LIFO::LIFO_push_array(const int push_value) { if (m_stored > m_maxSize) { return EXIT_FAILURE; } else { m_stack[m_stored++] = push_value; return EXIT_SUCCESS; } } /* ポップ */ int LIFO::LIFO_pop_array(int *pop_value) { if (m_stored == 0) { return EXIT_FAILURE; } else { *pop_value = m_stack[m_stored--]; return EXIT_SUCCESS; } } /* 以下テスト用 */ static void Check(bool result, int line) { if (result == false) { /* 結果がおかしい処理の行をログ出力 */ printf("ERROR Line:%d\n", line); } } /* 正常系テスト */ static void TestNormal(void) { int result; LIFO stack; result = stack.LIFO_push_array(10); Check((result == EXIT_SUCCESS), __LINE__); result = stack.LIFO_push_array(20); Check((result == EXIT_SUCCESS), __LINE__); int val = 0; result = stack.LIFO_pop_array(&val); Check((result == EXIT_SUCCESS), __LINE__); Check((val == 20), __LINE__); result = stack.LIFO_pop_array(&val); Check((result == EXIT_SUCCESS), __LINE__); Check((val == 10), __LINE__); } /* 境界値テスト */ static void TestLimit(void) { int result; LIFO stack; /* 空の状態でPOP */ int val = 0; result = stack.LIFO_pop_array(&val); Check((result == EXIT_FAILURE), __LINE__); /* MAX値までPUSH */ for (int i = 0; i < 1000; i++) { result = stack.LIFO_push_array(10); Check((result == EXIT_SUCCESS), __LINE__); } /* MAX値を超えてPUSH */ result = stack.LIFO_push_array(10); Check((result == EXIT_FAILURE), __LINE__); } /* メイン関数 */ int main() { /* テスト */ printf("TestStart\n"); TestNormal(); TestLimit(); printf("TestEnd\n"); return 0; }

  • スタックの配列プログラム

    スタックを配列で実現するプログラムとして #include<stdio.h> #define stack_size 100 #define stack_el_type int stack_el_type stack[stack_size]; int sp; void init_stack() { sp=-1 } void push(stack_el_type x) { if (sp < stack_size -1) stack[++sp] = x; else{ printf("stack full error.\n"); exit(1); } } stack_el_type pop() { if(sp >= 0 ) return stack[sp--]; else { printf("stack empty error.\n") exit(1); } } 上の完成形を参照として、 他の作り方として int stack[100] int sp void push(int x) int pop() を用いて作成する場合どのようにすればよいのでしょうか? またスタックを一方向リストで実現するプログラムを作成するとき struct node{ int data; struct node *next; } struct node *push(int x,struct node *root) struct node *pop(struct node *root) を用いて作成する場合どのようにすればよいのでしょうか? よろしければご教授お願いします

  • C言語で変更していただきたい所があるのですが・・・

    下のソースを加減乗除だけでなく、余りを求める演算(%)やべき乗演算(^)も使えるようにしたいのですがうまくいきません。 どなたか変更例をお見せできますでしょうか? #include <stdio.h> #include <stdlib.h> #define STACK_MAX 10 /* 配列によるスタック構造 */ double stack[STACK_MAX]; /* スタック頂上の位置(最下部からのオフセット)*/ int stack_top = 0; /* スタックへのpush */ void stack_push(double val) { if(stack_top == STACK_MAX) { /* スタックが満杯になっている */ printf("エラー:スタックが満杯です(Stack overflow)\n"); exit(EXIT_FAILURE); } else { /* 渡された値をスタックに積む */ stack[stack_top] = val; stack_top++; } } /* スタックからpop */ double stack_pop(void) { if(stack_top == 0) { /* スタックには何もない */ printf("エラー:スタックが空なのにpopが呼ばれました" "(Stack underflow)\n"); exit(EXIT_FAILURE); return 0; } else { /* いちばん上の値を返す */ stack_top--; return stack[stack_top]; } } int main(void) { char buffer[256]; double cal1, cal2; int i; do { printf("現在のスタック(%d個):", stack_top); for(i = 0; i < stack_top; i++) { printf("%0.3f ", stack[i]); } printf("\n>"); fgets(buffer, 255, stdin); switch(buffer[0]) { case '+': cal1 = stack_pop(); cal2 = stack_pop(); stack_push(cal2 + cal1); break; case '-': cal1 = stack_pop(); cal2 = stack_pop(); stack_push(cal2 - cal1); break; case '*': cal1 = stack_pop(); cal2 = stack_pop(); stack_push(cal2 * cal1); break; case '/': cal1 = stack_pop(); cal2 = stack_pop(); stack_push(cal2 / cal1); break; case '=': /* =の場合はこのすぐあとでwhile文からも抜ける */ break; default: /* 入力された値は数字のはずなので,スタックに積む */ stack_push(atoi(buffer)); break; } } while(buffer[0] != '='); printf("計算結果は%f です。\n",stack_pop()); if(stack_top != 0) { printf("エラー:スタックにまだ数が残っています\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; }

  • スタックで成績表を作るプログラム。

    成績表を作りたい。Studentのクラスを要素とするクラスStackを完成させてプログラムが動作するようにせよという問題なのですがprivateの物をどうやって要素にすればよいのでしょうか? class Student { private int id; private String name; private int eng; private int math; private int kokugo; Student(int i,String nm,int e,int m,int k) { id=i;name=nm;eng=e;math=m;kokugo=k; } void show(){ System.out.println("("+id+","+name+","+ eng+","+ math+","+ kokugo+")"); } } class Stack { } class Sample { public static void main(String[] args) { Stack ss=new Stack(3); ss.push(new Student(1,"A",10,10,10)); ss.push(new Student(2,"B",20,10,10)); ss.push(new Student(3,"C",30,10,10)); ss.push(new Student(4,"D",40,10,10)); ss.pop(); ss.pop(); ss.pop(); ss.pop(); } }

    • ベストアンサー
    • Java
  • プログラムの関数化

    皆様に助けていただき、なんとかコーディング出来たのですが、関数化したいと思います。アドバイスお願いします。 int overflow_check1(); int overflow_check2(); int overflow_check3(); int overflow_check4(); int lop; // 左のオペランドに入力する値 int rop; // 右のオペランドに入力する値 int result; // 計算結果 int mod; // 除算の余り int max = INT_MAX; // 表現可能な最大値 int min = INT_MIN; // 表現可能な最小値 char *check; // 変換不能な文字を格納 char op; // 入力する演算子 int main ( int argc, char *argv[] ) { /* 引数の個数チェック */ if ( argc != 4 ) { printf ( "usage : %s lop op rop\n", argv[0] ); exit ( 0 ); } /* 引数を取得して整数型に変換 */ lop = atoi ( argv[1] ); rop = atoi ( argv[3] ); /* 引数の取得 */ op = ( argv[2][0] ); /* startが整数であるか文字であるかのチェック */ lop = strtol ( argv[1], &check, 10 ); if ( errno != ERANGE ) { if ( *check != '\0' ) { printf ( "error : 整数を入力して下さい。\n" ); exit ( -1 ); } /* startに範囲を超えた値を入力した場合 */ } else { printf( "error : 整数型の範囲を超えました。\n" ); exit( -1 ); } /* endが整数であるか文字であるかのチェック */ rop = strtol ( argv[3], &check, 10 ); if ( errno != ERANGE ) { if ( *check != '\0' ) { printf ( "error : 整数を入力して下さい。\n" ); exit ( -1 ); } /* endに範囲を超えた値を入力した場合 */ } else { printf( "error : 整数型の範囲を超えました。\n" ); exit( -1 ); } /* argv[2]が2文字以上の場合 */ if ( strlen ( argv[2] ) >= 2 ) { printf ( "error : 演算子を正しく入力して下さい。\n" ); exit ( -1 ); } /* argv[2]に入力された演算子が'+'の場合 */ switch ( op ) { case '+': overflow_check1(); result = lop + rop; break; /* argv[2]に入力された演算子が'-'の場合 */ case '-' : overflow_check2(); result = lop - rop; break; /* argv[2]に入力された演算子が'*'の場合 */ case '*': overflow_check3(); result = lop * rop; break; /* argv[2]に入力された演算子が'/'の場合 */ case '/' : /* 0による除算 */ if ( rop == 0 ) { printf ( "error : 0による除算は禁止です。\n" ); exit ( -1 ); } overflow_check4(); result = lop % rop; // 剰余を求める break; default: printf ( "error : '+' '-' '*' '/'のいずれかの演算子を入力して下さい。\n" ); exit ( -1 ); } /* 割り算の結果として余りが出なかった場合 */ if ( result == 0 ) { result = lop / rop; printf ( "%d %c %d = %d", lop, op, rop, result ); exit ( 0 ); /* 割り算の結果として余りが出た場合 */ } else { result = lop / rop; mod = lop % rop; printf ( "%d %c %d = %d余り%d", lop, op, rop, result, mod ); exit ( 0 ); } /* 数値1 演算子 数値2 = 演算結果の形式で出力する */ printf ( "%d %c %d = %d", lop, op, rop, result ); exit ( 0 ); } int overflow_check1 () { /* オーバーフローのチェック */ if ( lop > 0 && rop > 0 ) { if ( lop > max - rop ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } } /* オーバーフローのチェック */ if ( lop < 0 && rop < 0 ) { if ( lop < min - rop ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } } return 0; } int overflow_check2 () { /* オーバーフローのチェック */ if ( lop > 0 && rop < 0 ) { if ( lop > max + rop ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } } /* オーバーフローのチェック */ if ( lop < 0 && rop > 0 ) { if ( lop < min + rop ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } } return 0; } int overflow_check3 () { /* オーバーフローのチェック */ if ( lop > max / rop ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( -1 ); } /* オーバーフローのチェック */ if ( rop < max / lop ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } return 0; } int overflow_check4 () { /* オーバーフローのチェック */ if ( ( lop == min ) && ( rop == -1 ) ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( -1 ); } return 0; }

  • スタックについて

    スタックを実現するプログラムを作っているのですが、実行するとセグメテーション違反が表示されます。でもどこが間違っているのかわかりません!どうしたらいいのでしょう? #include<stdio.h> #include<stdlib.h> struct stack{ int max; int used; int *array; }; struct stack * stack_create(int n) { struct stack *s; int i; s->array=(int *)malloc(sizeof(int)*n); s->used=0; s->max=n; return 0; } void stack_free(struct stack *s) { free(s); } int stack_push(struct stack *s,int datum) { if(s->used>=s->max){ return 0; } s->array[s->used]=datum; s->used++; return 1; } int stack_pop(struct stack *s,int *datump) { if(s->used<=0){ return 0; } *datump=s->array[s->used-1]; s->used--; return 1; } int stack_is_empty(const struct stack *s) { return s->used==0; } int main() { struct stack s; int i,p; int n; scanf("%d",&n); stack_create(n); for(i=0;i<=5;i++){ stack_push(&s,i); printf("push%2d\n",i); } for(i=1;i<=3;i++){ stack_pop(&s,&p); printf("pop%2d\n",p); } }

  • 集計プログラム

    sub fanc{ my $dir = "ディレクトリ";my @array = @_; my $n = $array[0];my $id = $array[1]; my @csv1 = ('AAA.csv','BBB.csv','CCC.csv','DDD.csv',EEE.csv'); my @csv2 = ('FFF.csv','GGG.csv','HHH.csv','III.csv',JJJ.csv'); my @csv3 = ('KKK.csv','LLL.csv','MMM.csv','NNN.csv','OOO.csv'); opendir(DIR, $dir) or exit; @pairs = grep { -f "$dir/$_" ? $_ : '' } readdir(DIR); close(DIR); if($id == 1){ $pattern = $csv1[$n -1]; } elsif($id == 2){ $pattern = $csv2[$n -1]; } elsif($id == 3){ $pattern = $csv3[$n -1]; } }else{ undef; } @files = grep(/$pattern/, @pairs); until(@files == 0){ my $data = shift @files; open(IN, $data) or exit; @file = <IN>;chomp @file; close(IN); foreach my $i (@file){ my @m = split(/,/, $i); push my @rec1, $m[1]; push my @rec2, $m[2]; } $val1 += $rec2[0]; shift @rec2; $val2 += $rec2[0]; shift @rec2; $val3 += $rec2[0]; shift @rec2; $val4 += $rec2[0]; shift @rec2; $val5 += $rec2[0]; shift @rec2; $val6 += $rec2[0]; shift @rec2; $val7 += $rec2[0]; shift @rec2; $val8 += $rec2[0]; shift @rec2; $val9 += $rec2[0]; shift @rec2; $val10 += $rec2[0]; shift @rec2; } %tmp; my @rec = grep( !$tmp{$_}++, @rec1 ); foreach my $x (@rec){$sum1 += $x;} $res1 = $val1 / $sum1 * 100; $res2 = $val2 / $sum1 * 100; $res3 = $val3 / $sum1 * 100; ・ ・ こんな感じでパーセンテージを出していますが、csvのデータは全て違うのに、引数を変えて並べて実行すると 答えが同じように返ってきます。どこかおかしいのでしょうか?

    • ベストアンサー
    • Perl
  • 下記のプログラムを実行したところ、不正な処理をしたので強制終了しましたとでました。何故でしょうか?

    #include <stdio.h> #include <stdlib.h> #include <float.h> int main( void ) { int val; int sum = 0; int max = -DBL_MAX; int cnt; char FileName[FILENAME_MAX]; FILE *fp; printf("入力ファイル名>>>"); scanf("%s", FileName ); if( (fp = fopen( FileName, "r" )) == NULL ) { printf("ファイルが見つかりません------%s\n",FileName ); exit( EXIT_FAILURE ); } for(cnt=0; ;cnt++) { fscanf(fp,"%d",&val); /*合計を求める*/ if(val == 0) { break; } sum += val; /*最大値を求める*/ if( max < val) { max = val; } } if( cnt > 0) { printf("平均は%g,最大値は%dです\n",(double)sum / cnt, max); } fclose( fp ); return EXIT_SUCCESS; } コンパイルはできるのですが実行すると このプログラムは不正な処理をしたので強制終了しますとでました 入力ファイル名>>>ってのも表示されません やはりこれは僕のパソコンがおかしいのでしょうか? 何か原因があるのなら教えてください

  • コンパイルできるのですが実行途中でエラーが

    #include<iostream> #include<cstdlib> using namespace std; class stack{ char *stck; int tos; int size; public: stack(char c); void push(char ch); char *pop(); ~stack(); }; stack::stack(char c){ tos=0; stck=(char*)malloc(c); size=c; cout<<"生成スタック\n"; if(!stck){ cout<<"メモリ割り当てエラー\n"; exit(1); } } void stack::push(char ch){ if(tos==size){ cout<<"スタックは一杯です\n"; return; } *stck=ch; stck++; tos++; } char *stack::pop(){ if(tos==0){ cout<<"スタックは空です\n"; return 0; } stck--; tos--; return stck; } stack::~stack(){ free(stck); } int main(){ stack s1(10),s2(10); int i; char *o; s1.push('a'); s2.push('x'); s1.push('b'); s2.push('y'); s1.push('c'); s2.push('z'); for(i=0;i<5;i++){ o=s1.pop(); cout<<"s1をポップする"<<*o<<"\n"; } for(i=0;i<5;i++){ o=s2.pop(); cout<<"s2をポップする"<<*o<<"\n"; } return 0; } なんですが、実行した所 生成スタック 生成スタック s1をポップするc s1をポップするb s1をポップするa スタックは空です までで止まってしまいます。 たぶんreturn 0の戻り値の型がポインタだから止まってしまうのだろうと思います。 正しく実行するにはどうすればいいのでしょうか? お願いします。

  • ArrayList でスタックを

    初歩的でツマラナイかもしれません。 import java.util.ArrayList; でスタックを実現するクラス"MyStack"を書きました。 フィールドは private ArrayList<Integer> stack = new ArrayList<Integer>(); のみという条件です。 MyStack.java - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - import java.util.ArrayList; public class MyStack {   private ArrayList<Integer> stack = new ArrayList<Integer>();      // データを先頭に追加   public void push( int item ) {     stack.add( item );   }   // 先頭のデータを取り出す   public int pop( ) {     int rtn;     if( stack.isEmpty() ) {       System.out.println( "スタックは空です." );       System.exit( 1 );     }          rtn = stack.get( 0 );     stack.remove( 0 );     return rtn;   } } このMyStackを実行するクラス"MainForMyStack"を書きます。 実行結果は、標準出力に 43210 と出ることを想定しています。 MainForMyStack.java - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - import java.util.ArrayList; public class MainForMyStack {   public static void main(String[] args) {     MyStack stack = new MyStack();     // 0,1,2,3,4 をスタックに追加     for( int i=0; i < 5; i++ ) {       stack.push( i );     }     // スタックのデータを先頭から取り出す     for( int i=0; i < stack.size(); i++ ) {       System.out.print( stack.pop() );     }   } } さて、MainForMyStack.java の i < stack.size(); の箇所でエラーが出るのはなぜでしょう? どなたかご教授の方お願いします。

    • ベストアンサー
    • Java