【问题标题】:Strange C++ std::string behavior... How can I fix this?奇怪的 C++ std::string 行为......我该如何解决这个问题?
【发布时间】:2009-04-28 05:16:26
【问题描述】:

这让我发疯了。我已经研究了 2 个多小时试图弄清楚这一点......

这是我的问题。我正在开发一个与贝叶斯网络一起使用的相当大的程序。这是主要功能:

using namespace std;

int main()
{  
    DSL_network net;
    initializeNetwork(net); 
    setEvidence(net);
    net.SetDefaultBNAlgorithm(7);
    net.SetNumberOfSamples(80000);
    cout << "Samples:\t" << net.GetNumberOfSamples() << endl;
    updateEvidence(net);
    //net.WriteFile("test.dsl");
    return(DSL_OKAY);
}

这一切都很好。当我想打印一个字符串时,问题就来了:

using namespace std;

int main()
{  
    //simple string creation
    string a = "test";
    //should print out "test"
    cout << a << endl;
    DSL_network net;
    initializeNetwork(net); 
    setEvidence(net);
    net.SetDefaultBNAlgorithm(7);
    net.SetNumberOfSamples(80000);
    cout << "Samples:\t" << net.GetNumberOfSamples() << endl;
    updateEvidence(net);
    //net.WriteFile("test.dsl");
    return(DSL_OKAY);
}

这是输出(只是打印字符串 a...):

   ▀ÇΦy♠≈6 ♦

会发生什么?

更新:

int main()
    {  
        //simple string creation
        string a = "test";
        //should print out "test"
        cout << a << endl;
        return(DSL_OKAY);
    }

仍然打印

▀ÇΦy♠≈6 ♦

重大更新: 这是最近的。我创建了一个全新的项目并粘贴了 Neil Butterworth 发布的代码(谢谢顺便说一句)。我运行了代码,它打印正确。然后我将这两个.lib 文件添加到新项目的链接器中(smile.lib 用于 SMILE 库,wsock32.lib 用于套接字。)

我再次尝试了代码,它正确打印了第一个“测试”,然后打印了乱码。这是我链接在一起的一个 .lib 的问题。我自己尝试了每一个,看看它们是否只是冲突,似乎是 Smile.lib 库导致了这个问题。我需要查看他们的文档并找出原因。

有什么想法吗?

感谢大家的帮助

谢谢

【问题讨论】:

  • 这有点含糊(至少在这个时候对我来说)——你是在说:'string a = "test"; cout
  • 是否有任何#includes 也可能包含字符串类?
  • 是的,可能有。这会是个问题吗?我会检查的
  • “我是一个使用贝叶斯网络的相当大的程序。”哇,我印象深刻,你写了一个有感知力的程序,它知道如何向 SO 发布它自己的问题!
  • 我检查了#includes,没有冲突。

标签: c++ string


【解决方案1】:

这很奇怪。我总是喜欢将问题分解为最小的情况。下面的程序在你运行时做了什么?

using namespace std;
int main() {  
    string a = "test";
    cout << a << endl;
    return 0;
}

如果这样可行,那么还有其他问题,您需要一次添加一行,直到它失败。然后仔细检查那行非常(“我在打猎兔兔”)。

根据您的编辑,可能使用了不同的字符串类。试试这个:

int main() {  
    std::string a = "test";
    std::cout << a << std::endl;
    return 0;
}

更新:

由于它适用于新项目而不是当前项目,请检查以下内容。

  • 确保您链接的是标准 C++ 运行时。
  • 确保您没有将string 定义为其他内容(其中包括编译器的-Dstring=somethingelse 命令行选项)。
  • 使用std::string检查行为,而不仅仅是string

【讨论】:

  • 这都是与项目相关的......我打开了另一个项目,它工作正常。是否有一些设置是错误的?谢谢
  • 如果您有调试器,请在打印前检查实际变量“a”。它可能不是 std::string。 std:: 版本在可疑项目中做了什么?
  • 您使用的是哪个编译器/IDE。项目是特定于产品的。
  • 两个字符串(正在工作的项目,和顶起一个)显示为 std::basic_string,std::allocator>。我正在使用 VS2005 谢谢
  • 这是个问题吗? .\SocketC.cpp(207) : 警告 C4996: 'strerror' 被宣布弃用
【解决方案2】:

也试试这个:

int main()
    {  
        //simple string creation
        string a = "test";
        const char* cStr = a.c_str();
        //should print out "test"
        cout << cStr << endl;
        return(DSL_OKAY);
    }

如果const char* 行没有导致编译器错误,那么我们知道std::str 是一个8 位字符串。如果cout 没有导致编译器错误,那么我们知道cout 是为8 位字符定义的。 (如果程序产生相同的结果,那么我们仍然感到困惑:-}

