1

2001 年に出版された本「Data Structures and Algorithms in C++」を読んでいますが、この本のコードがコンパイルできないことがわかったので、C++ コンパイラはその時から大幅に変更する必要があると思います。

#include <fstream.h>
#include <string.h>

だから私は答えをグーグルで探し、コードを次のように変更しました

#include <fstream>
#include <cstring>
using namespace std;

しかし、コードをコンパイルしようとすると、見たことのないエラーが発生しました。

oo@oo:~/raf$ g++ database.cpp personal.cpp student.cpp useDatabase.cpp -o useDatabase
In file included from /usr/include/c++/4.6/ios:45:0,
                 from /usr/include/c++/4.6/istream:40,
                 from /usr/include/c++/4.6/fstream:40,
                 from personal.h:4,
                 from student.h:1,
                 from student.cpp:1:
/usr/include/c++/4.6/bits/ios_base.h: In copy constructor ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’:
/usr/include/c++/4.6/bits/ios_base.h:788:5: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private
/usr/include/c++/4.6/bits/basic_ios.h:64:11: error: within this context
In file included from /usr/include/c++/4.6/istream:41:0,
                 from /usr/include/c++/4.6/fstream:40,
                 from personal.h:4,
                 from student.h:1,
                 from student.cpp:1:
/usr/include/c++/4.6/ostream: In copy constructor ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’:
/usr/include/c++/4.6/ostream:57:11: note: synthesized method ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’ first required here 
In file included from student.cpp:1:0:
student.h: In function ‘std::ostream& operator<<(std::ostream&, Student&)’:
student.h:17:39: note: synthesized method ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’ first required here 
student.h:15:18: error:   initializing argument 1 of ‘std::ostream& Student::writeLegibly(std::ostream)’
student.cpp: At global scope:
student.cpp:24:10: error: prototype for ‘std::ostream& Student::writeLegibly(std::ostream&)’ does not match any in class ‘Student’
student.h:15:18: error: candidate is: std::ostream& Student::writeLegibly(std::ostream)
student.cpp: In member function ‘std::istream& Student::readFromConsole(std::istream&)’:
student.cpp:34:5: error: ‘cout’ was not declared in this scope
In file included from /usr/include/c++/4.6/ios:45:0,
                 from /usr/include/c++/4.6/ostream:40,
                 from /usr/include/c++/4.6/iostream:40,
                 from useDatabase.cpp:1:
/usr/include/c++/4.6/bits/ios_base.h: In copy constructor ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’:
/usr/include/c++/4.6/bits/ios_base.h:788:5: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private
/usr/include/c++/4.6/bits/basic_ios.h:64:11: error: within this context
In file included from /usr/include/c++/4.6/iostream:40:0,
                 from useDatabase.cpp:1:
/usr/include/c++/4.6/ostream: In copy constructor ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’:
/usr/include/c++/4.6/ostream:57:11: note: synthesized method ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’ first required here 
In file included from useDatabase.cpp:2:0:
student.h: In function ‘std::ostream& operator<<(std::ostream&, Student&)’:
student.h:17:39: note: synthesized method ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’ first required here 
student.h:15:18: error:   initializing argument 1 of ‘std::ostream& Student::writeLegibly(std::ostream)’
oo@oo:~/raf$ 

答えを得るためにGoogleに多くの時間を費やしましたが、さらに多くのエラーが発生しました. Github アカウントを登録して、そこにコードをアップロードする必要があるかもしれません。

データベース.cpp

#include "database.h"

template<class T> Database<T>::Database() {
    cout << "File name: ";
    cin >> fName;
}

template<class T> void Database<T>::add(T& d){
    database.open(fName, ios::in|ios::out|ios::binary);
    database.seekp(0, ios::end);
    d.writeToFile(database);
    database.close();
}

template<class T> void Database<T>::modify(const T& d){
    T tmp;
    database.open(fName, ios::in|ios::out|ios::binary);
    while(!database.eof()){
        tmp.readFromFile(database);
        if (tmp == d){
            cin >> tmp;
            database.seekp(-d.size(), ios::cur);
            tmp.writeToFile(database);
            database.close();
            return;
        }
    }
    database.close();
    cout << "The record to be modified is not in the database\n";
}

