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.
精彩评论