3

Let's say we have a long string with multiple newline characters:

char const* some_text = "part1\n\npart2\npart3";

Now the task is to replace all '\n' characters with spaces if it appears only once between text parts, and at the same time leave all '\n' characters if it appears more than once. In other words:

"123\n456" => "123 456"
"123\n\n456" => "123\n\n456"
"123\n\n456\n789" => "123\n\n456 789"

What is the best way to do this?

ventsyv
  • 3,316
  • 3
  • 27
  • 49
  • Looping through and checking for newlines and changing if next not newline? – Sami Kuhmonen Sep 16 '15 at 20:13
  • 2
    `std::regex_replace` – mastov Sep 16 '15 at 20:14
  • possible duplicate of [How to replace all occurrences of a character in string?](http://stackoverflow.com/questions/2896600/how-to-replace-all-occurrences-of-a-character-in-string) – ventsyv Sep 16 '15 at 20:15
  • is this C or C++? If C++, why not `std::string` – Olipro Sep 16 '15 at 20:16
  • 1
    @ventsyv: If you read the question, you'd see that this one does not ask to replace ALL occurrences – Ben Voigt Sep 16 '15 at 20:21
  • My bad, I misunderstood the question. – ventsyv Sep 16 '15 at 20:23
  • The most interesting to me is which company it is where programmers are asked to implement various user-hostile things like this, expending energy on that. – Cheers and hth. - Alf Sep 16 '15 at 20:23
  • @mastov, OMG! Dont ever use regex! Especially for custom text processing logic. –  Sep 16 '15 at 20:26
  • This seems like a pretty straightforward process to implement using basic string manipulation. Whatever mental process you used to create your examples, just code that up. – MooseBoys Sep 16 '15 at 20:28
  • 3
    @AlekDepler what's your concern with using `regex`? Performance? – mattnewport Sep 16 '15 at 20:31
  • 2
    WARNING: do *not* try to make any modifications of this C string: `char* some_text = "part1\n\npart2\npart3";`. - it's *read-only*; on many platforms writing to it will die with an access violation! – paulsm4 Sep 16 '15 at 20:34
  • @mattnewport, I just often have situations when 1km-long regular expression (written by someone else when dinosaurs were still alive) is "doing something" and you are acting like Sherlock Holmes trying to understand it's logic. Besides this, there some compatibility issues on different platforms. –  Sep 16 '15 at 20:48
  • @AlekDepler regexes, like any tool, can be abused but as of C++11 they are standardized in C++ (so there shouldn't be any cross platform differences) and for many uses they are much simpler (and likely more efficient) than custom code. This particular problem is simple enough that a regex may not be much simpler than the direct solution though. – mattnewport Sep 16 '15 at 20:59

3 Answers3

3

The following regular expression detects single occurrences of newlines:

([^\n]|^)\n([^\n]|$)

|-------|
no newline before
(either other character or beginning of string)

        |--|
       newline

           |--------|
        no newline after
   (either other character or end of string)

You can use that regular expression in std::regex_replace in order to replace those single newlines by spaces (and keeping the matched character before and after the newline by adding $1 and $2):

std::string testString("\n123\n\n456\n789");
std::regex e("([^\n]|^)\n([^\n]|$)");
std::cout << std::regex_replace(testString, e, "$1 $2") << std::endl;
mastov
  • 2,942
  • 1
  • 16
  • 33
2

This function may works for your case, just manually check and replace single \n with space. There may have better option like regex_replace.

void rep(char ch[])
{
    int cnt = 0;
    int i;
    for(i=0; ch[i]!='\0'; i++)
    {
        if(ch[i]=='\n')
            cnt++;
        else if(cnt==1)
        {
            ch[i-1]=' ';
            cnt=0;
        }
        else
            cnt=0;
    }
    if(cnt==1)
        ch[i-1]=' ';
}
ashiquzzaman33
  • 5,781
  • 5
  • 31
  • 42
2

Since it was tagged as C++, I'll treat it as such. Obviously this could be solved with a regex but it's equally trivial enough (as described) not to require one.

std::string s = "your\n\nstring\nhere\n";
size_t n = -1, len = s.length();
    while ((n = s.find('\n', n+1)) != std::string::npos)
        if ((n == 0 && s[n+1] != '\n') || (n == len && s[n-1] != '\n') ||
            (n != 0 && n != len && s[n-1] != '\n' && s[n+1] != '\n'))
            s[n] = ' ';
mattnewport
  • 13,728
  • 2
  • 35
  • 39
Olipro
  • 3,489
  • 19
  • 25