strcmp but with '\n' as the terrminator

A

Allan Bruce

Hi there,
I am reading a file into a char array, and I want to find if a string exists
in a given line.
I cant use strcmp since the line ends with '\n' and not '\0'. Is there a
similar function that will do this, or will I have to write my own?
Thanks
Allan
 
R

Richard Heathfield

Allan said:
Hi there,
I am reading a file into a char array, and I want to find if a string
exists in a given line.
I cant use strcmp since the line ends with '\n' and not '\0'. Is there a
similar function that will do this, or will I have to write my own?

Assuming that for some strange reason you haven't yet switched over to my
"stretchy string" routines (which abuse the word "string", since they work
on non-null-terminated data), the easiest way to do what you want, if the
"string" is writeable, is to find the \n, change it to \0, do the strstr,
and then change it back again. If you're doing this a lot, though, you
should beware, as it's not a very efficient solution; in which case, you'd
want to write your own, I guess (unless someone has a better idea).
 
C

code_wrong

Allan Bruce said:
Hi there,
I am reading a file into a char array, and I want to find if a string exists
in a given line.
I cant use strcmp since the line ends with '\n' and not '\0'. Is there a
similar function that will do this, or will I have to write my own?

If you are looking for a substring in a string you can use
strstr()

Syntax:

#include <string.h>
char *strstr(const char *s1, const char *s2);

Description:

Scans a string for the occurrence of a given substring.

strstr scans s1 for the first occurrence of the substring s2.

Return Value

strstr returns a pointer to the element in s1, where s2 begins (points to s2
in s1). If s2 does not occur in s1, strstr returns null.

HTH
cw
 
?

=?ISO-8859-1?Q?Bj=F8rn_Augestad?=

Richard said:
Allan Bruce wrote:




Assuming that for some strange reason you haven't yet switched over to my
"stretchy string" routines (which abuse the word "string", since they work
on non-null-terminated data), the easiest way to do what you want, if the
"string" is writeable, is to find the \n, change it to \0, do the strstr,
and then change it back again. If you're doing this a lot, though, you
should beware, as it's not a very efficient solution; in which case, you'd
want to write your own, I guess (unless someone has a better idea).

Maybe he can ignore the \n and just use strstr() instead? He won't get
exact matches for the whole line, but he will "find if a string exists
in a given line". ;-)
 
E

Emmanuel Delahaye

Allan Bruce said:
I am reading a file into a char array, and I want to find if a string
exists in a given line.
I cant use strcmp since the line ends with '\n' and not '\0'. Is there
a similar function that will do this, or will I have to write my own?

The usual trick is to remove the '\n' from the read line:

#include <string.h>

<...>

{
char *p = strchr (line, '\n'); /* search ... */

if (p)
{
*p = 0; /* ... and kill. */
}
}
 
C

code_wrong

Allan Bruce said:
there to

I have used strstr mainly, not strcmp as my post indicates! (doh)
But the problem is still that strstr requires a null terminator and not
'\n'.
Any ideas?

Which function are you using to read your file?
If you read your file with fgets() then you will get null terminated strings
to play with.
Of course there is still the newline character to take into account, but
that will not matter if you use strstr() to check for substrings.

cw
 
R

Richard Heathfield

Bj[o]rn Augestad said:
Richard Heathfield wrote: said:
Allan Bruce wrote:
Maybe he can ignore the \n and just use strstr() instead? He won't get
exact matches for the whole line, but he will "find if a string exists
in a given line". ;-)

Well, he did say quite clearly that there was no '\0' at the end of the
data. Or did I misunderstand him?
 
R

Richard Heathfield

Emmanuel said:
The usual trick is to remove the '\n' from the read line:

#include <string.h>

<...>

{
char *p = strchr (line, '\n'); /* search ... */

Undefined behaviour if line has no terminating null character, as the OP has
pointed out twice now.

<snip>
 
?

=?ISO-8859-1?Q?Bj=F8rn_Augestad?=

Richard said:
Bj[o]rn Augestad wrote:

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Maybe he can ignore the \n and just use strstr() instead? He won't get
exact matches for the whole line, but he will "find if a string exists
in a given line". ;-)


Well, he did say quite clearly that there was no '\0' at the end of the
data. Or did I misunderstand him?

I don't know. :)

I was just assuming(I know, I know...) that the OP was reading a file
line by line using fgets() and then tried to match some string with the
line read, but ran into problems because of the trailing \n.

Only time and some source code will tell. ;-)
 
A

Allan Bruce

