Newbie question

B

BBryant

Probably a fundamental I am missing somewhere, trying to convert from
VB after 5 years is proving more difficult than I expected :)

How can I get the boost:tokenizer output into a char array? With this,
it errors (of course, because the tok_iter isn't a char). I can change
szDataBuf to a string, and C-style type cast *tok_iter to a string to
get it to compile, but the program crashes when attempting to fill the
array.

int ParseData(char * sInput, char seperator) {
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
std::string a(sInput);
char szChr1 = 1;
char szDataBuf[18][256];

boost::char_separator<char> sep(&szChr1);
tokenizer tokens(a, sep);

int iIterator = 0;

for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter !=
tokens.end(); ++tok_iter)
{
szDataBuf[iIterator] = *tok_iter; <---- ERROR LINE
iIterator++;
}

return 0;
}
 
E

evaned

First, why do you want to use a C array? I'm not saying you shouldn't,
just that you should have a reason. The standard library provides a
string class; it's easier to use and safer than C strings.

That said, you'll need to use the function strdup in <cstring> if you
need to deal with C strings.

(Also, prefer static_cast<type>(argument) to old C style casts; they
are easier to search for and more predictable)
 
P

Pete Becker

That said, you'll need to use the function strdup in <cstring> if you
need to deal with C strings.

strdup is not part of Standard C or of Standard C++. It's a common
extension.
 
B

BBryant

Pete said:
strdup is not part of Standard C or of Standard C++. It's a common
extension.

Very good input, thank you. I am a complete newbie here, this is
actually a conversion from a VB application I wrote. Didn't even know a
string class existed. Do you have any links to some good reference
material (websites, books, etc)? My only current reference is SAMS
teach yourself C++ in 21 days.

I got the code to work, thank you for the static_cast and string
suggestion, it did exactly what I needed (Teach yourself everything to
know about C++ in 21 days my foot...)

int ParseData(string sInput) {
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
char szChr1 = 1;
string sDataBuf[22];
boost::char_separator<char> sep(&szChr1);
tokenizer tokens(sInput, sep);

int iIterator = 0;

for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter !=
tokens.end(); ++tok_iter)
{
sDataBuf[iIterator] = static_cast<string>(*tok_iter);
cout << sDataBuf[iIterator] << endl;
iIterator++;
}

return 0;
}
 
P

Pete Becker

BBryant said:
for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter !=
tokens.end(); ++tok_iter)
{
sDataBuf[iIterator] = static_cast<string>(*tok_iter);
cout << sDataBuf[iIterator] << endl;
iIterator++;
}

I'm not familiar with the Boost tokenizer stuff. I have a couple of
minor style comments.

Increment iIterator in the for() statement rather than separately.

for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter !=
tokens.end(); ++tok_iter, ++iIterator)

And lose the name decorations. "iIterator" doesn't say anything that
"Iterator" doesn't, and neither says anything that "iterator" doesn't.
 
B

BBryant

Point taken...another remnant from VB. I didn't know you could have
multiple incrementing variables in for() statements, thank you for the
suggestions.
 
B

BBryant

Now on to the next problem. I receive data only from m_socket[0]. I
have searched around for some help with the WSAEventSelect function but
haven't found much. Any ideas? Thank you for your help thusfar Pete and
Eva.

#include <winsock2.h>
#include <iostream>
#include "parser.h"

using namespace std;


void bListen() {
// Initialize Winsock.
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
if ( iResult != NO_ERROR )
cout <<"Error at WSAStartup()\n";

// Create a socket.
SOCKET m_socket[2];
m_socket[0] = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
m_socket[1] = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );

if ( m_socket[0] == INVALID_SOCKET ) {
cout << "Error at socket(0): " << WSAGetLastError() << "\n";
WSACleanup();
return;
}
if ( m_socket[1] == INVALID_SOCKET ) {
cout << "Error at socket(1): " << WSAGetLastError() << "\n";
WSACleanup();
return;
}

// Bind the socket.
sockaddr_in service[2];