template<class T> bool Database<T>::find(const T& d){
    T tmp;
    database.open(fName, ios::in|ios::binary);
    while(!database.eof()){
        tmp.readFromFile(database);
        if (tmp == d){
            database.close();
            return true;
        }
    }
    database.close();
    return false;
}

template<class T> ostream& Database<T>::print(ostream& out){
    T tmp;
    database.open(fName, ios::in|ios::binary);
    while(1){
        tmp.readFromFile(database);
        if (database.eof())
            break;
        out << tmp << endl;
    }
    database.close();
    return out;
}

template<class T> void Database<T>::run() {
    char option[5];
    T rec;
    cout << "1.Add 2.Find 3.Modify a record 4.Exit\n";
    cout << "Enter an option: ";
    cin.getline(option, 4);
    while (cin.getline(option, 4)){
        if (*option == '1'){
            cin >> rec;
            add(rec);
        }
        else if (*option == '2'){
            rec.readKey();
            cout << "The record is ";
            if (find(rec) == false)
                cout << "not ";
            cout << "in the database\n";
        }
        else if (*option == '3'){
            rec.readKey();
            modify(rec);
        }
        else if (*option != '4'){
            cout << "Wrong option\n";
        }
        else return;
        cout << *this;
        cout << "Enter an option";
    }
}

データベース.h

#ifndef DATABASE
#define DATABASE
#include <fstream>
#include <iostream>
using namespace std;

template<class T> class Database{
    public:
        Database();
        void run();
    private:
        fstream database;
        char fName[20];
        ostream& print(ostream&);
        void add(T&);
        bool find(const T&);
        void modify(const T&);
        friend ostream& operator<<(ostream& out, Database& db) {
            return db.print(out);
        }
};
#endif

個人.cpp

#include "personal.h"
#include <iostream>

Personal::Personal() : nameLen(10), cityLen(10) {
    name = new char[nameLen + 1];
    city = new char[cityLen + 1];
}

Personal::Personal(char *ssn, char *n, char *c, int y, long s) : nameLen(10), cityLen(10) {
    name = new char[nameLen + 1];
    city = new char[cityLen + 1];
    strcpy(SSN, ssn);
    strcpy(name, n);
    strcpy(city, c);
    year = y;
    salary = s;
}

void Personal::writeToFile(fstream& out) const {
    out.write(SSN, 9);
    out.write(name, nameLen);
    out.write(city, cityLen);
    out.write(reinterpret_cast<const char*>(&year), sizeof(int));
    out.write(reinterpret_cast<const char*>(&salary), sizeof(int));
}

void Personal::readFromFile(fstream& in) {
    in.read(SSN, 9);
    in.read(name, nameLen);
    in.read(city, cityLen);
    in.read(reinterpret_cast<char *>(&year), sizeof(int));
    in.read(reinterpret_cast<char *>(&salary), sizeof(int));
}

void Personal::readKey() {
    char s[80];
    cout << "Enter SSN: ";
    cin.getline(s, 80);
    strncpy(SSN, s, 9);
}

ostream& Personal::writeLegibly(ostream& out){
    SSN[9] = name[nameLen] = city[cityLen] = '\0';
    out << "SSN = " << SSN << ", name = " << name
        << ", city = " << city << ", year = " << year
        << ", salary = " << salary;
    return out;
}

istream& Personal::readFromConsole(istream& in){
    char s[80];
    cout << "SSN: ";
    in.getline(s, 80);
    strncpy(SSN, s, 9);
    cout << "Name: ";
    in.getline(s, 80);
    strncpy(name, s, nameLen);
    cout << "City: ";
    in.getline(s, 80);
    strncpy(city, s, cityLen);
    cout << "Birthyear: ";
    in >> year;
    cout << "Salary: ";
    in >> salary;
    in.getline(s, 80); //get '\n'
    return in;
}

個人.h

#ifndef PERSONAL
#define PERSONAL

#include <fstream>
#include <cstring>
using namespace std;

class Personal {
    public:
        Personal();
        Personal(char*, char*, char*, int, long);
        void writeToFile(fstream&) const;
        void readFromFile(fstream&);
        void readKey();
        int size() const {
            return 9 + nameLen + cityLen + sizeof(year) + sizeof(salary);
        }
        bool operator==(const Personal& pr) const{
            return strcmp(pr.SSN, SSN) == 0;
        }