Bjørn Augestad said:
Richard said:
Bj[o]rn Augestad wrote:

Richard Heathfield wrote: <all snipped>

Allan Bruce wrote:



Hi there,
I am reading a file into a char array, and I want to find if a string
exists in a given line.
I cant use strcmp since the line ends with '\n' and not '\0'.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Is there a
similar function that will do this, or will I have to write my own?
Maybe he can ignore the \n and just use strstr() instead? He won't get
exact matches for the whole line, but he will "find if a string exists
in a given line". ;-)


Well, he did say quite clearly that there was no '\0' at the end of the
data. Or did I misunderstand him?

I don't know. :)

I was just assuming(I know, I know...) that the OP was reading a file
line by line using fgets() and then tried to match some string with the
line read, but ran into problems because of the trailing \n.

Only time and some source code will tell. ;-)

I am using this to read the file:
// find how big the file is
fseek(fptr, 0, SEEK_END);
size = ftell(fptr);

//allocate memory for string
if ( (contents = new char[size]) == NULL)
return 0;

Basically reading it in one big chunk, since I am doing some things to the
code that take a long time so I wanted to keep the file open for as little
time as possible.
I use strstr() to find some matches and also use strcmp() to see if some are
true for example, a line may be:
# Material: Porsche_Body
Now this will be stored with a '\n' at the end but no '\0'.
In this example I wish to search for "Material:" using strstr() but if it
doesnt exist then strstr() is causing undefined behaviour. If strstr() is
successful, then I want to see if the material name matches what I already
have loaded using strcmp() but since the '\0' isnt there - problems. I
count how many chars until the '\n' and then use strncmp I suppose, but that
doesnt get around the strstr() and I want to know for future how to use
strcmp with '\n' terminator.
From the gist of it, I should program my own function, or better still
macro.
Am I correct?
Thanks
Allan
 
R

Richard Heathfield

Allan Bruce wrote:

Now this will be stored with a '\n' at the end but no '\0'.
In this example I wish to search for "Material:" using strstr() but if it
doesnt exist then strstr() is causing undefined behaviour. If strstr() is
successful, then I want to see if the material name matches what I already
have loaded using strcmp() but since the '\0' isnt there - problems. I
count how many chars until the '\n' and then use strncmp I suppose, but
that doesnt get around the strstr() and I want to know for future how to
use strcmp with '\n' terminator.
From the gist of it, I should program my own function, or better still
macro.
Am I correct?

The simplest solution is to ensure that the string is null-terminated, by
allocating one byte more than you need for the data, and writing a '\0'
character into that byte.
 
S

Serve Laurijssen

Allan Bruce said:
Hi there,
I am reading a file into a char array, and I want to find if a string exists
in a given line.
I cant use strcmp since the line ends with '\n' and not '\0'. Is there a
similar function that will do this, or will I have to write my own?
Thanks
Allan

You can use use strncmp for that, but only if you know how big the total
buffer is so you know where to stop.
 
S

Serve Laurijssen

Serve Laurijssen said:
You can use use strncmp for that, but only if you know how big the total
buffer is so you know where to stop.

ah what the hell, here's some sample code.
Had a little bit too much whiskey, so trying to find all bugs is left as an
exercise for you :)

#include <stdlib.h>
#include <stdio.h>
int main(void)

{

int i;

char buf[10] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' };

char *findstr = "ijk";

for (i = 0; i <= (sizeof buf / sizeof *buf)-strlen(findstr); i++)

{

if (strncmp(buf+i, findstr, 2) == 0)

printf("%.3s\n", buf+i);

}

puts("done");

return 0;

}
 
A

Allan Bruce

Serve Laurijssen said:
there
a

You can use use strncmp for that, but only if you know how big the total
buffer is so you know where to stop.

ah what the hell, here's some sample code.
Had a little bit too much whiskey, so trying to find all bugs is left as an
exercise for you :)

#include <stdlib.h>
#include <stdio.h>
int main(void)

{

int i;

char buf[10] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' };

char *findstr = "ijk";

for (i = 0; i <= (sizeof buf / sizeof *buf)-strlen(findstr); i++)

{

if (strncmp(buf+i, findstr, 2) == 0)

printf("%.3s\n", buf+i);

}

puts("done");

return 0;

}

Thanks, will have a look.
I have to say one thing though, I hope you are drinking Scotch since it is
the best, but I may be biassed, but if you are its spelt whisky. Only the
Irish could spell it differently! (Sorry to my Irish mates...)
Allan
 
E

Emmanuel Delahaye

