Click to See Complete Forum and Search --> : Read buffer line per line


tux0r
September 30th, 2002, 09:05 AM
Hi,

I'm programming in C Ansi under Unix so a C (and not C++) answer would really be appreciated :)

My program is supposed to get a text file from the net. This part is coded well (I think) and I get the file with 'GET file.txt HTTP/1.1'.

Now I receive the file with a HTTP header like:

HTTP/1.1 200 OK
Date: Mon, 30 sep 2002 13:55:33 GMT
[..]
Content-Type: text/plain

NAME=name1&SURNAME=surname1&ENTER=yes
NAME=name2&SURNAME=surname2&ENTER=yes
NAME=name3&SURNAME=surname3&ENTER=yes
NAME=name4&SURNAME=surname4&ENTER=yes
NAME=name5&SURNAME=surname5&ENTER=yes


I wanted to parse the file to get NAME and SURNAME for each line with a 'while' loop and 'strstr' but it gets the first line and get it over and over..

Please, what's the (best) way to parse a buffer and get all the NAME and SURNAME.

I already have the part to manage the users so just help me with the loop part.

Regards,

Pierrick

Martin Boucher
September 30th, 2002, 04:44 PM
It's not clear but I will suppose that you have the file in a char* buffer since your using strstr in your message. You're stick with the first line (I also suppose that you have skipped the header) because strstr works on a char* buffer (not on a stream). So if you call :

strstr( buffer, ... );
strstr( buffer, ... );
strstr( buffer, ... );
etc.

buffer points at the same memory location. You have to advance it yourself. But I rather use "sscanf" if I was you. I would do something like :


while( sscanf( buffer, "NAME=%s&SURNAME=%s&%s\n", nameBuffer, surnameBuffer, skipBuffer ) == 3 )
{
...
}

The location of the buffer pointer is managed by sscanf. Also, be sure your temp. buffers have enough space. If the point of reading the file is just to extract what you do in the while-loop, use fscanf to read your file it will be fastest than reading the file then scaning the names. You'll read and scan in one step.

Hope this help,
Martin

kuphryn
September 30th, 2002, 08:36 PM
I am not sure if you can ignore certain data when you download data from a website via HTTP. If you want to filter data, you could use the /GET command and then save relevant data only.

Kuphryn

tux0r
October 1st, 2002, 02:08 AM
Thanx martin!

The trouble is I still have the header in the buffer (since I assume the size is variable).

And the sscanf is not working apparently.

I try to do only one sscanf (so without the while loop).

Like the following:

char incodata[] = "NAME1=name1&SURNAME1=surname1&ENTER=1";
int i = 0;
i = sscanf (incodata, "NAME1=%s", info_name):
printf ("\n%s\n", info_name);

and it prints 0 !

I don't know this function, so I read some stuff on the net and I cant figure out if I have to put the whole string like NAME1=%s&SURNAME1=%s&ENTER=%s"

Anyway it's not working.

Regards,

Pierrick

tux0r
October 1st, 2002, 05:56 AM
OK I tried to make it work the whole morning (switzerland time) and all I had is "segmentation fault" or infinite loop!

I have a buffer which contains datas
I didnt cut anything.. I have this buffer exactly as it is shown above.

incodata is the buffer declared as char * with an malloc.

What I am trying to do is to find every occurance of a word in this buffer.

Something like


while (get_the_next_line(incodata))
if(strstr(incodata, "NAME1"))
printf ("found\n"):


So i tried the following:


while(strstr(incdoata,"NAME1"))
printf("found\n"):


but it's looping for ever!

Thanx for helping !

Pierrick

PaulWendt
October 1st, 2002, 06:22 AM
READ what the other people have told you; to quote Martin:

buffer points at the same memory location. You have to advance it yourself. But I rather use "sscanf" if I was you. I would do something like


Why didn't you do as he suggested and use sscanf()?

--Paul

tux0r
October 1st, 2002, 06:48 AM
I tried with sscanf with no success.

It always return 0!

OK now I have the following:

while( sscanf( incodata, "NAME=%s&SURNAME=%s&%s\n", info_login, info_passw, info_skipp ) == 3 )
{
printf ("found\n"):
}

it doesnt print 'found' !
so it does not find what I'm looking for...

Let me remember you that I have the HTTP header.. Do I have to take care about it ?

thanx

tux0r
October 1st, 2002, 08:36 AM
OK Full example of what I did.
(Still not working).


char incodata[] = "NAME1=name1&SURNAME1=surname1&ENTER=Enter\nNAME1=name2&SURNAME1=surname2&ENTER=Enter";
char *info_name = (char *) malloc (BUF_SZ);
char *info_surname = (char *) malloc (BUF_SZ);
char *info_skip = (char *) malloc (BUF_SZ);