    protected:
        const int nameLen, cityLen;
        char SSN[10], *name, *city;
        int year;
        long salary;
        ostream& writeLegibly(ostream&);
        friend ostream& operator<<(ostream& out, Personal& pr){
            return pr.writeLegibly(out);
        }
        istream& readFromConsole(istream&);
        friend istream& operator>>(istream& in, Personal& pr){
            return pr.readFromConsole(in);
        }
};

#endif

学生.cpp

#include "student.h"

Student::Student() : majorLen(10) {
    Personal();
    major = new char[majorLen + 1];
}

Student::Student(char *ssn, char *n, char *c, int y, long s, char *m): majorLen(11){
    Personal(ssn, n, c, y, s);
    major = new char[majorLen + 1];
    strcpy(major, m);
}

void Student::writeToFile(fstream& out) const {
    Personal::writeToFile(out);
    out.write(major, majorLen);
}

void Student::readFromFile(fstream& in) {
    Personal::readFromFile(in);
    in.read(major, majorLen);
}

ostream& Student::writeLegibly(ostream &out){
    Personal::writeLegibly(out);
    major[majorLen] = '\0';
    out << ", major = " << major;
    return out;
}

istream& Student::readFromConsole(istream& in){
    Personal::readFromConsole(in);
    char s[80];
    cout << "Major: ";
    in.getline(s, 80);
    strncpy(major, s, 9);
    return in;
}

学生.h

#include "personal.h"

class Student : public Personal {
    public:
        Student();
        Student(char*, char*, char*, int, long, char*);
        void writeToFile(fstream&) const;
        void readFromFile(fstream&);
        int size() const{
            return Personal::size() + majorLen;
        }
    protected:
        char *major;
        const int majorLen;
        ostream& writeLegibly(ostream);
        friend ostream& operator<<(ostream& out, Student& sr){
            return sr.writeLegibly(out);
        }
        istream& readFromConsole(istream&);
        friend istream& operator>>(istream& in, Student& sr){
            return sr.readFromConsole(in);
        }
};

useDatabase.cpp

#include <iostream>
#include "student.h"
#include "personal.h"
#include "database.h"

int main(){
    Database<Personal> db;
    db.run();
}
4

4 に答える 4

4

これは、SO の質問で分析するには大きな (おそらく大きすぎる) ファイルのセットでした。SO (または技術サポート) に提示するために、問題のサイズを縮小するいくつかの方法を学ぶ必要があります。

C または C++ での最初のステップの 1 つは、作成したヘッダーが正常にコンパイルされるようにすることです。ヘッダーがクリーンでない場合、ヘッダーを使用するコードをコンパイルできないため、最初にヘッダーを整理する必要があります。

私を助けるために、私が呼び出すスクリプトがありますchkhdr

#!/bin/sh
# Check whether headers compile

tmp=chkhdr-$$
trap 'rm -f $tmp.?; exit 1' 0 1 2 3  13 15

cat > $tmp.c <<EOF
#include HEADER /* Check self-containment */
#include HEADER /* Check idempotence */
int main(void) { return 0; }
EOF

options=
for file in "$@"
do
    case "$file" in
    (-*) options="$options $file";;
    (*)  echo "$file"
         ${CC:-gcc} $options -DHEADER="\"$file\"" -c $tmp.c
         ;;
    esac
done

rm -f $tmp.?
trap 0

これを使用して、ヘッダーが自己完結型で冪等であることを確認します。自己完結型ヘッダーは、その前に他のヘッダーなしで含めることができ、コンパイルされます。つまり、サービスが必要な場所ならどこでも、手間をかけずに使用できます。べき等ヘッダーは、問題を引き起こすことなく複数回含めることができます。(私は主に C で作業しているため、デフォルトのコンパイラは G++ ではなく GCC です。ただしCC=g++、環境で設定して C++ 作業に切り替えることができます。)

あなたのstudent.hヘッダーはべき等ではありませんでした。私はすぐに標準スタンザを上下に追加しました。

#ifndef STUDENT_H_INCLUDED
#define STUDENT_H_INCLUDED

...original contents of student.h...

#endif /* STUDENT_H_INCLUDED */

ガード マクロ名の詳細な選択はユーザー次第です。これは私が最近使用している命名方式ですが、ヘッダーのドラフトの MD5 チェックサムのようなものを使用して、準ランダム ガード マクロを提供することにはいくつかのメリットがあります。