Allan Bruce said:
I have to say one thing though, I hope you are drinking Scotch since it is
the best, but I may be biassed, but if you are its spelt whisky. Only the

best what? Do you mean pure malt? Forget those blended piece of shit.
Irish could spell it differently! (Sorry to my Irish mates...)

What the hell? Do you meant whiskey? The Whiskey!
 
A

Allan Bruce

Emmanuel Delahaye said:
Allan Bruce said:
I have to say one thing though, I hope you are drinking Scotch since it is
the best, but I may be biassed, but if you are its spelt whisky. Only
the

best what? Do you mean pure malt? Forget those blended piece of shit.
Irish could spell it differently! (Sorry to my Irish mates...)

What the hell? Do you meant whiskey? The Whiskey!

--
-ed- (e-mail address removed) [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

I do mean single malt, I am an Islay man, so I prefer Ardbeg, Laphroaig and
Lagavulin, and they are all spelt whisky! not whiskey! I am Scottish and
take pride in my whisky, not the Irish variety which generally tastes like
cats pee, sorry Bushmills but it does.
Allan
 
C

Chris Torek

I [have an entire, probably large] file [in] a char array, and I want
to find if a string exists in a given line.

Elsethread, you note you mean "strstr", not "strcmp".

I suspect (per insertion above and given some guesses as to what
you are doing) that you want to check a relatively large number
of lines as well, not just one specific line.

If the file is large and the number of lines is large, you may find
it worthwhile to implement a Boyer-Moore search. By writing your
own, you can choose any sort of termination conditions you like,
including stopping at newlines.

Boyer-Moore is, in the ideal case, O(N/M) where N is the length of
the search space -- in this case, some presuambly large number of
lines -- and M is the length of the string to be found. It has
some overhead setup that makes it a bad idea unless N is noticeably
larger than M. Since strstr() does not get much information, and
C strings are generally short, strstr() is unlikely to use Boyer-Moore
-- but you know more about what you are searching, so you can.
 
M

Michael B Allen

I am using this to read the file:
// find how big the file is
fseek(fptr, 0, SEEK_END);
size = ftell(fptr);

//allocate memory for string
if ( (contents = new char[size]) == NULL)
return 0;

Basically reading it in one big chunk, since I am doing some things to
the code that take a long time so I wanted to keep the file open for as
little time as possible.
I use strstr() to find some matches and also use strcmp() to see if some
are true for example, a line may be:

# Material: Porsche_Body

Now this will be stored with a '\n' at the end but no '\0'. In this
example I wish to search for "Material:" using strstr() but if it doesnt

I find the best way to parse stuff like this is to use a little "State
Machine" which in this context is just a loop with a switch like:

int ch, state = 0;

while ((ch = fgetc(in)) != EOF) {
switch (state) {
case 0:
if (ch == '#') {
state = 1;
}
break;
case 1:
if (isspace(ch)) {
break;
}
state = 2;
case 2:
if (ch == ':') {
ident[i++] = '\0'; /* Material */
state = 3;
break;
}
ident[i++] = ch;
break;
case 3:
if (isspace(ch)) {
break;
}
state = 4;
case VALUE:
if (ch == '\r' || ch == '\n') {
value[v++] = '\0'; /* Porsche_Body */
state = 0;
break;
}
value[v++] = ch;
}
}

The advantage in doing this is that it tends to scale a lot better. As
your file format changes or if you encounter content that you previously
thought you would never need to parse you can refactor easily without
the code growing exponentially more complex. For example if you suddenly
started getting files that had identifiers (e.g. Material) without values
you could add a test for '\r' and '\n' in case 3 to make value[0] =
'\0' and reset the state to 0.

This is all very crudely described of course. You would need to adjust
the technique to your needs.

Mike
 
J

Joona I Palaste

I do mean single malt, I am an Islay man, so I prefer Ardbeg, Laphroaig and
Lagavulin, and they are all spelt whisky! not whiskey! I am Scottish and
take pride in my whisky, not the Irish variety which generally tastes like
cats pee, sorry Bushmills but it does.

The malt is spoiled by the too high alcohol content. It ends up tasting
like alcohol. If you like malt, drink beer.

--
/-- Joona Palaste ([email protected]) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"Immanuel Kant but Genghis Khan."
- The Official Graffitist's Handbook
 
R

Richard Heathfield

Emmanuel Delahaye wrote:

Forget those blended piece of shit.

Was this entirely necessary? This /is/ a technical newsgroup, after all.

I'd hate to have to plonk you.
 

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

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top