【问题标题】:How to print a CStringList in c++ using cout如何使用 cout 在 C++ 中打印 CStringList
【发布时间】:2011-07-28 08:15:09
【问题描述】:

我是 C++ 新手。我只是在浏览一些代码并产生了这个疑问。

代码在某处定义了一些 CStringList。我想将其打印到文件中。所以我写了下面的代码

 CStringList *stringListDev;
 .....
 .....
 .....
 ..... 
 ofstream myfile("example.txt");
 for(int i=0; i<stringListDev->Count; i++)
 {
    myfile << stringListDev[i];
 }

我收到一条错误消息,说 请指导我如何将字符串列表的内容写入 C++ 文件。

【问题讨论】:

  • 请提供准确的错误信息。
  • @wiso - 这是一个 MFC 集合类。

标签: c++ string mfc


【解决方案1】:

CString 和相关的容器根据文件中的 UNICODE 设置定义它们的字符类型。如果您的程序始终遵循 UNICODE 字符集,您可以坚持使用 wofstream。否则,请附上如下定义。因此,您可以确保您的程序能够以 UNICODE 和 ASCII/MBCS 字符集编译。

#ifdef UNICODE
typedef ofstream tstream;
#else
typedef wofstream tstream;
#endif

tstream myfile("example.txt");

很高兴了解 BOM 字符以及读取/写入 Unicode 字符串的一些注意事项。

