0

無知で申し訳ありませんが、私は C++ と ROOT に不慣れで、何が間違っているのか正確にはわかりません。

私がやろうとしているのは、ヒストグラムの n ピークのビンの位置を返す関数を作成することです。以下は私のコードです:

#include <iostream>
#include <algorithm>
#include <iterator>

#include "TROOT.h"
#include "TCanvas.h"
#include "TH1.h"
#include "TF1.h"

using namespace std;

int *peak_counter1d(TH1F *histogram,int peak_num,int threshold = 5,int display = 0){
  if(display == 1){
    TCanvas *look = new TCanvas("look","look",500,400);
    histogram->Draw();
  }
  int total_bins = histogram->GetNBinsX();
  double peak_bins[peak_num];
  peak_bins[0] = histogram->GetMaximumBin();
  int counter = 1;
  int *check_array; // to put previously found peak bins
  while(counter < peak_num){
    double peak = threshold;
    double peak_loc = -500;
    check_array = new int[counter];
    for(int i=0; i<counter; i++){
      check_array[i] = peak_bins[i]; // fills the array with previously found peak bins
    }
    for(int i=0; i<total_bins; i++){
      if(peak < histogram->GetBinContent(i)){ 
        bool exists = find(begin(check_array),end(checkarray),i); // makes sure this is a peak we haven't already found
        if(!exists){
          peak = histogram->GetBinContent(i);
          peak_loc = i;
        }
      }
    }
    peak_bins[counter] = peak_loc;
    counter ++;
  }
  delete[] check_array;

  return peak_bins;
}

void testing(){
  gROOT->Reset();
  TH1F *histo = new TH1F("histo","try",100,0,10);
  TF1 *f1 = new TF1("f1","exp(-x/10)*sin(x)*sin(x)",0,10);
  double val;
  for(int i=0; i<100; i++){
    val = f1->Eval(i/10.0);
    //cout << i << "\t" << i/100.0 << "\t" << val << endl;
    histo->SetBinContent(i,val);
  }

  int *peak_bins;
  peak_bins = peak_counter1d(histo,3,5,1);
  for(int i=0; i<3; i++){
    cout << i << "\t" << *(peak_bins+i) << endl;
  }
}

このコードを ROOT で実行すると、次のようになります。

root [] .x testing.cpp
Error: Can't call TH1F::GetNBinsX() in current scope testing.cpp:15:
Possible candidates are...
(in TH1F)
(in TH1)
*** Interpreter error recovered ***

これは、関数内のオブジェクト メソッドにアクセスする際の問題だと思います。なぜなら、testing() 関数で histo->GetNBinsX() メソッドを呼び出しても問題がないからです。しかし、私は知りません。

ありがとうございます。他の悲惨なコーディング方法を行っている場合は、お知らせください。

4

2 に答える 2

-1

コードにはさまざまな問題があります。

最も明白なのはこれです:

int *peak_counter1d(TH1F *histogram,int peak_num,int threshold = 5,int display = 0)
{
    //...
    double peak_bins[peak_num];
    //...
    return peak_bins;
}

ローカル変数へのポインタを返しています。ローカル変数へのポインターを返すことは未定義の動作です。

次の問題はこれです。

  int *check_array; // to put previously found peak bins
  while(counter < peak_num)
  {
      //...
      check_array = new int[counter];
  }
  delete[] check_array;

割り当てを解除せずにループしているため、メモリリークが発生する可能性がありますcheck_array。もう 1 つの問題は、そのループが実行delete []されない場合、初期化されていない変数を呼び出していることです。

次の問題はこれです。

int * peak_counter1d(...)
{
    double peak_bins[peak_num];
    //...
    return peak_bins;
}

ローカル変数へのポインターを安全に返すことができたとしても、関数は int* を返しますが、double *.

次の問題はこれです。

TCanvas *look = new TCanvas("look","look",500,400);

を割り当てlookていますが、割り当てを解除したり、使用したりすることはありません。

で同じことを行いmainます:

 TH1F *histo = new TH1F("histo","try",100,0,10);
  TF1 *f1 = new TF1("f1","exp(-x/10)*sin(x)*sin(x)",0,10);

C++ は Java ではありません。を使用してオブジェクトを作成する必要はありませんnew

TH1F histo("histo","try",100,0,10);
  TF1 f1("f1","exp(-x/10)*sin(x)*sin(x)",0,10);

最後の問題を除いて、動的配列の作成に をstd::vector使用せずに を使用すれば、これらの問題全体を修正できます。new[]

これらの変更を適用すると、コードは次のようになります (コンパイルされていません)。

#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>

#include "TROOT.h"
#include "TCanvas.h"
#include "TH1.h"
#include "TF1.h"

using namespace std;

vector<int> peak_counter1d(TH1F *histogram,int peak_num,int threshold = 5,int display = 0)
{
  if(display == 1)
  {
    // TCanvas *look = new TCanvas("look","look",500,400);
     histogram->Draw();
  }
  int total_bins = histogram->GetNBinsX();
  vector<int> peak_bins(peak_num);
  peak_bins[0] = histogram->GetMaximumBin();
  int counter = 1;
  vector<int> check_array; // to put previously found peak bins
  while(counter < peak_num){
    double peak = threshold;
    double peak_loc = -500;
    check_array.resize(counter);
    for(int i=0; i<counter; i++){
      check_array[i] = peak_bins[i]; // fills the array with previously found peak bins
    }
    for(int i=0; i<total_bins; i++){
      if(peak < histogram->GetBinContent(i)){ 
        bool exists = find(begin(check_array),end(checkarray),i); // makes sure this is a peak we haven't already found
        if(!exists){
          peak = histogram->GetBinContent(i);
          peak_loc = i;
        }
      }
    }
    peak_bins[counter] = peak_loc;
    counter ++;
  }
  return peak_bins;
}

void testing(){
  gROOT->Reset();
  TH1F histo("histo","try",100,0,10);
  TF1 f1("f1","exp(-x/10)*sin(x)*sin(x)",0,10);
  double val;
  for(int i=0; i<100; i++){
    val = f1.Eval(i/10.0);
    //cout << i << "\t" << i/100.0 << "\t" << val << endl;
    histo.SetBinContent(i,val);
  }

  vector<int> peak_bins = peak_counter1d(&histo,3,5,1);
  for(int i=0; i<3; i++){
    cout << i << "\t" << peak_bins[i] << endl;
  }
}
于 2015-07-06T19:09:08.453 に答える