2

関数のロードでの宿題のために、ifstreamオブジェクトをインスタンス化してファイルを開き、読み込みを開始すると、長いコンパイラエラーが発生します。また、fstreamを削除し、入力をリダイレクトしてcinを使用しようとしましたが、それほど遠くはありませんでした。inの代わりにcinを使用する以外は、まったく同じエラーです。

    #ifndef _BUBBLE_SORT_H
    #define _BUBBLE_SORT_H

    #include <iostream>
    #include <fstream>
    #include <cstdlib>

    using namespace std;

    template <typename T>
    void swap(T *a, T *b){
            T t = *a; 
            *a = *b; 
            *b = t;
    }

    template <typename T>
    void bubbleSort(T * arr, int n){ 
            bool isSorted = false;
            for (int last = n-1; last > 0 && !isSorted; last--) {
                    isSorted = true;
                    for (int i = 0; i < last; i++)
                            if (arr[i] > arr[i+1]) {
                                    swap((arr+i), (arr+i+1));
                                    isSorted = false;
                             }
                    if (last % 1000 == 0) cerr << ".";
            }
    }

    template <typename T>
    void print(T arr[], int n){ 
            for(int i = 0; i < n; i++)
                    cout << arr[i] << '\t';
    }

    template <typename T>
    T &load(string filename, int &n){
            ifstream in; 
            in.open(filename.c_str());

            in >> n;
            if(!in) {
                    cerr << "Error opening file" ;
                    exit(1);
            }   
            T *arr = new T[n];

            for(int i = 0; i < n; i++)
                    in >> *(arr + i); 
            in.close();
            return *arr;
    } 

#endif

私はgnugccコンパイラを使用しています

4

1 に答える 1

1

問題は、load関数の呼び出しにあります。あなたはそれを呼んでいますか、あなたが読んでいる配列のタイプを示していますか?配列を返すようにload関数を編集し、main関数の呼び出し元を編集するための提案を次に示します。

template <typename T>
T *load(string filename, int &n){
        ifstream in; 
        in.open(filename.c_str());

        in >> n;
        if(in.fail()) {
                cerr << "Error opening file" ;
                exit(1);
        }   
        T *arr = new T[n];

        for(int i = 0; i < n; i++)
                in >> *(arr + i); 
        in.close();
        return arr;
} 

int main(){
        int x, i;
        string fileName = "test.txt";
        double *arr = load<double>(fileName, x); // make sure you have <double> in the call
        for(i = 0; i < x; i++) cout << arr[i] << endl;
        delete [] arr;
        return 0;
        }

読み取っている配列のタイプがたとえばdoubleであることを必ず含めてください。そうしないと、エラーが発生します。また、私の謙虚な意見では、上記のスニペットに示されているようにポインタを返す方が良いです。お役に立てば幸いです。

編集

テンプレートの動作方法に少し余分なものがあります。コードをコンパイルすると、プログラム全体で使用されている(Tで表されている)さまざまなタイプの数に応じて、テンプレートが同じ関数のさまざまなバージョンに拡張されます。したがって、それを考慮し、質問で提示されたコードを見ると、コンパイラは未知の型に基づく関数に拡張できないため、ファイル入力ストリームから型Tに読み取ろうとしても意味がありません。ただし、テンプレート変数Tのタイプがわかっている場合(typenameすべてが関数の引数に含まれている場合)、<double>関数呼び出しで渡された引数のタイプから誘導されるため、指定は省略できます。

于 2013-03-04T20:12:04.990 に答える