简体   繁体   中英

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM