开发者

Mysterious line break in cout statement

I wrote a small snippet to search for matched strings in an array, then output results for parallel arrays in a nicely formatted fashion. However, I must have some fundamental misunderstanding about how string outputs work, because for the life of me I cannot get this to output correctly, no matter where I put the tab, the newline, or whether I use an endl in my code.

Here is the relevant code below:

for (int i = 0; i < arrayCount; i++) {
    if (arrayCopy[i].find(localString) != string::npos) {
        cout << "\n\t"
        << array1[i] << " {"
        << subArray1[i] << ", "
        << subArray2[i] << "}";
    }
}

I'm expecting results to have a tab at start of each line:

         MatchedString1 {Data, MoreData}
         MatchedString2 {Data, MoreData}
         MatchedString3 {Data, MoreData}

Instead I am getting results like开发者_运维技巧 below, where the tabs appear on blank lines (except for the first result):

         MatchedString1 {Data, MoreData}

MatchedString2 {Data, MoreData}

MatchedString3 {Data, MoreData}

What devilish quirk exists in c++ that is causing me so much pain?!


Using the following source to recreate your problem:

$ cat test.cpp 
#include <iostream>
#include <string>

int main() {
    using std::cout;
    using std::string;

    const std::string array1[] = {"MatchedString1", "MatchedString2", "MatchedString3"};
    const std::string arrayCopy[] = {"MatchedString1", "MatchedString2", "MatchedString3"}; 
    const std::string localString = "String";
    const std::string subArray1[] = {"Data", "Data", "Data"};
    const std::string subArray2[] = {"More data", "More data", "more data"};
    const unsigned int arrayCount = 3;

    for (int i = 0; i < arrayCount; i++) {
        if (arrayCopy[i].find(localString) != string::npos) {
            cout << "\n\t"
                << array1[i] << " {"
                << subArray1[i] << ", "
                << subArray2[i] << "}";
        }
    }
}

Compile and run:

$ g++ test.cpp 
$ ./a.out

        MatchedString1 {Data, More data}
        MatchedString2 {Data, More data}
        MatchedString3 {Data, more data}

Conclusion:

The extra line-breaks are in your data.

Suggestion:

Use square brackets to delineate your input:

std::cout << "[" << array1[i] << "] {[" << subArray1[i] << "], [" << subArray2[i] << "]}" <<  std::endl;

Stripping the strings:

If you find you need to strip your strings, you may find the following functions useful:

std::string lstrip(const std::string& s, const char* chars = " \t\r\n")
{
    std::string::size_type begin = s.find_first_not_of(chars);
    if (begin == std::string::npos)
    {
        return "";
    }
    return std::string(s, begin);
}

std::string rstrip(const std::string& s, const char* chars = " \t\r\n")
{
    std::string::size_type end = s.find_last_not_of(chars);
    return std::string(s, 0, end + 1);
}

std::string strip(const std::string& s)
{
    return lstrip(rstrip(s));
}

Use like this:

        std::cout << "\t"
            << strip(array1[i]) << " {"
            << strip(subArray1[i]) << ", "
            << strip(subArray2[i]) << "}"
            << std::endl;


(Restating my comment as a possible answer.)

The standard approach is to always put the \n at the end and everything else in the order it appears.

The only thing I can think of that would break this is a \r at the beginning of the second and third matched strings. (Someone else rightly observed that the double-spacing suggests a \n at the beginning of the input.)


Are you sure this isn't just somethin silly like "MatchedString" actually being "\nMatchedString"? You could try printing some extra stuff there to delineate your whitespace more clearly.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