fgets

M

Magix

Hi,

I'm not too sure on reading specify string with the first < > from file
stream,and make the file pointer go to next line, with fgets. or any better
idea.

E.g
let say text.txt has
<11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
<22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
<333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>

while(fgets(num, 7, fp)!=NULL)
{
// filter the < and >
printf( "%s",num );
// go to new line
}

it will print num:
11111
22222
33333

Advise...pls. Thanks

Regards.
 
M

Magix

Magix said:
Hi,

I'm not too sure on reading specify string with the first < > from file
stream,and make the file pointer go to next line, with fgets. or any better
idea.

E.g
let say text.txt has
<11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
<22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
<333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>

while(fgets(num, 7, fp)!=NULL)
{
// filter the < and >
printf( "%s",num );
// go to new line
}

it will print num:
11111
22222
33333

Advise...pls. Thanks

Regards.

Sorry, it will print num:
11111
22222222
333
 
M

Mike Wahler

Why 7?
Sorry, it will print num:
11111
22222222
333


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LINE_SIZE 100 /* adjust to your needs */
#define LDELIM '<'
#define RDELIM '>'

int main()
{
FILE *fp = fopen("test.txt", "r");
static char line[LINE_SIZE];

if(!fp)
{
fprintf(stderr, "Cannot open input\n");
return EXIT_FAILURE;
}

while(fgets(line, sizeof line, fp))
{
char *left = 0;
char *right = 0;

if(left = strchr(line, LDELIM))
right = strchr(++left, RDELIM);

if(left && right)
{
*right = 0;
printf("%s\n", left);
}
}

if(!feof(fp))
{
fprintf(stderr, "Error reading input\n";
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}

Input:

<11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
<22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
<333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>


Output:

11111
22222222
333

The above will only work correctly if all lines are less than
;LINE_SIZE; characters. If they're larger and you don't increase
'LINE_SIZE' to accomodate, you'll need to handle cases where
a single 'fgets()' call doesn't extract a newline character.

-Mike
 
M

Michael Mair

Hi Magix,
It will print num:
11111
22222222
333

You can also use fscanf():

#include <stdio.h>
#include <stdlib.h>

#define STRINGIZE(s) # s
#define MAKESTRING(s) STRINGIZE(s)

#define FIELDWIDTH 7

int main (void)
{
FILE *fp;
char str[FIELDWIDTH+1];

if ( (fp=fopen("magix.inp","r")) == NULL )
exit(EXIT_FAILURE);

while (1) {
int howmany = fscanf(fp, "<%"MAKESTRING(FIELDWIDTH)
"[^>]%*[^<]<%*[^>]><%*[^>]>",
str);
if (howmany!=1)
break;
puts(str);
}
fclose(fp);

exit(EXIT_SUCCESS);
}

The format string does the following:
It gobbles a '<', then scans for up to FIELDWIDTH non-'>'
characters into str. As we do not know whether this covers
the first "<tag>", we now scan for the beginning of
the second, then gobble the second and third tags, respectively.
The leading ' ' is for gobbling any left over white spaces
from previous line.

Note, however, that this does not give you the certainty that
your line was of the required format. You could scan for the
final '>' or try to fgetc() the following '\n' to be on the
safe side.

It might be a good idea to #define left/right delimiter
characters instead of '<','>'. You can insert them quite
in the same way as the FIELDWIDTH.


Cheers,
Michael
 
W

William L. Bahn

"Michael Mair" <[email protected]>
wrote in message
Hi Magix,
or any

better


It will print num:
11111
22222222
333

You can also use fscanf():

while (1) {
int howmany = fscanf(fp, "<%"MAKESTRING(FIELDWIDTH)
"[^>]%*[^<]<%*[^>]><%*[^>]>",
str);

The format string does the following:
It gobbles a '<', then scans for up to FIELDWIDTH non-'>'
characters into str. As we do not know whether this covers
the first "<tag>", we now scan for the beginning of
the second, then gobble the second and third tags, respectively.
The leading ' ' is for gobbling any left over white spaces
from previous line.

Note, however, that this does not give you the certainty that
your line was of the required format. You could scan for the
final '>' or try to fgetc() the following '\n' to be on the
safe side.

It might be a good idea to #define left/right delimiter
characters instead of '<','>'. You can insert them quite
in the same way as the FIELDWIDTH.

Why so complicated?

What happens if there is a space in the input string?
What happens if there aren't exactly three pairs of tags on a
line (which I don't see any requirement for - the example just
happens to have three on each line)?

For what the OP is asking for, if I understand it correctly, you
don't need to perform string operations at all.

This is the way I read what is being asked for (which,
admittedly, involved reading between the lines):

1) Lines consist of strings of characters delimited by '<'
(LDELIM) and '>' (RDELIM) characters.
2) There may be one or more such strings on a given line.
3) Output should consist only of the first such string on each
line.

IF we are willing to assume (for the first pass at the algorithm)
that the strings really do obey Rule #1, then we have the
following:

1) WHILE: End of File not reached
1.1) WHILE: (Next character is NOT LDELIM)
1.1.1) Do nothing - go on to next character.
1.2) WHILE: (Next character is NOT RDELIM)
1.2.1) Print the character.
1.3) Print a newline character.
1.4) WHILE: (Next character is NOT the end of the line)
1.4.1) Do nothing - go on to the next character.

Each of the tests should include checks for EOF and (if desired)
newline characters in unexpected places.

At the risk of doing someone's homework (hopefully they'll at
least learn something from seeing the problem stated clearly, an
algorithm developed based on the problem statement, and code
developed based on the algorithm).

#include <stdio.h> /* FILE, NULL, fopen(), putchar(), printf()
*/

#define EXIT_OK (0)
#define EXIT_FAIL_NoOpen (1)

#define FILENAME "data.txt"

#define LDELIM ('<')
#define RDELIM ('>')

int main(void)
{
int c;
FILE *fp;

fp = fopen(FILENAME, "rt");
if(NULL == fp)
{
printf("Error opening %s for reading - aborting.\n",
FILENAME);
return EXIT_FAIL_NoOpen;
}

do /* Until end of file is reached */
{
/* Strip up to and including first occurrence of LDELIM
*/
while( (EOF != (c = getc(fp))) && ('\n' != c) &&
(LDELIM != c) )
/* EMPTY LOOP */;

/* Print out characters up to first occurrence of
RDELIM */
while( (EOF != (c = getc(fp))) && ('\n' != c) &&
(RDELIM != c) )
putchar(c);
putchar('\n');

/* Strip remaining characters on line */
while( (EOF != (c = getc(fp))) && ('\n' != c) )
/* EMPTY LOOP */;

} while (EOF != c);

fclose(fp);

return EXIT_OK;
}


As usual, I welcome comments and criticisms.

NOTE TO THE OP: By using the subject line you did, you imply that
your question is specifically dealing with a specific function -
namely fgets() - and people might assume that, for whatever
reason, you either have to use that function or are trying to
learn more about that function by doing so. Your post content
implies that this is not the case. A better subject line might
have been something like: "Trying to output initial part of each
line".
 
N

Nick Keighley

I'm afraid I don't understand you. Do you mean "I want to read the
text
Sorry, it will print num:
11111
22222222
333

no it won't. Do you mean that's what you want it to do? If so you
could get a character at a time.
 
M

Michael Mair

Hello William,

Why so complicated?

What happens if there is a space in the input string?
(Then scan for white spaces which are not return between > and
<... but that is beside the point, see below)
What happens if there aren't exactly three pairs of tags on a
line (which I don't see any requirement for - the example just
happens to have three on each line)?

For what the OP is asking for, if I understand it correctly, you
don't need to perform string operations at all.

That may be the problem -- I did not entirely understand his
intention, so I made up one that seemed to fit... :-/
It seemed to me that he defined an input format which I
put into a format string as I do not think that fgets()
is the best thing to use. OTOH, he seemed to want to do
it "in one go", so I tried to give him that.

This is the way I read what is being asked for (which,
admittedly, involved reading between the lines):

1) Lines consist of strings of characters delimited by '<'
(LDELIM) and '>' (RDELIM) characters.
2) There may be one or more such strings on a given line.
3) Output should consist only of the first such string on each
line.

Er, right. Then the way is clear. My assumptions from his
input file were that
1,2) Lines consist of exactly three strings delimited by < and >
with no spaces between > and <, and a '\n' in the end.
3) Output should consist only of the first FIELDWIDTH (7 for the
OP) characters of the first string (or less, if the string has
strlen(string)<FIELDWIDTH) on each line.


Cheers
Michael
 
C

CBFalconer

Nick said:
I'm afraid I don't understand you. Do you mean "I want to read

If we say 'the initial text so delimited' then things should be
very simple:

Input the whole string, search for the first '<' and save the
pointer. Then search for the next '>' and zero that. Print the
string denoted by the saved pointer. Roughly:

if (firstp = strchr(buffer, '<')) firstp++;
if (firstp && (endp = strchr(firstp, '>')))
*endp = '\0';
puts(firstp);
else {
/* something isn't there */
}
 
M

Malcolm

Magix said:
I'm not too sure on reading specify string with the first < > from file
stream,and make the file pointer go to next line, with fgets. or any better
idea.

E.g
let say text.txt has
<11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
<22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
<333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>

while(fgets(num, 7, fp)!=NULL)
{
// filter the < and >
printf( "%s",num );
// go to new line
}
fgets() is useful if you can specify a maximum line length, and reject every
input over that limit (say 1024 characters). If you need to be able to
handle lines of any length, or if the input doesn't naturally fall into
lines, then it is not really useful and you need to write your own function
to read data into dynamically allocated memory.

You can parse simple input, like a block of text containing a few tag
delimited by <> just using a commonsense approach.

Once things get more complicated, for instance you allow nested tags, escape
sequences, and different types of tag, then you need to move to a recursive
parser. It is not easy to explain how to write one in a short post, but
basically you need a parsetag() function which calls itself when it hits a
nested tag. It also needs a match() function to flag an error if the closing
'>' is not detected at the appropriate place.
 

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
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top