while( sscanf( incodata, "NAME1=%s&SURNAME1=%s&%s", info_name, info_surname, info_skip ) == 3)
{
printf ("found\n");
}


Is it enough to help ?

Best Regards !

PaulWendt
October 1st, 2002, 09:18 AM
I looked at it and yeah you're right. The input buffer is not
delimited by whitespace ... and that's how sscanf() delimits
strings. You'll probably need to use strtok() and strstr() to find
what you need. strtok() will go through the buffer for you. Don't
nest strtok() calls because strtok() uses internal data to keep
track of where it's at.

tux0r
October 1st, 2002, 09:29 AM
- Don't nest strtok() calls because strtok() uses internal data to keep
track of where it's at.

donc nest ?

PaulWendt
October 1st, 2002, 10:11 AM
DON'T do the following:

char buffer[] ="blah\tblah\nblah\tblah\nblah\tblah\n";
char* pToken = 0;
char* pInnerToken = 0;

// get by line
pToken = strtok(buffer, "\n");
while (pToken != 0)
{
// get by tab
pInnerToken = strtok(pToken, "\t");
while (pInnerToken != 0)
{
// this probably screwed something up.
// don't nest strtok()'s
pInnerToken = strtok(0, "\t");
}

pToken = strtok(0, "\n");
}



You'd have to use a different method to parse the inner string.

--Paul

tux0r
October 1st, 2002, 01:06 PM
Thanx to all of you for the help !!

I finally did it the following way:


char my_str[] = "http header + carriage return + NAME1 and SURNAME1 bla bla .....";
char *p;
char *info_name = (char *) malloc (1024);
char *info_surname = (char *) malloc (1024);

p = strstr(my_str, "NAME1");
p = strtok(p, "& \n");

while ( p != NULL)
{
if (strstr(p, "NAME1"))
{
strcpy( info_name, p + strlen("NAME1") + 1);
printf ("Name: %s\n", info_name);
}
else if (strstr(p, "SURNAME1"))
{
strcpy( info_surname, p + strlen("SURNAME1") + 1);
printf ("Surname: %s\n\n", info_surname);
}

p = strtok (NULL, "& \n");
}


I know it's really awful (like the strlen("NAME1")) but it was just a quick test :)

I will modify it to use #define and stuff.

I don't know if it's the best solution to do it but it's working and since I didn't find any examples on the net I had to do it myself :)


Cya

PaulWendt
October 1st, 2002, 01:55 PM
Hello,

I know you said that this is just an example and you'll probably
fix this anyway ... but I have to point out that the use of malloc()
requires the use of a free() unless you want to have a memory
leak.


char* pBuffer = malloc(1024);
free(pBuffer);


With the example you're using, you might as well use local char
arrays; you'll have the same fixed-size limitation, but you won't
have to worry about the dynamic memory allocation routines
like malloc() or free(). Here's your routine modified so that the
dynamic memory allocation business has been removed:


char my_str[] = "http header + carriage return + NAME1 and SURNAME1 bla bla .....";
char *p;
char info_name[1024];
char info_surname[1024];

p = strstr(my_str, "NAME1");
p = strtok(p, "& \n");

while ( p != NULL)
{
if (strstr(p, "NAME1"))
{
strcpy( info_name, p + strlen("NAME1") + 1);
printf ("Name: %s\n", info_name);
}
else if (strstr(p, "SURNAME1"))
{
strcpy( info_surname, p + strlen("SURNAME1") + 1);
printf ("Surname: %s\n\n", info_surname);
}

p = strtok (NULL, "& \n");
}


If you don't make the change I recommend, you'll have to use a
free() at the end of your code.

--Paul

tux0r
October 1st, 2002, 03:34 PM
What's better or more "pro", malloc/free or without memory business ?

Thanx for your support.. I appreciate your advices !

PaulWendt
October 1st, 2002, 04:10 PM
The best rule of thumb to go by while programming is "Keep it as
simple as possible". malloc() is useful when you don't know the
size of the buffer in advance. Let's say you are creating a string
and you're creating it from user-input. What if you use a 64 byte
buffer and the user inputs 100 bytes? So you'd develop a routine
that counts the number of bytes input by the user and then use
malloc() to create a dynamic buffer, which would hold this
information. In your example, you are not using any complex
algorithm requiring a dynamically-growing character array. There-
fore, I'd suggest you use the character array in this case.

That's not to say that malloc() doesn't have its uses; it is slightly
more difficult to use, however, so use it more judiciously.

--Paul

tux0r
October 1st, 2002, 04:11 PM
OK Perfect.

So I'll just do as you told me!

Thanx