service[0].sin_family = AF_INET;
service[0].sin_addr.s_addr = inet_addr( "192.168.1.100" );
service[0].sin_port = htons( 46999 );
service[1].sin_family = AF_INET;
service[1].sin_addr.s_addr = inet_addr( "192.168.1.100" );
service[1].sin_port = htons( 47000 );

if ( bind( m_socket[0], (SOCKADDR*) &service[0], sizeof(service[0])
) == SOCKET_ERROR ) {
cout << "bind(0) failed.\n";
closesocket(m_socket[0]);
return;
}
if ( bind( m_socket[1], (SOCKADDR*) &service[1], sizeof(service[1])
) == SOCKET_ERROR ) {
cout << "bind(1) failed.\n";
closesocket(m_socket[1]);
return;
}

char wbData[256];
int iBytes, nRet;

WSAEVENT hEvent = WSACreateEvent();
WSANETWORKEVENTS events;
WSAEventSelect(*m_socket, hEvent, FD_READ);
while(1)
{
nRet = WSAWaitForMultipleEvents(2, &hEvent, FALSE,
WSA_INFINITE, FALSE);
if(WSAEnumNetworkEvents(*m_socket,hEvent,&events) ==
SOCKET_ERROR)
{
cout << "Failure at WSAEnumNetworkEvents: " <<
WSAGetLastError() << endl;
}
else
{
if(events.lNetworkEvents & FD_READ)
{
iBytes = recv(*m_socket, wbData, 256, 0);
ParseData(static_cast<string> (wbData));
}
}
}

WSACloseEvent(hEvent);
return;
}
 
E

evaned

Do you have any links to some good reference
material (websites, books, etc)? My only current reference is SAMS
teach yourself C++ in 21 days.

People seem to suggest Accelerated C++ a lot if you've programmed
before. I haven't looked at it myself, but I hear one of the nice bits
about it is that it teaches C++ as C++ instead of a better C right from
the start, so it goes through vector and string and other standard
library things before the C counterparts.

Two other books that come up because of their completeness are The C++
Programming Language by Stroustrup, which is pretty poorly written but
by the guy that actually made C++, and The C++ Primer (I think that's
the title; they just released a new edition so the cover on Amazon
isn't the same) by Lippman, though Amazon seems to have poor reviews on
this so maybe it's not as good as my impression was. One other you
might want to check out is C++, How to Progrm by Deitel; it has good
Amazon reviews.

The SAMS book isn't that good really. I thought it had something about
string at least though... (I don't have it here in my dorm... didn't
think it was worth bring up ;-))


As for the code... I would be wary. There are a couple things that
raise a red flag for me:
- Using a char to hold szChr1; if the char_separactor is expecting a C
string of characters that separate tokens, it will continue reading
past memory where it's allowed. It's looking in memory for something of
the form { <separater character>, <sep. char.>, ..., <sep. char.>, 0 },
but it's getting { 1 (the value of szChr1), <whatever random data
happens to be after szChr in the stack>, <more random variables>, <then
eventually a 0> }. You want somethnig like char szChr1[] = "\x1";
probably, or even better string separators = "\x1" would work.

- The cast. The Boost libraries are generally very well designed, and
integrate well with the C++ standard library. I would be suprised if
you would need a cast. Probably *tok_itr alone is a string, so you
could drop the cast.


BTW, thanks Pete for the clarification on strdup. I should have checked
up on that a little more. I'll revise my statement earlier... if you
had wanted to use C strings, you could do something like this:
int len = strlen(source);
destination = new char[len]; /* or maybe len+1; I don't if you need
to explicitly allocate space for the terminating null and strlen
doesn't include it in its count */
strncpy(source, destination, len);
There might be a better way. I at least would make a function strdup
that does the above, and then use that if there wasn't a native
implementation.
 
B

BBryant

Excellent suggestions. I was using a cast since my prior methods
required one, didn't even think about removing it. I changed the szChr1
variable as suggested as well. Thank you for the ideas on the books, I
will look into buying them.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,055
Members
47,659
Latest member
salragu

Latest Threads

Top