How to find new line char in a string

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?
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

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.
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';
}
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.
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!!!
What if the incoming file was created on UNIX (LF)? What if it was created on Mac (CR)? What if it's mixed?
How was mine roundabout; how would you have done it?
Last edited on
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
Oh. Well, I never used the C++ classes, never feeling I needed them.
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.
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
I haven't ever looked, but it would be nice if the STL used copy on write semantics...
You should check to see if the compiler is using RVO for your example, helios. In general I would not rely on this optimization.
Damn. VC++ doesn't do it.
Topic archived. No new replies allowed.