Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

extract part of a LPSTR

8 views
Skip to first unread message

Maileen

unread,
May 29, 2004, 1:33:57 PM5/29/04
to
Hi,

I have a text file included as resource to my EXE.
i declared a LPSTR variable which consists of the full contents of my
text file (included asresource)

this LPSTR consists of several lines of my initial text file.
i know that each line is a semi-colon formated line ending by a CRLF (0D
0A in hexa).

how can i extract each line of my resource in order to place them into
an string array ?
thx,
Maileen

William DePalo [MVP VC++]

unread,
May 29, 2004, 2:26:44 PM5/29/04
to
"Maileen" <nos...@email.com> wrote in message
news:uPVudMaR...@TK2MSFTNGP09.phx.gbl...

> this LPSTR consists of several lines of my initial text file.
> i know that each line is a semi-colon formated line ending by a CRLF (0D
> 0A in hexa).
>
> how can i extract each line of my resource in order to place them into
> an string array ?

The old, tried and true <g> way would have you use strtok().

Regards,
Will

Jag Man

unread,
May 29, 2004, 5:11:11 PM5/29/04
to
I just happened to have written this. It uses the standard library string,
and the STL vector,
set up for wide characters. Should also work for ordinary characters if you
use string instead of tstring
and char instead of wchar_t.
To use Split() on your string s:


std::vector<tstring> v;
v = Split(s, L' \n'); // L'\n' is the newline character
// the vector can be indexed like an array.
for (k = 0; k < v.size(); k++)
err_file << v[k] << " ";
err_file << std::endl;

Good luck,
Ed

//
// Splits a tstring into a vector of tstrings
//
//
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <comutil.h>
#include <string>
#include <vector>
#include <tchar.h>

#ifndef tstring
typedef std::basic_string<TCHAR> tstring;
#endif


const std::vector<tstring> Split(const tstring& s, wchar_t sep )
{
std::vector<tstring> v;

std::ofstream err_file;
err_file.open("error.log", std::ios::out|std::ios::app);
if(!err_file){
exit (1);
}

int state=0; // 0 means looking for non whitespace
// 1 means looking for whitespace
int count=0, i=0;
tstring tok;

while( s[i] != L'\0'){
if(state == 0){ // looking for a word to begin
if(s[i] != sep ){
tok += s[i];
state =1;
}
else{
}
}
else {// looking for word to end
if(s[i] == sep ){
count++;
state = 0;
v.push_back(tok); // save completed token in the vector
tok.erase();
}
else{
tok += s[i];
}

}
i++;
}

if(state == 1){
state = 0;
v.push_back(tok); // save last completed token in the vector
tok.erase();
count++; // count the last word if it was delimited with the
NULL
}

// err_file << "count = " << count << std::endl;

err_file.close();

return v;

Jerry Coffin

unread,
May 30, 2004, 12:12:06 AM5/30/04
to
In article <uPVudMaR...@TK2MSFTNGP09.phx.gbl>, nos...@email.com
says...

One way would be to use an istringstream to do most of the work:

std::istringstream<std::string> input(your_lpstr);
std::string buffer;
std::vector<std::string> lines;

while (std::getline(input, buffer))
std::push_back(lines, buffer);

I tend to like another a bit better, even though it takes a bit more
code. We start by defining a string proxy that knows that it's a
line -- I.e. that when being read from a file, a whole line should be
read, not just a space delimited word:

class line {
std::string data;
public:
friend std::istream &operator>>(std::istream &is, line &l) {
std::getline(is, l.data);
return is;
}
operator std::string() { return data; }
};

having done that, we can basically just use std::copy to copy lines
to a vector:

std::vector<line> lines;
std::istringstream input(your_lpstr);

std::copy(
std::istream_iterator<line>(input),
std::istream_iterator<line>(),
std::back_inserter(lines));

Depending on what sorts of things you're doing, there's yet another
possibility: create a locale that only treats \r and \n as white
space:

class line_reader : std::ctype<char> {
line_reader() : std::ctype<char>(get_table()) {}
static std::ctype_base::mask const *get_table() {
static std::ctype_base::mask *rc;

if ( rc == 0) {
rc = new std::ctype_base::mask
[std::ctype<char>::table_size];
std::fill_n(rc, std::ctype,char>::table_size,
std::ctype_base::mask());
rc['\r'] = rc['\n'] = std::ctype_base::space;
]
return rc;
}
};

Using this is somewhat similar:

std::istringstream input(your_lpstr);
input.imbue(std::locale(std::locale(), new line_reader));

std::vector<std::string> lines;

std::copy(std::istream_iterator<std::string>(input),
std::istream_iterator<std::string>(),
std::back_inserter(lines));

Which of these is best will depend on the situation. If you're doing
this in one place, and that's it, then it's probably easiest to use
the first.

If you're reading line-at-a-time in quite a few places, the second is
probably easier to use, but it treats the line-at-a-time behavior as
part of the type of thing you're reading. The third uses locales,
which few people ever even look at, not to mention understanding, but
in some ways it's probably the cleanest of the solutions -- it plugs
into the standard library and extends it in exactly one of the
intended ways.

There are a number of other possibilities -- Boost has a tokenizer
class, and the standard library has strtok. I hesitate at even
mentioning strtok though -- IMO, it's only one (rather small) step
above gets, in being a function you should virtually never use.

Nearly the only use of strtok I condone is one that's completely
different from its intent or normal use -- if (for example) you're
reading lines of text in C (using fgets), it works well for stripping
off the trailing newline you normally get:

fgets(input_file, buffer, sizeof(buffer));
strtok(buffer, "\n");

Whether this is good or bad is open to question: it's about the
cleanest way I know of to do this job and it's nearly the only really
safe use for strtok, but people find it puzzling, since it's totally
different from the usual purpose to which strtok is put.

--
Later,
Jerry.

The universe is a figment of its own imagination.

0 new messages