سؤال

في ANSI C++, كيف يمكنني تعيين cout تيار متغير الاسم ؟ ما أريد القيام به ، إذا كان المستخدم لديه المحدد الناتج اسم الملف إرسال الإخراج إلى هناك وإلا إرسالها إلى الشاشة.حتى شيء من هذا القبيل:

ofstream outFile;
if (outFileRequested) 
    outFile.open("foo.txt", ios::out);
else
    outFile = cout;  // Will not compile because outFile does not have an 
                     // assignment operator

outFile << "whatever" << endl;

حاولت القيام بذلك باعتباره وظيفة الماكرو أيضا:

#define OUTPUT outFileRequested?outFile:cout

OUTPUT << "whatever" << endl;

ولكن الذي أعطاني خطأ التحويل أيضا.

علي إما أن استخدام IF-ثم كتلة كل الانتاج ، ولكن أود أن تجنب ذلك إذا كان بإمكاني.أي أفكار ؟

هل كانت مفيدة؟

المحلول

استخدم إشارة. لاحظ أن المرجع يجب أن يكون من نوع std::ostream، وليس std::ofstream، منذ std::cout هو std::ostream، لذلك يجب استخدام أقل قاسم مشترك.

std::ofstream realOutFile;

if(outFileRequested)
    realOutFile.open("foo.txt", std::ios::out);

std::ostream & outFile = (outFileRequested ? realOutFile : std::cout);

نصائح أخرى

وأفترض البرنامج يتصرف مثل أدوات يونكس القياسية، أنه عندما لم تعط ملف والكتابة إلى الإخراج القياسي، وعندما تعطى ملف سيكتب في هذا الملف. يمكنك إعادة توجيه cout لكتابة إلى عازلة تيار آخر. طالما التوجيه الخاص بك هو على قيد الحياة، كل ما هو مكتوب على cout ومكتوبة بشفافية إلى الوجهة التي المعينة. مرة واحدة ينتقل الكائن إعادة توجيه خارج النطاق، يتم وضع التيار الأصلي وسيتم إخراج الكتابة إلى الشاشة مرة أخرى:

struct CoutRedirect { 
    std::streambuf * old; 
    CoutRedirect():old(0) {
        // empty
    }

    ~CoutRedirect() {
        if(old != 0) {
            std::cout.rdbuf(old);
        }
    }

    void redirect(std::streambuf * to) {
        old = std::cout.rdbuf(to);
    }
}

int main() {
    std::filebuf file;
    CoutRedirect pipe;
    if(outFileRequested) {
        file.open("foo.txt", std::ios_base::out);
        pipe.redirect(&file);
    }
}

والآن، يتم إعادة توجيه cout إلى ملف طالما الأنابيب على قيد الحياة في main. يمكنك جعله أكثر "إنتاج جاهزة" بجعله غير copyable، لأنها ليست على استعداد ليتم نسخها: إذا كان نسخة يخرج من نطاق، فإنه استعادة التيار الأصلي بالفعل

ويمكنك العثور على شرح مفصل جدا من كيفية القيام بذلك هنا: http://groups.google.com/group/ comp.lang.c ++ / جي اس / 1d941c0f26ea0d81؟ كابلان = 1

ونأمل شخص ما سوف يكتب هذا الأمر أكثر وضوحا لتجاوز سعة مكدس لأخذ النقاط ...

التالية آدم روزنفيلد's المسارات ، ولكن تحديد إشارة التهيئة مشكلة مع الثلاثي و فاصلة المشغلين:

bool outFileRequested = false;

std::ofstream realOutFile;
std::ostream & outFile = outFileRequested
    ? realOutFile.open("foo.txt", std::ios::out), realOutFile
    : std::cout;

outFile << "some witty remark";

(اختبار في مقابل)

وأعتقد آدم على الطريق الصحيح لكنني لا أعتقد أنه يمكنك تعيين المراجع - تحتاج إلى استخدام مؤشر بدلا من ذلك:

std::ofstream realOutFile;
std::ostream * poutFile;

if(outFileRequested)
{
    realOutFile.open("foo.txt", std::ios::out);
    poutFile = &realOutFile;
}
else
    poutFile = &std::cout;

هل يمكن بعد ذلك تحديد إشارة إلى أن قيمة المؤشر، لكنها لن تكون عالمية

std::ostream & outFile = *poutFile;

ولست متأكدا من أنه يمكنك تعيين cout إلى متغير من نوع ofstream. cout هو كائن من نوع ostream (في حين CIN هو من نوع istream) وأنا لست على يقين من أن يرث واحد من الآخر. لذلك، ربما شيء التحقق لمعرفة ما إذا أعطيت / ملف موجود وأنه خلق نوع تيار المناسب أن يكون النهج الأفضل.

وجاء ذلك حوالي ساعتين للحصول على. في الأساس، ولدي الطبقة الخارجية تشغيل مجموعة اختبار. أبعث في مندوب لتشغيل الاختبارات، وذلك من أجل الحصول على الانتاج أنا في حاجة الى ارسال في دفق إخراج. أعتقد أنني يمكن أن تفعل تيار مختلفة لكل اختبار. على أي حال، كنت أريد أن تمر في ofstream لاستخدامها لاحقا.

// Main code to create Test Suite Object
ofstream debugFile("debug.txt");
TestSuiteObject* myTestSuite = new TestSuiteObject(&debugFile);

// Test Suite Object
class TestSuiteObject: public Test::Suite
{
public:
 TestSuiteObject(std::ofstream* debug) : m_debug(*debug)
 {
  m_debug << "some witty remark" << std::endl;
  TEST_ADD(TestSuiteObject::test1);
  TEST_ADD(TestSuiteObject::test2);
  TEST_ADD(TestSuiteObject::test3);

 }

 void test1();
 void test2();
 void test3();

private:
 std::ofstream& m_debug;
};
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top