How to find new line char in a string

Jul 1, 2009 at 1:55pm
hi All,

Through Web service i'm downloading a file as a string. Now the string is having the whole file. I want to extract line by line in that string. Can any one help in how to do this?
Jul 1, 2009 at 2:05pm
string::find( char c, size_type pos = 0 ) returns the index of the first occurrence of c in the string beginning at index pos.

string::substr( size_type pos = 0, size_type n = npos ) returns the substring of n characters beginning from, and including, the character at index 'pos'.

algorithm:

find the first \n
while one found
get the substring from the beginning up to the \n
set the string equal to the substring beginning immediately after the \n through the end of the string
find the first \n

Jul 1, 2009 at 7:41pm
could you print the string to a file and then do std::getline(file, std::string)? if might be slower but will be easier to program.
Jul 2, 2009 at 12:55am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <windows.h>
#include <tchar.h>

VOID SplitString(__in LPCTSTR lpctszString, __in _TCHAR tch, __out LPTSTR lptszBuffer[])
{
	UINT	i = 0;
	UINT	j = 0;
	UINT	k = 0;

	for(; i < _tcsclen(lptszString); i++)
	{
		if(_totupper(lptszString[i]) == _totupper(tch))
			lptszBuffer[j++][k-=k] = '\0';
		else
			lptszBuffer[j][k++] = lptszString[i];
	}
	lptszBuffer[j][k] = '\0';
}
Jul 2, 2009 at 2:54am
Dear God, people. Is this the "Let's do things the most roundabout way possible" week and no one told me?
I don't know who I would fail with the lower grade if I was a teacher and smilodon and Kiana were my students.
Jul 2, 2009 at 4:37am
On Windows platform, a new line is represented by Carriage Return Line Feed (CRLF), a combination of Enter key on keyboard and new line character. In other words "\r\n"... Here goes a simple simple code...

Assuming strInput is the input string, coming in from any source...

1
2
3
4
5
6
7
8
9
10
11
12
13
std::string strCRLF = "\r\n";
std::vector <std::string> vecStrs;
int nStartFrom = 0;

for(int nLocCRLF = std::string::npos; nLocCRLF != std::string::npos; )
{
    nLocCRLF = strInput.find(strCRLF, nStartFrom);
    if(nLocCRLF != std::string::npos)
    {
       vecStrs.push_back(strInput.substr(nStartFrom, (nLocCRLF-nStartFrom)));
    }
}// for nLocCRLF


cheers!!!
Jul 2, 2009 at 4:48am
What if the incoming file was created on UNIX (LF)? What if it was created on Mac (CR)? What if it's mixed?
Jul 4, 2009 at 6:41am
How was mine roundabout; how would you have done it?
Last edited on Jul 4, 2009 at 6:41am
Jul 4, 2009 at 6:55am
How was mine roundabout;
Use of non-standard elements and use of over-complicated algorithms for a relatively simple task. Never forget the KISS principle. The more complex an algorithm, the harder it is to maintain and the more likely it is to contain bugs.

how would you have done it?
Depends on how much emphasis on portability and efficiency is needed.
If none and none then:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <sstream>
#include <vector>

//Assumes only '\n' is used as the newline.
std::vector<std::string> splitIntoLines(const std::string &string){
    std::stringstream stream(string);
    std::vector<std::string> res;
    while (1){
        std::string line;
        std::getline(stream,line);
        if (!stream.good())
            break;
        res.push_back(line);
    }
    return res;
}

smilodon had the right idea, but he twisted it beyond recognition.
Last edited on Jul 4, 2009 at 7:00am
Jul 4, 2009 at 5:18pm
Oh. Well, I never used the C++ classes, never feeling I needed them.
Jul 4, 2009 at 7:44pm
If you want to add some efficiency in there, don't use the copy constructor on the return value (work over a reference instead), and avoid vector in deference of deque:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <sstream>
#include <string>
#include <vector>

void splitIntoLines(
    std::deque <std::string> &result,
    const std::string &s
) {
    std::istringstream ss( s );
    std::string line;
    while (std::getline( ss, line )) {
        result.push_back( line );
    }
}

Hurr, that's all.
Jul 4, 2009 at 7:55pm
However, I've seen returning the copy of a vector take no time. I'll test it now to be sure.

EDIT: Yep.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <vector>
#include <ctime>

unsigned t0,t1;

std::vector<int> f(){
    t0=clock();
    std::vector<int> v(100*1000*1000);
    t1=clock();
    return v;
}

int main(){
    std::vector<int> v=f();
    unsigned elapsed=clock()-t1;
    std::cout <<t1-t0<<std::endl;
    std::cout <<elapsed<<std::endl;
    return 0;
}
Last edited on Jul 4, 2009 at 8:00pm
Jul 5, 2009 at 2:22am
I haven't ever looked, but it would be nice if the STL used copy on write semantics...
Jul 5, 2009 at 2:54pm
You should check to see if the compiler is using RVO for your example, helios. In general I would not rely on this optimization.
Jul 5, 2009 at 3:48pm
Damn. VC++ doesn't do it.
Topic archived. No new replies allowed.