【讨论】:

    【解决方案2】:

    CStringList 类本身是一个集合类,你不希望它是指针。

    CStringList stringListDev;
    ofstream myfile("example.txt"); 
    for(int i=0; i<stringListDev.GetCount(); i++) 
    { 
      myfile << stringListDev[i]; 
    }
    

    【讨论】:

      【解决方案3】:

      让我这样重写你的代码。

      CStringList stringListDev; // CStringList doesn't need to be a pointer.
       .....
       .....
       .....
       ..... 
       ofstream myfile("example.txt");
       for(int i=0; i<stringListDev.Count; i++)
       {
          myfile << stringListDev[i].GetBuffer(stringListDev[i].GetLength());
          stringListDev[i].ReleaseBuffer();
       }
      

      CStringList 类包含CString 对象的列表,这是另一个 MFC 类。对于cout,我认为您需要LPTSTR 作为输入。所以,使用GetBuffer() 函数来获得相同的结果,不要忘记调用ReleaseBuffer()。欲了解更多信息,请参阅the documentation

      根据我的经验,传递不带参数的 GetBuffer(默认参数为 0)也会返回指向字符串的指针,您无需调用 ReleaseBuffer(),因为它返回指向原始字符串的指针而没有任何内存分配。但我不建议这样做,因为它不在文档中。

      【讨论】:

      • 如果您不应该修改它,则将 0 传递给 GetBuffer。只要您不应该修改它,就不建议调用 getbuffer。 CString 重载了 LPCTSTR 运算符。
      • 我同意它不安全。我也没推荐!但是前一种方式有什么问题呢?我们将在使用后很快发布它。
      • 出现异常怎么办?这可能适合这种情况。传递我们需要的任何东西并使其安全,这更像是一种编程实践。如果你读过 Effective C++,有一个关于将内部指针暴露给外部世界的好建议。它清楚地说明了问题
      • 同意!如果传递的 CString 对象自动转换为 LPCTSTR,则不需要 GetBuffer
      • 是的..这是人们没有意识到的。大多数人不知道有一个运算符 LPCTSTR,即使是那些知道显式调用的人也是 strObj.operator LPCTSTR();明确地。在这种情况下,函数和运算符之间没有区别。
      【解决方案4】:

      如果它符合您的目的,您可以使用CStringList::Serialize 将对象的内容写入文件。 查看示例代码:

      CStringList csList;
      csList.AddTail( L"A" ); // Filling sample data
      csList.AddTail( L"B" );
      csList.AddTail( L"C" );
      CFile File( L"foo.txt", CFile::modeCreate | CFile::modeWrite ); // File opened using CFile object
      CArchive Arch( &File, CArchive::store , MAX_PATH ); // Assign it to CArchive object
      csList.Serialize( Arch ); // Call Serialize
      Arch.Close();
      File.Close();
      

      此代码将csList 的内容写入foo.txt 作为二进制数据。您可以通过类似的方式将其加载到对象中。

      参考

      Serialization CArchive CFile

      【讨论】:

        【解决方案5】:

        您应该使用std::vectorstd::string,而不是编写自己的类:

        #include <vector>
        #include <string>
        
        std::vector<std::string> stringArray;
        
        stringArray.push_back("some string");
        stringArray.push_back("some other string");
        //..
        
        for(size_t i = 0 ; i < stringArray.size(); i++ )
            std::cout << stringArray[i] << std::endl;
        

        您还可以在上面的代码中使用myfile 代替std::cout

        您也可以将 for 循环替换为:

        #include <iterator>
        #include <algorithm>
        
        std::copy(stringArray.begin(), stringArray.end(), 
                  std::ostream_iterator<std::string>(myFile,"\n"));
        

        【讨论】:

        • +1(建议使用标准类),-1(建议 std::copy)= 0。
        • @6502: 是的,我也想知道:)
        • 没有错,除了使代码长 25%(不包括额外的包含),需要更多的时间和更多的内存来编译,如果出现拼写错误,会吐出大约 5 个充满废话的屏幕对于明确的错误消息,它不能单步执行,它的灵活性较低(例如,在显式情况下添加行号是微不足道的),最后它可能会运行得慢一些(不确定这一点,tho)。实际上,IMO 不包括“嘿妈妈……看!没有明确的循环!”加上这种方法(如果你真的想称之为加分)它有什么好的部分?
        • @6502:我同意这一点。但我并不认为它是最好的,而是希望他熟悉标准库附带的其他内容。例如,我知道我可以使用std::copy,但我从未将它用于我的真实代码(替换loop),原因与您提到的相同,但只是因为它很慢,并不意味着我不应该熟悉这个。
        【解决方案6】:

        CStringListGetAt(pos) 方法,它返回CString。 要将CString 输出到ofstream,请使用CT2A

        myfile << CT2A(stringListDev->getAt(i));
        

        别忘了关闭文件:

        myfile.close();
        

        UPD 你也可以使用std::wofstream

        wofstream myfile("example.txt");
        myfile << (LPCTSTR) stringListDev->getAt(i);
        

        【讨论】:

        • LPCTSTR 是长指针常量 TCHAR 字符串。 wofstream 完全是 UNICODE 的东西。如果项目是 UNICODE 的东西,它就可以工作。否则会失败
        【解决方案7】:

        我自己弄的。代码很简单

           CStringList *stringListDev;
           .....
           .....
           .....
           ..... 
           ofstream myfile("example.txt");
           for(int i=0; i<stringListDev->Count; i++)
           {
              myfile << stringListDev->Strings[i];
           }
        

        感谢您的所有回复!你们摇滚!!

        【讨论】:

          【解决方案8】:

          如果这确实是关于 MFC CStringList 的问题,那么迭代不正确(至少对于 MFC in Visual Studio 2010)。

          CStringList stringListDev;
          // add to list
          POSITION pos = stringListDev.GetHeadPosition();
          while(pos != NULL)
          {
              CString value = stringListDev.GetNext(pos);
              myfile << (LPCTSTR)value; // cast to use built in operator
          }
          

          附带说明: 与标准库相比,MFC 在结构和设计上相当陈旧,我建议仅在与其他 MFC 代码(CDialog 等)交互的严格需要时才使用它们.)

          【讨论】:

            猜你喜欢
            • 2021-12-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-29
            相关资源
            最近更新 更多