编辑(基于您在下面的评论):我注意到“test”的错误输出为 9 个字符——“▀ÇΦy♠≈6 ♦”。尝试其他“测试”字符串,例如,哦,“retest”或“foo”。我怀疑您的输出通常是原始字符串中字符数的 2x 或 2x+1(“retest”为 12 或 13,“foo”为 6 或 7。)这表明您正在输入 16 位字符串进入一个 8 位缓冲区。不过,我不知道您如何才能通过编译器 - 也许您对 std::string 和/或 cout 的定义有误或过时?

编辑 2:我记得我以前在哪里看到过这个。几年前,我看到了一个问题,即 DOS 控制台窗口破坏了程序的输出。 (我不记得确切的细节,但我认为问题在于 DOS 控制台无法处理 UTF-8 字符集。)如果您在 DOS 窗口中看到此输出(或者,不太可能,如果它是通过system() 传送到另一个程序),然后尝试将其重定向到一个文件,然后用记事本打开该文件。它可能会起作用......

【讨论】:

  • 这是我打印“a”得到的结果:ÿÿÿÿ߀èy÷6
  • 附言。长度始终为15... ▀ÇΦy♠≈6 ♦ 前后有一些空字符
【解决方案3】:

检查是否

  • 你有#include&lt;iostream&gt; 和其他相关的标题包括吗?
  • net.GetNumberOfSamples() 具有有效值 AND
  • 你没有混合stringwstring

【讨论】:

  • 是的。假设包含正确的#include。 net.GetNumberofSamples 是问题所在。这将返回一个 int 并打印正常。
【解决方案4】:

您是否 100% 认为源代码文件是 ASCII?尝试在一些十六进制编辑器中打开它。

尝试在一个全新的文件中输入(而不是复制/粘贴)代码,看看会发生什么。

如果失败了,那么显然你的 cout 有什么问题。你能告诉我们哪些库链接到可执行文件中吗?也许某些东西会关闭标准输出流或类似的东西。

【讨论】:

    【解决方案5】:

    我建议您慢慢删除所有#include,直到找到导致问题的那个。

    【讨论】:

      【解决方案6】:

      您可以尝试为字符串类型显式指定 std 命名空间。

      我建议您尝试这样做的主要原因是,在某些包含的头文件中可能有一个定义,它将字符串替换为其他一些类或定义。添加命名空间应强制不使用宏。

      要检查的另一件事是获取写入文件的源代码的已处理列表(或程序集和源代码列表,如果您想进行一些程序集黑客攻击)并检查它以查看发生了什么.如果不出意外,您可能会在那里找到答案。

      【讨论】:

        【解决方案7】:

        编译并运行以下确切代码;不要添加任何 using 指令。

        #include <iostream>
        #include <string>
        
        int main() {
            std::string s = "test";
            for ( unsigned int i = 0; i < s.size(); i++ ) {
                std::cout << s[i];
            }
            std::cout << "\n";
            std::operator<<( std::cout, s );
            std::cout << "\n";
        }
        

        如果循环打印“test”,则表示字符串正常,问题出在输出中。如果第二个“测试”被破坏,那么问题肯定出在输出处理中。

        【讨论】:

        • 感谢您的提示。在我的帖子中查看我的重大更新
        【解决方案8】:

        将 std::string 转换为 char 字符串是否有效。 即:

        cout << a << endl;
        

        变成

        cout << a.c_str() << endl;
        

        【讨论】:

          【解决方案9】:

          您似乎很可能正在混合 wchar 和 char,因此在您的主要固定字符被认为是宽的(2 字节/字符)或一些 unicode,并且您的 cout 库认为它们是简单的 1 字节/字符。我会查看与项目链接的库。

          不幸的是,我不确定如何解决这个问题。几乎可以肯定,您可以更改项目的某个设置(不幸的是,我面前没有 VS 2005),但您正在寻找诸如 wchar、t_char 或 unicode 之类的东西。

          我很好奇如果你使用会发生什么

          string a("test");
          

          而不是直接分配。

          【讨论】:

            【解决方案10】:

            是否有可能在同一个项目的另一个文件中的某个位置,operator &lt;&lt; 被重载? 请尝试搜索“operator &lt;&lt;”或“operator&lt;&lt;”。

            【讨论】:

              【解决方案11】:

              建议:

              • 在您的cout &lt;&lt; 之前致电cout.flush,看看您是否得到了奇怪的字符
              • 试试printf

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-11-17
                • 1970-01-01
                • 2020-03-25
                • 2020-02-14
                • 1970-01-01
                相关资源
                最近更新 更多