student.hヘッダーのみをコンパイルした場合の出力は次のとおりです。

In file included from chkhdr-8120.c:1:
/usr/include/c++/4.2.1/bits/ios_base.h: In copy constructor ‘std::basic_ios<char, std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)’:
/usr/include/c++/4.2.1/bits/ios_base.h:779: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private
/usr/include/c++/4.2.1/iosfwd:55: error: within this context
/usr/include/c++/4.2.1/iosfwd: In copy constructor ‘std::basic_ostream<char, std::char_traits<char> >::basic_ostream(const std::basic_ostream<char, std::char_traits<char> >&)’:
/usr/include/c++/4.2.1/iosfwd:64: note: synthesized method ‘std::basic_ios<char, std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)’ first required here 
student.h: In function ‘std::ostream& operator<<(std::ostream&, Student&)’:
student.h:20: note: synthesized method ‘std::basic_ostream<char, std::char_traits<char> >::basic_ostream(const std::basic_ostream<char, std::char_traits<char> >&)’ first required here 
student.h:20: error:   initializing argument 1 of ‘std::ostream& Student::writeLegibly(std::ostream)’

エラー メッセージの最後の行は、問題を明確に示しています。他のメッセージはやや関連性があり、核心メッセージにつながります。(非常に多くの場合、特に C では、最初のエラーが最も重要です。最後の行が重要な行であることに驚きました。) の 20 行目を次のように変更student.hします。

    ostream& writeLegibly(ostream&);

その問題を解決し、student.hヘッダーがきれいにコンパイルされました。他のヘッダーもきれいでした。その後、ソース ファイルをコンパイルするのは簡単なことでした。問題があっただけstudent.cppです:

student.cpp: In member function ‘std::istream& Student::readFromConsole(std::istream&)’:
student.cpp:34: error: ‘cout’ was not declared in this scope

「代わりに使用する必要がある」場合のように聞こえますがstd::cout、それを追加すると次のようになります。

student.cpp: In member function ‘std::istream& Student::readFromConsole(std::istream&)’:
student.cpp:34: error: ‘cout’ is not a member of ‘std’

を含めることで修正され#include <iostream>ます。次に、コードは次の場所できれいにコンパイルされます。

g++ -c *.cpp

リンクできません。データベース コードへの未定義の参照に出くわしましたが、それは驚くべきことではありません。


概要

修正の詳細はそれほど重要ではありません。大切なのはテクニックです。ここでの重要なテクニックは次のとおりです。

  1. ヘッダーが単独で正常に動作することを確認します ( chkhdr)。
  2. 一度に 1 つのファイルに取り組みます。
  3. 問題の最小化。

すべてのコードを処理する必要はありませんでした。問題をより適切に切り分けることができたはずです。これは、ソフトウェアの問題を他の人に報告するあらゆる状況で重要なスキルです。不要なものを排除し、必要最小限のものに減らします。

于 2012-04-07T07:42:50.430 に答える
3

Student変更中

ostream& writeLegibly(ostream);

ostream& writeLegibly(ostream&);

そしてそれは多くを修正するはずです。アンパサンドが欠落しているため、ストリームをコピーしようとしていました。

于 2012-04-07T07:11:43.857 に答える
3

コンパイラは C++ を変更しましたが、C は下位互換性があります。言語の強みの 1 つ。とにかく、あなたのコードを VS2010 にコピーしました。問題を分析する方が簡単だったからです。

  1. #include < iostream > を personal.h に入れます。これは、cout がある personal.cpp によって使用されます。

  2. の Student.h の署名

    ostream& writeLegibly(ostream);
    

    間違っています。次のようにする必要があります。

    ostream& writeLegibly(ostream&);
    
  3. database.cpp の実装コードを database.h に移動しました。#endif の上に単純な切り取りと貼り付けを行います。テンプレートの性質上、コンパイラはそれが別の実装 cpp にあることを好みませんでした。

それが役立つことを願っています。

于 2012-04-07T07:33:46.340 に答える
3

エラーレポート

student.cpp:34:5: error: ‘cout’ was not declared in this scope

私はあなたが必要だと思います

#include <iostream>
于 2012-04-07T06:52:16.853 に答える