By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
428,586 Members | 623 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 428,586 IT Pros & Developers. It's quick & easy.

Anyway to read file line by line ?

P: n/a
My .dat file will contain information like below.

///////////
First
0x04
0x05
0x06

Second
0x07
0x08
0x09

Third
0x0E
0x0F
0x0D
///////////

In my main program, it will open this dat file, read line by line.
When it hits the string I'm searching for (e.g. "First"), the program
will know that the next line will be the variables to be stored. Are
there any C function to read file line by line? Please give me some
clue. Thanks a lot.

Abby.
Nov 13 '05 #1
Share this Question
Share on Google+
40 Replies


P: n/a
On 1 Aug 2003 15:43:46 -0700, ab*****@yahoo.com (Abby) wrote:
My .dat file will contain information like below.

///////////
First
0x04
0x05
0x06

Second
0x07
0x08
0x09

Third
0x0E
0x0F
0x0D
///////////

In my main program, it will open this dat file, read line by line.
When it hits the string I'm searching for (e.g. "First"), the program
will know that the next line will be the variables to be stored. Are
there any C function to read file line by line? Please give me some
clue. Thanks a lot.

Look at the fgets function.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 13 '05 #2

P: n/a

"Abby" <ab*****@yahoo.com> wrote in message
Are there any C function to read file line by line? Please give me some
clue. Thanks a lot.

fgets() reads a line, if you know the maximum length it can be.

It is maybe better to use fscanf(). A bit like printf(), it takes a format
string that is a little language in its own right.
Nov 13 '05 #3

P: n/a

"Abby" <ab*****@yahoo.com> wrote in message
news:b4**************************@posting.google.c om...
My .dat file will contain information like below.

///////////
First
0x04
0x05
0x06

Second
0x07
0x08
0x09

Third
0x0E
0x0F
0x0D
///////////

In my main program, it will open this dat file, read line by line.
When it hits the string I'm searching for (e.g. "First"), the program
will know that the next line will be the variables to be stored. Are
there any C function to read file line by line? Please give me some
clue. Thanks a lot.

Abby.


You can use fgets( ) to read the line from file.
In this case, if you need to extract the value of hex code (like 0x0E,
0x0F ). You can use sscanf( ) to help you.
fgets( stringbuffer, 20, fp);
sscanf( stringbuffer, "%X", &var1);

--
Jeff
Nov 13 '05 #4

P: n/a
In <pa****************************@bd-home-comp.no-ip.org> bd <bd*****@bd-home-comp.no-ip.org> writes:
On Sat, 02 Aug 2003 00:18:37 +0100, Malcolm wrote:

"Abby" <ab*****@yahoo.com> wrote in message
Are there any C function to read file line by line? Please give me some
clue. Thanks a lot.
fgets() reads a line, if you know the maximum length it can be.


It's not difficult to dynamically allocate memory for a line with fgets.


How can you predict the size needed by each fgets() call?
Then it can be any length.
To be able to read arbitrarily sized lines, fgets() is of little help.
The code actually implementing such a routine is even simpler if you
don't use fgets at all!

AFAICT, fgets is a solution in search of a problem.
It is maybe better to use fscanf(). A bit like printf(), it takes a format
string that is a little language in its own right.


The length is still fixed - or you have a buffer overflow.


You have the option to trivially discard the excess characters, thus
avoiding a fixed buffer overflow. Depending on the actual application,
this may or may not be an acceptable solution.
Best to use fgets.


Nope, it's *never* best to use fgets. Its usage is complicated and
error prone. When I ask for a fgets-based, bullet-proof solution, I
usually get broken code: it's far too easy to omit or ignore one of the
ways a fgets call can go wrong. The function is simply broken by
design (assuming that it was actually designed).

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #5

P: n/a
In <bg**********@news.hgc.com.hk> "Jeff" <no*****@notexist.com> writes:

"Abby" <ab*****@yahoo.com> wrote in message
news:b4**************************@posting.google. com...
My .dat file will contain information like below.

///////////
First
0x04
0x05
0x06

Second
0x07
0x08
0x09

Third
0x0E
0x0F
0x0D
///////////

In my main program, it will open this dat file, read line by line.
When it hits the string I'm searching for (e.g. "First"), the program
will know that the next line will be the variables to be stored. Are
there any C function to read file line by line? Please give me some
clue. Thanks a lot.
You can use fgets( ) to read the line from file.
In this case, if you need to extract the value of hex code (like 0x0E,
0x0F ). You can use sscanf( ) to help you.

fgets( stringbuffer, 20, fp);


You can't blindly assume that a fgets call succeeds or that it exhausts
an input line.
sscanf( stringbuffer, "%X", &var1);


You can't blindly assume that a sscanf call succeeds, either.

With relatively few exceptions, the return value of a library function
call should not be discarded *before* being checked.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #6

P: n/a
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
Nope, it's *never* best to use fgets. Its usage is complicated and
error prone. When I ask for a fgets-based, bullet-proof solution, I
usually get broken code: it's far too easy to omit or ignore one of the
ways a fgets call can go wrong. The function is simply broken by
design (assuming that it was actually designed).


May I submit this code?

#ifndef H_ED_IO_20030121102334
#define H_ED_IO_20030121102334

/* ed/inc/io.h */
#include <stdio.h>

enum
{
IO_OK,
IO_ERR_READ,
IO_ERR_LENGTH,
IO_ERR_BUFFER,
IO_ERR_CONVERSION,
IO_ERR_EMPTY,
IO_ERR_OUTPUT_ADDRESS,
IO_ERR_NB
};

int fget_s (char *s, size_t size, FILE * fp);

<...>

#endif /* H_ED_IO_20030121102334 */
#include "ed/inc/io.h"
#include <string.h>

static void clear_in (FILE * fp)
{
int c;

while ((c = fgetc (fp)) != '\n' && c != EOF)
{
}
}

int fget_s (char *s, size_t size, FILE * fp)
{
int err = IO_OK;

if (s != NULL)
{
if (fgets (s, size, fp) != NULL)
{
char *p = strchr (s, '\n');

if (p)
{
*p = 0;
}
else
{
clear_in (fp);
err = IO_ERR_LENGTH;
}
}
else
{
err = IO_ERR_READ;
}

}
else
{
err = IO_ERR_BUFFER;
}

return err;
}

<...>

--
-ed- em**********@noos.fr [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/
Nov 13 '05 #7

P: n/a
In <Xn***************************@130.133.1.4> Emmanuel Delahaye <em**********@noos.fr> writes:
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
Nope, it's *never* best to use fgets. Its usage is complicated and
error prone. When I ask for a fgets-based, bullet-proof solution, I
usually get broken code: it's far too easy to omit or ignore one of the
ways a fgets call can go wrong. The function is simply broken by
design (assuming that it was actually designed).
May I submit this code?

#ifndef H_ED_IO_20030121102334
#define H_ED_IO_20030121102334

/* ed/inc/io.h */
#include <stdio.h>

enum
{
IO_OK,
IO_ERR_READ,
IO_ERR_LENGTH,
IO_ERR_BUFFER,
IO_ERR_CONVERSION,
IO_ERR_EMPTY,
IO_ERR_OUTPUT_ADDRESS,
IO_ERR_NB
};

int fget_s (char *s, size_t size, FILE * fp);

<...>

#endif /* H_ED_IO_20030121102334 */
#include "ed/inc/io.h"
#include <string.h>

static void clear_in (FILE * fp)
{
int c;

while ((c = fgetc (fp)) != '\n' && c != EOF)
{
}
}

int fget_s (char *s, size_t size, FILE * fp)
{
int err = IO_OK;

if (s != NULL)


What's the point in checking s if you don't check fp too? Either both
or neither.
{
if (fgets (s, size, fp) != NULL)
{
char *p = strchr (s, '\n');

if (p)
{
*p = 0;
}
else
{
clear_in (fp); ^^^^^^^^^^^^^
What is that? An attempt to make the code look simpler than it actually
is? ;-)
err = IO_ERR_LENGTH;
}
There is a logical error here. Imagine that the *only* character left
unread on the input line was the newline itself. This shouldn't be
treated as an error condition; simply remove it from the stream and
return IO_OK: the user provided buffer contains the full line!
}
else
{
err = IO_ERR_READ;
}

}
else
{
err = IO_ERR_BUFFER;
}

return err;
}


Its sheer complexity brilliantly proves my point. Despite the fact that
you have not inlined the code of clear_in(), and of the bug mentioned
above. Fixing these issues will complicate the function significantly.

Try to implement fget_s without using fgets at all and see if the code is
not actually simpler.

The fscanf equivalent is so simple that it can be used inline whenever
needed:

char s[NN + 1] = "", c;

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
if (rc == 1) fscanf("%*[^\n]%*c);
if (rc == 0) getc(fp);

The value of rc is telling the whole story:

EOF - end of file encountered before getting a single character
0 - an empty line was input
1 - the line was truncated
2 - the line was completely read

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #8

P: n/a
Dan Pop wrote:
char s[NN + 1] = "", c;

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
if (rc == 1) fscanf("%*[^\n]%*c);
if (rc == 0) getc(fp);

The value of rc is telling the whole story:

EOF - end of file encountered before getting a single character
0 - an empty line was input
1 - the line was truncated
2 - the line was completely read


Huh! Call me converted. Saved for future reference!!
(Thanks, Dan.)

--
|_ CJSonnack <Ch***@Sonnack.com> _____________| How's my programming? |
|_ http://www.Sonnack.com/ ___________________| Call: 1-800-DEV-NULL |
|_____________________________________________|___ ____________________|
Nov 13 '05 #9

P: n/a
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
In <Xn***************************@130.133.1.4> Emmanuel Delahaye
<em**********@noos.fr> writes:
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
Nope, it's *never* best to use fgets. Its usage is complicated and
error prone. When I ask for a fgets-based, bullet-proof solution, I
usually get broken code: it's far too easy to omit or ignore one of
the ways a fgets call can go wrong. The function is simply broken by
design (assuming that it was actually designed).
May I submit this code?

#ifndef H_ED_IO_20030121102334
#define H_ED_IO_20030121102334

/* ed/inc/io.h */
#include <stdio.h>

enum
{
IO_OK,
IO_ERR_READ,
IO_ERR_LENGTH,
IO_ERR_BUFFER,
IO_ERR_CONVERSION,
IO_ERR_EMPTY,
IO_ERR_OUTPUT_ADDRESS,
IO_ERR_NB
};

int fget_s (char *s, size_t size, FILE * fp);

<...>

#endif /* H_ED_IO_20030121102334 */
#include "ed/inc/io.h"
#include <string.h>

static void clear_in (FILE * fp)
{
int c;

while ((c = fgetc (fp)) != '\n' && c != EOF)
{
}
}

int fget_s (char *s, size_t size, FILE * fp)
{
int err = IO_OK;

if (s != NULL)


What's the point in checking s if you don't check fp too? Either both
or neither.


You are correct. I will fix it.
{
if (fgets (s, size, fp) != NULL)
{
char *p = strchr (s, '\n');

if (p)
{
*p = 0;
}
else
{
clear_in (fp);

^^^^^^^^^^^^^
What is that? An attempt to make the code look simpler than it actually
is? ;-)


This function was defined a few lines before.
err = IO_ERR_LENGTH;
}


There is a logical error here. Imagine that the *only* character left
unread on the input line was the newline itself. This shouldn't be
treated as an error condition;


You mean, if the size of the buffer was < 2? I should test that as a
precondition. To work correctly, the buffer size must be >= 2 char.
simply remove it from the stream and
It's done.
return IO_OK: the user provided buffer contains the full line!
}
else
{
err = IO_ERR_READ;
}

}
else
{
err = IO_ERR_BUFFER;
}

return err;
}
Its sheer complexity brilliantly proves my point. Despite the fact that
you have not inlined the code of clear_in(),


It was.
and of the bug mentioned
above.
Fixing these issues will complicate the function significantly.
I guess you are kidding. Even once fixed, this code is straight simple and
clear. I see no complications or difficulties on it. It takes a significant
number of source lines because I'm used to write code that is readable (at
last by me). I'm not found of cryptic or ultra-compact coding (actually it's
forbidden in the company I work for).
Try to implement fget_s without using fgets at all and see if the code
is not actually simpler.
I see your point. Could be, yes.
The fscanf equivalent is so simple that it can be used inline whenever
needed:

char s[NN + 1] = "", c;

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
if (rc == 1) fscanf("%*[^\n]%*c);
if (rc == 0) getc(fp);
I agree that it's short and compact, but I'd call it cryptic. The
choice of the 'complicated' qualifier or not is left to the reader!
The value of rc is telling the whole story:

EOF - end of file encountered before getting a single character
0 - an empty line was input
1 - the line was truncated
2 - the line was completely read


Interesting however. Thanks for having read me.

--
-ed- em**********@noos.fr [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/
Nov 13 '05 #10

P: n/a
ab*****@yahoo.com (Abby) wrote:
My .dat file will contain information like below.

///////////
First
[...]

In my main program, it will open this dat file, read line by line.
When it hits the string I'm searching for (e.g. "First"), the program
will know that the next line will be the variables to be stored. Are
there any C function to read file line by line? Please give me some
clue. Thanks a lot.


You can try using fgets() as suggested by others, but it requires you
to make choices about the target buffer size before you read each
line. I.e., either your solution is convoluted and has a built in
buffer growing algorithm, or it has a buffer overflow, or it just
behaves incorrectly for inputs that are too large. If you have a very
strict way in which your input files are constructed then you can get
away with a fixed buffer algorithm, of course.

The alternative is to use a string library that takes care of this for
you. There are many string libraries that can work for you, but let
me just suggest how it might be done with my own called the "better
string library" (http://bstring.sf.net/):

Alternative 1: A high performance streaming solution (but it will read
ahead, which may be inappropriate for your application)

FILE * fp = fopen (inputFileName, "r");

if (fp) {
bStream s = bsopen ((bNread) fread, fp);
bstring b = cstr2bstr ("");
while (BSTR_OK == bsreadln (b, s, '\n')) {
/* b->data is an "unsigned char *" pointing to a line */
}
bdestroy (b);
bsclose (s);
fclose (fp);
}

Alternative 2: A slow but simpler streaming solution (the file reading
is exact)

FILE * fp = fopen (inputFileName, "r");

if (fp) {
bstring b;
while ((b = bgets ((bNgetc) fgetc, fp, '\n')) != NULL) {
/* b->data is an "unsigned char *" pointing to a line */
bdestroy (b);
}
fclose (fp);
}

Alternative 3: Just read the whole thing and parse it afterward (if
you have to read and hold the whole file anyway, this is probably the
fastest solution and gives you indexed random access to the lines.)

FILE * fp = fopen (inputFileName, "r");
bstring b;

if (fp) {
bstring b = bread ((bNread) fread, fp);
struct bstrList * bl = bsplit (b, '\n');
int i;
if (bl) for (i=0; i < bl->qty; i++) {
/* bl->entry[i]->data is pointing to a line */
}
bstrListDestroy (bl);
bdestroy (b);
fclose (fp);
}

None of the alternatives shown above have any risk of buffer overflow
(though apparently they might not work correctly on the Tandom NonStop
or Data General Eclipse computers, but if you are on such a machine
you practically already know this and you have my greatest sympathy
and there is a simple way to work around the problem as described in
the documentation) and as shown there will be no memory leaks. Even
attempts at out-of-memory and input stack smashing attacks cannot
happen.

As to parsing the lines, the "better string library" has functions
like biseq, bCaselessCmp, bsplit, binstr, binchr etc and because of
its direct interoperability with char * buffers, you can use C
standard library functions like atoi, sscanf, and so on with no issue.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Nov 13 '05 #11

P: n/a
Kevin Easton <kevin@-nospam-pcug.org.au> wrote in message news:<ne********************@tomato.pcug.org.au>.. .
Dan Pop <Da*****@cern.ch> wrote:
[...]
The fscanf equivalent is so simple that it can be used inline whenever
needed:

char s[NN + 1] = "", c;

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
if (rc == 1) fscanf("%*[^\n]%*c);
if (rc == 0) getc(fp);

The value of rc is telling the whole story:

EOF - end of file encountered before getting a single character
0 - an empty line was input
1 - the line was truncated
2 - the line was completely read


If you want to be able to specify the buffer size at runtime, then this
solution becomes a little more complex.


but not by very much.
#define FORMAT_STRING_SIZE 200

size_t runtime_size;
....
char *s = malloc (runtime_size), c;
if (!s) {
/* handle error */
} else {
int rc;
char temp[FORMAT_STRING_SIZE];

sprintf (temp, "%%%u[^\\n]%%1[\\n]");
rc = fscanf (fp, temp, s, &c);

switch (rc) {
/* handle all the possible return values here */
}

free (s);
}

goose,
Nov 13 '05 #12

P: n/a
In <ne********************@tomato.pcug.org.au> Kevin Easton <kevin@-nospam-pcug.org.au> writes:
Dan Pop <Da*****@cern.ch> wrote:
[...]
The fscanf equivalent is so simple that it can be used inline whenever
needed:

char s[NN + 1] = "", c;

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
if (rc == 1) fscanf("%*[^\n]%*c);
if (rc == 0) getc(fp);

The value of rc is telling the whole story:

EOF - end of file encountered before getting a single character
0 - an empty line was input
1 - the line was truncated
2 - the line was completely read


If you want to be able to specify the buffer size at runtime, then this
solution becomes a little more complex.


A little more complex meaning an extra sprintf call. However, given the
fact that the code is so simple that it can be inlined, you don't
normally need to specify the buffer size at run time.

As I said sometime ago, none of these solutions (either scanf or fgets
based) is robust enough for production code, because they don't check
for embedded null characters in the input stream.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #13

P: n/a
goose <ru**@webmail.co.za> wrote:
Kevin Easton <kevin@-nospam-pcug.org.au> wrote in message news:<ne********************@tomato.pcug.org.au>.. .
Dan Pop <Da*****@cern.ch> wrote:
[...]
> The fscanf equivalent is so simple that it can be used inline whenever
> needed:
>
> char s[NN + 1] = "", c;
>
> int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
> if (rc == 1) fscanf("%*[^\n]%*c);
> if (rc == 0) getc(fp);
>
> The value of rc is telling the whole story:
>
> EOF - end of file encountered before getting a single character
> 0 - an empty line was input
> 1 - the line was truncated
> 2 - the line was completely read
If you want to be able to specify the buffer size at runtime, then this
solution becomes a little more complex.


but not by very much.


Yes, "little" and "not very much" are pretty much synonyms, are they
not?
#define FORMAT_STRING_SIZE 200

size_t runtime_size;
...
char *s = malloc (runtime_size), c;
if (!s) {
/* handle error */
} else {
int rc;
char temp[FORMAT_STRING_SIZE];

sprintf (temp, "%%%u[^\\n]%%1[\\n]");


Where's the matching argument for that %u conversion specifier? :)

- Kevin.

Nov 13 '05 #14

P: n/a
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
You're missing the point, although my explanation was crystal clear.
Imagine that size is 50 and the line has 49 characters plus the newline.
You have read the full line (except the newline), but you're returning
IO_ERR_LENGTH to the user, despite the fact that s contains the complete
line. Instead of doing that, you should remove the newline character
from the input stream and return IO_OK. But this is complicating your
function even further.
You mean this case:

sizeof s = 10
012345678
input error #2: 'ERR_LENGTH'
IN: '012345678'

Understood. The fix should not be too difficult, but I would imply a
strlen(), which is a waste of time.
Its sheer complexity brilliantly proves my point. Despite the fact
that you have not inlined the code of clear_in(),


It was.


Was it *inlined* ? I don't think so.


Dou you mean I should have coded this function like a function-like macro?

It is a static function. I let the compiler optimize it. Some of them do
inline in such conditions. Don't tell me that I should have use the C99
inline feature, or worst, some gcc extension. I attempt to write today's
/portable/ code. (At work, I use at last 4 different C-compilers for various
targets like x86, 68k, PowerPC or Texas DSP).
and of the bug mentioned
above.
Fixing these issues will complicate the function significantly.


I guess you are kidding. Even once fixed, this code is straight simple
and clear.


Fix it first, and see what it looks like.


Here is the fix (you will like it!):

static int clear_in (FILE * fp)
{
int n = 0;
int c;

do
{
c = fgetc (fp);

if (c != EOF)
{
n++;
}
}
while (c != '\n' && c != EOF);

return n;
}
int fget_s (char *s, size_t size, FILE * fp)
{
int err = IO_OK;

if (s != NULL)
{
if (size > 1)
{
if (fp != NULL)
{
if (fgets (s, size, fp) != NULL)
{
char *p = strchr (s, '\n');

if (p)
{
*p = 0;
}
else
{
int n = clear_in (fp);

if (n > 1)
{
err = IO_ERR_LENGTH;
}
}
}
else
{
err = IO_ERR_READ;
}
}
else
{
err = IO_ERR_FILE;
}
}
else
{
err = IO_ERR_BUFFER_SIZE;
}
}
else
{
err = IO_ERR_BUFFER;
}

return err;
}
Your coding style is very unreadable to me. I really had to make an
effort to match some if's and else's, because they were so far away, due
to your *waste* of vertical space.
The indentation is supposed to be crystal clear (My DOS port of GNUIndent
1.91). If you don't like it, just reindent the code with you own settings.
(K&R-style is more compact)
Try to implement fget_s without using fgets at all and see if the code
is not actually simpler.


I see your point. Could be, yes.


Then, what's the point in using fgets?


At a first glance, it seems quick and simple, but you are right, it is more
complicated than it sounded. I'm working on a pure fgetc() solution.
The fscanf equivalent is so simple that it can be used inline whenever
needed:

char s[NN + 1] = "", c;

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
if (rc == 1) fscanf("%*[^\n]%*c);
if (rc == 0) getc(fp);


I agree that it's short and compact, but I'd call it cryptic.


What is the cryptic part? A simple fscanf call, followed by two simple

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
What is NN ? A macro? Are you sure a macro is replaced in a string?

I would have written it:

int rc = fscanf(fp, "%*[^\n]%1[\n]", NN, s, &c);
if (rc == 1) fscanf("%*[^\n]%*c);


I think some parameters are missing for the two '*' and the two '%'.
Additionally, a '"' is missing too. Could you please fix that.

I feel free to call this code cryptic and hard to read and it seems that I'm
not alone.
tests, needed to decide what kind of cleanup is needed (if any).
This code also correctly handles the situation where your code fails
(the buffer has the exact size for the input line).
The choice of the 'complicated' qualifier or not is left to the reader!


When three simple lines of code can do the job better than a couple
dozen, there is no question about which is the complicated solution.


We don't have the same definition for 'complicated'. You count the lines, I
try to read the code. That's the difference. Nobody win[s?]. Just a different
approach.

--
-ed- em**********@noos.fr [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/
Nov 13 '05 #15

P: n/a
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
As I said sometime ago, none of these solutions (either scanf or fgets
based) is robust enough for production code, because they don't check
for embedded null characters in the input stream.


I see. A fully fgetc() solution should be better, isn't it?

--
-ed- em**********@noos.fr [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/
Nov 13 '05 #16

P: n/a
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
The fscanf equivalent is so simple that it can be used inline whenever
needed:

char s[NN + 1] = "", c;

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
Not sure that the NN macro will be replaced in a string...

int rc = fscanf(fp, "%*[^\n]%1[\n]", NN, s, &c);
if (rc == 1) fscanf("%*[^\n]%*c);
This part is very broken.

if (rc == 1) fscanf(fp, "%*[^\n]%*c", <I don't know what>);
if (rc == 0) getc(fp);


--
-ed- em**********@noos.fr [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/
Nov 13 '05 #17

P: n/a
In 'comp.lang.c', Emmanuel Delahaye <em**********@noos.fr> wrote:
Understood. The fix should not be too difficult, but I would imply a
strlen(), which is a waste of time.


Actually, I found a solution without strlen().

--
-ed- em**********@noos.fr [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/
Nov 13 '05 #18

P: n/a
Emmanuel Delahaye <em**********@noos.fr> wrote:
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote: [...]
The fscanf equivalent is so simple that it can be used inline whenever
needed:

char s[NN + 1] = "", c;

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
if (rc == 1) fscanf("%*[^\n]%*c);
if (rc == 0) getc(fp);

I agree that it's short and compact, but I'd call it cryptic.


What is the cryptic part? A simple fscanf call, followed by two simple

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
What is NN ? A macro? Are you sure a macro is replaced in a string?


I think it's clear from context that NN is supposed to be replaced by
the human writing the code...
I would have written it:

int rc = fscanf(fp, "%*[^\n]%1[\n]", NN, s, &c);


Then you would have written something that doesn't work.
if (rc == 1) fscanf("%*[^\n]%*c);


I think some parameters are missing for the two '*' and the two '%'.


You need to bone up on scanf - in particular how %* works in the scanf
family as opposed to how it works in the printf family.

- Kevin.

Nov 13 '05 #19

P: n/a

I see much nit-picking in this thread but who is willing to put up the
complete, unbreakable, replacement for Emmanuel Delahaye's code?

--
-MM
I rarely read email from this address /"\
because of spam. \ / ASCII Ribbon Campaign
I MAY see it if you put #NOTSPAM# X Against HTML Mail
in the subject line. / \
Nov 13 '05 #20

P: n/a
Mark Mynsted wrote:
I see much nit-picking in this thread but who is willing to put up the
complete, unbreakable, replacement for Emmanuel Delahaye's code?


Mark...

For "reasonable" length input lines, see the code at

http://www.iedu.com/mrd/c/getsm.c

However, it breaks on my system when the line length exceeds
about 700k characters; and may break sooner (or later) on /your/
system.
--
Morris Dovey
West Des Moines, Iowa USA
C links at http://www.iedu.com/c

Nov 13 '05 #21

P: n/a
In <Xn***************************@130.133.1.4> Emmanuel Delahaye <em**********@noos.fr> writes:
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
As I said sometime ago, none of these solutions (either scanf or fgets
based) is robust enough for production code, because they don't check
for embedded null characters in the input stream.


I see. A fully fgetc() solution should be better, isn't it?


Indeed, except that I see no good reason for preferring the fgetc function
to the getc macro (traditionally, the f in fgetc stands for "function").
Provided that it is properly designed and implemented. The most difficult
part is the design, the implementation is a piece of cake.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #22

P: n/a
In <Xn***************************@130.133.1.4> Emmanuel Delahaye <em**********@noos.fr> writes:
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
You're missing the point, although my explanation was crystal clear.
Imagine that size is 50 and the line has 49 characters plus the newline.
You have read the full line (except the newline), but you're returning
IO_ERR_LENGTH to the user, despite the fact that s contains the complete
line. Instead of doing that, you should remove the newline character
from the input stream and return IO_OK. But this is complicating your
function even further.
You mean this case:

sizeof s = 10
012345678
input error #2: 'ERR_LENGTH'
IN: '012345678'


Yup.
Understood. The fix should not be too difficult, but I would imply a
strlen(), which is a waste of time.
What the hell do you need a strlen() for? I can't see any in your
fixed solution below!
Its sheer complexity brilliantly proves my point. Despite the fact
that you have not inlined the code of clear_in(),

It was.


Was it *inlined* ? I don't think so.


Dou you mean I should have coded this function like a function-like macro?

It is a static function. I let the compiler optimize it. Some of them do
inline in such conditions. Don't tell me that I should have use the C99
inline feature, or worst, some gcc extension. I attempt to write today's
/portable/ code. (At work, I use at last 4 different C-compilers for various
targets like x86, 68k, PowerPC or Texas DSP).


"Inlining" means writing the code right there, instead of putting it into
a function and calling it. It is the logical equivalent of the C99 inline
keyword, but is achieved by the programmer, not by the compiler.
Here is the fix (you will like it!):
Indeed! It is a brilliant confirmation of my point about the
complexity of *properly* using fgets() for reading a line of input!
You have also confirmed my statement that most people don't get it
right at the first attempt ;-)
static int clear_in (FILE * fp)
{
int n = 0;
int c;

do
{
c = fgetc (fp);

if (c != EOF)
{
n++;
}
}
while (c != '\n' && c != EOF);

return n;
}
int fget_s (char *s, size_t size, FILE * fp)
{
int err = IO_OK;

if (s != NULL)
{
if (size > 1)
{
if (fp != NULL)
{
if (fgets (s, size, fp) != NULL)
{
char *p = strchr (s, '\n');

if (p)
{
*p = 0;
}
else
{
int n = clear_in (fp);

if (n > 1)
{
err = IO_ERR_LENGTH;
}
}
}
else
{
err = IO_ERR_READ;
}
}
else
{
err = IO_ERR_FILE;
}
}
else
{
err = IO_ERR_BUFFER_SIZE;
}
}
else
{
err = IO_ERR_BUFFER;
}

return err;
}
Your coding style is very unreadable to me. I really had to make an
effort to match some if's and else's, because they were so far away, due
to your *waste* of vertical space.
The indentation is supposed to be crystal clear (My DOS port of GNUIndent
1.91). If you don't like it, just reindent the code with you own settings.
(K&R-style is more compact)


The indentation is not the issue. The number of indentation levels
caused by the nested control statements is the issue. Code requiring
more than three nested control statements is badly designed and horribly
difficult to read, no matter how well indented.

Although your mama didn't tell you, C is not Pascal and there is no
point in writing Pascal code disguised as C code. I have rewritten
your fget_s without using any kind of nested control statements:

int fget_s (char *s, size_t size, FILE * fp)
{
char *p;

if (s == NULL) return IO_ERR_BUFFER;
if (size <= 1) return IO_ERR_BUFFER_SIZE;
if (fp == NULL) return IO_ERR_FILE;
if (fgets(s, size, fp) == NULL) return IO_ERR_READ;
p = strchr(s, '\n');
if (p != NULL) {
*p = 0;
return IO_OK;
}
if (clear_in(fp) == 1) return IO_OK;
return IO_ERR_LENGTH;
}

No need to figure out which else matches which if (there is no else at
all) and, by testing the right conditions, you don't need nested if's
either. If your employer forbids more than one return statement per
function, I'd suggest finding a new job.
char s[NN + 1] = "", c;

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
if (rc == 1) fscanf("%*[^\n]%*c);
if (rc == 0) getc(fp);

I agree that it's short and compact, but I'd call it cryptic.


What is the cryptic part? A simple fscanf call, followed by two simple

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
What is NN ? A macro? Are you sure a macro is replaced in a string?


Nope, it's not a macro, it's a place holder for an embedded constant.
I would have written it:

int rc = fscanf(fp, "%*[^\n]%1[\n]", NN, s, &c);
Unfortunately, this is not possible, * has different semantics in scanf
formats: it's the assignment suppression character, as exemplified in
my own code below.
if (rc == 1) fscanf("%*[^\n]%*c);
I think some parameters are missing for the two '*' and the two '%'.
Additionally, a '"' is missing too. Could you please fix that.


The only missing bit is the string literal terminator:

if (rc == 1) fscanf("%*[^\n]%*c");

You're in dire need of a clue about scanf and friends.
I feel free to call this code cryptic and hard to read and it seems that I'm
not alone.
You have amply demonstrated that you're not competent enough to make such
a statement, for the simple reason that you don't know how scanf works.

Furthermore, truth is not a democracy issue. The fscanf calls are
cryptical to my mother, too, but she doesn't have a single clue about C.
See my point?
tests, needed to decide what kind of cleanup is needed (if any).
This code also correctly handles the situation where your code fails
(the buffer has the exact size for the input line).
The choice of the 'complicated' qualifier or not is left to the reader!


When three simple lines of code can do the job better than a couple
dozen, there is no question about which is the complicated solution.


We don't have the same definition for 'complicated'. You count the lines,


Wrong! The line count is irrelevant. The code structure is.
I try to read the code. That's the difference.
Indeed. As demonstrated above, your code is very unreadable, being very
badly structured.
Nobody win[s?]. Just a different approach.


I disagree. Take my version of fget_s, add vertical space and braces
according to your taste and it's still a lot more readable than
your version.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #23

P: n/a
>>>>> "Morris" == Morris Dovey <mr*****@iedu.com> writes:
Morris> For "reasonable" length input lines, see the code at
Morris> http://www.iedu.com/mrd/c/getsm.c

A clever solution.

--
-MM
I rarely read email from this address /"\
because of spam. \ / ASCII Ribbon Campaign
I MAY see it if you put #NOTSPAM# X Against HTML Mail
in the subject line. / \
Nov 13 '05 #24

P: n/a
In <Xn***************************@130.133.1.4> Emmanuel Delahaye <em**********@noos.fr> writes:
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:

All-right, but I wonder...
int fget_s (char *s, size_t size, FILE * fp)
{
char *p;

if (s == NULL) return IO_ERR_BUFFER;
if (size <= 1) return IO_ERR_BUFFER_SIZE;
if (fp == NULL) return IO_ERR_FILE;
if (fgets(s, size, fp) == NULL) return IO_ERR_READ;
p = strchr(s, '\n');
if (p != NULL) {
*p = 0;
return IO_OK;
}
if (clear_in(fp) == 1) return IO_OK;
return IO_ERR_LENGTH;
}
... where do I place the cursor when I want to know the returned value using
the debugger?


On the line calling it. Once you have debugged this function, its
internals are of little relevance to debugging the rest of the program.
I figure that your answer is "True C programmers don't use debuggers"...


Good programmers place readability much higher than ease of using the
debugger on their priority list. And it is not uncommon for C programmers
to use the debugger only for analysing core dumps. A certain Brian W.
Kernighan has openly admitted that he has no other uses for a debugger.
>> int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);

What is NN ? A macro? Are you sure a macro is replaced in a string?


Nope, it's not a macro, it's a place holder for an embedded constant.


Ok, it was pseudo-code.


Sort of. The rest was supposed to be valid C code, modulo the
unterminated string literal glitch.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #25

P: n/a
Dan Pop wrote:
(traditionally, the f in fgetc stands for "function").


Really? Wow. I always thought they stood for "file":

fopen - file open
fclose - file close
fgets - file get string
fgetc - file get char

Like that.

Come to think of it, shouldn't it be:

fstrcpy - function string copy
fmemset - function memory set

Like that?

--
|_ CJSonnack <Ch***@Sonnack.com> _____________| How's my programming? |
|_ http://www.Sonnack.com/ ___________________| Call: 1-800-DEV-NULL |
|_____________________________________________|___ ____________________|
Nov 13 '05 #26

P: n/a
On 5 Aug 2003 13:41:30 GMT, Da*****@cern.ch (Dan Pop) wrote:
In <Xn***************************@130.133.1.4> Emmanuel Delahaye <em**********@noos.fr> writes:
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:
if (rc == 1) fscanf("%*[^\n]%*c);


This part is very broken.


Apart from the missing " at the end of the format string, it's OK.


Am I missing something, or are you? I see 2 problems in the line
above. You have noted the second. Chapter and verse, please on
the first :-)

Dan
--


Regards,
Bruce Wheeler

Nov 13 '05 #27

P: n/a
Kevin Easton <kevin@-nospam-pcug.org.au> wrote in message news:<ne********************@tomato.pcug.org.au>.. .
goose <ru**@webmail.co.za> wrote:
Kevin Easton <kevin@-nospam-pcug.org.au> wrote in message news:<ne********************@tomato.pcug.org.au>.. .
<snipped>

but not by very much.


Yes, "little" and "not very much" are pretty much synonyms, are they
not?


<sheepish grin> err, yeah ... guess i got a little overenthusiastic
at following up to everything :-)

<snipped>

sprintf (temp, "%%%u[^\\n]%%1[\\n]");


Where's the matching argument for that %u conversion specifier? :)

NNNNNNNGGGGGGGG!!!!

stuff like this *always* happens when I'm too lazy to compile before
posting

goose,
my last response to this got trashed, hope this only appears
once
Nov 13 '05 #28

P: n/a
In <3f30c4c0.16999333@news> bs*********@hotmail.com (Bruce Wheeler) writes:
On 5 Aug 2003 13:41:30 GMT, Da*****@cern.ch (Dan Pop) wrote:
In <Xn***************************@130.133.1.4> Emmanuel Delahaye <em**********@noos.fr> writes:
In 'comp.lang.c', Da*****@cern.ch (Dan Pop) wrote:

if (rc == 1) fscanf("%*[^\n]%*c);

This part is very broken.


Apart from the missing " at the end of the format string, it's OK.


Am I missing something, or are you? I see 2 problems in the line
above. You have noted the second. Chapter and verse, please on
the first :-)


The first is trivially reported by the compiler. The second is more
problematic if you forget -pedantic on your gcc command line ;-)

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #29

P: n/a
Dan Pop wrote:
(traditionally, the f in fgetc stands for "function").
Really? Wow. I always thought they stood for "file":

fopen - file open
fclose - file close
fgets - file get string
fgetc - file get char

Like that.

Come to think of it, shouldn't it be:

fstrcpy - function string copy
fmemset - function memory set

Like that?


Broken analogy.


Why? If the leading "f" in "fgetc" stands for "function", then
it seems a short stretch to presume it likewise stands for
"function" when it is used elsewhere, *particularly* when used
in the same "family". It is perhaps more of a stretch to wonder
why it wasn't used universally, but let's stick with the file
stream family.
Have a look at K&R1. You won't find any trace of fgetc, but
you'll find getc, with exactly the same semantics. So, where
does fgetc come from?
Irrelevant. Wherever it came from, it seems it wears the same
cloak (read: prefix) as do its other family members (as above).
We might also add: fprintf, fscanf, fread, fwrite, fputs,....
All of which require a FILE*. Doesn't seem hard to perceive
that the "f" refers to that FILE* argument.
As I said, K&R C provided getc, with the explicit mention that
it is a macro defined in <stdio.h>. Later, some people decided
that it would be handy to also have a function with the same
semantics, and this is how fgetc was born. So, with this
additional information, even Programmer Dude could figure out
what the f in fgetc stands for.
Same as the "f" in "fopen", "fprintf", "fgets", "fscanf" & "fclose"!
But, Dan, speaking of broken analogies, where are the matching
"open", "printf" (!), "gets" (!!), "scanf" (!!!) & "close" macros?
Even in standard C there is a subtle difference between getc and
fgets, despite the identical interface and semantics.
Surely more than a *subtle* difference between getc and fgets! (-;

But, yes, I'm aware of the subtle difference between getc and fgetc.
But said subtle difference having nought to do with what the "f"
stands for (AFAICS).
The same discussion applies to putc vs fputc, with the mention that
a putc macro is only allowed to perform multiple evaluation of the
file pointer parameter. These are the ONLY exceptions from the
general rule that a macro implementation of a standard library
function cannot perform multiple evaluation of its parameters. A
strong indication that the C standard did its best to preserve getc
and putc as macros (although the implementation must also provide
their function version, too).
All very true and very useful ... but irrelevant wrt to that "f".
Next time you try to be smart, get a clue first.


I do *so* enjoy our pleasant talks together!! (-;

--
|_ CJSonnack <Ch***@Sonnack.com> _____________| How's my programming? |
|_ http://www.Sonnack.com/ ___________________| Call: 1-800-DEV-NULL |
|_____________________________________________|___ ____________________|
Nov 13 '05 #30

P: n/a
In <3F***************@mmm.com> Programmer Dude <cj*******@mmm.com> writes:
All very true and very useful ... but irrelevant wrt to that "f".


If you can't see the relevance, you're either genuinely obtuse or
deliberately obtuse.

Without the background information I have provided, your intervention
would have made sense. Insisting on it afterwards doesn't make any!

What is the historical difference between getc and fgetc and which
preceded the other by several good years? If you insist that the
answer to this question is irrelevant to the issue, I have nothing more
to add.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #31

P: n/a
Dan Pop wrote:
All very true and very useful ... but irrelevant wrt to that "f".
If you can't see the relevance, you're either genuinely obtuse or
deliberately obtuse.


Or genuinely curious.
What is the historical difference between getc and fgetc and which
preceded the other by several good years? If you insist that the
answer to this question is irrelevant to the issue, I have nothing
more to add.


Is it, then, your contention that the "f" in "fgetc" means "function",
whereas the "f" in "fopen", "fprintf", "fscanf", "fread", "fwrite",
"fclose" and others all mean something else?

If so, what? And what makes fgetc such a standout?

--
|_ CJSonnack <Ch***@Sonnack.com> _____________| How's my programming? |
|_ http://www.Sonnack.com/ ___________________| Call: 1-800-DEV-NULL |
|_____________________________________________|___ ____________________|
Nov 13 '05 #32

P: n/a
goose wrote:
Come to think of it, shouldn't it be:

fstrcpy - function string copy
fmemset - function memory set

Like that?


not really, unless you already have a strcpy that is a macro,
and it is necessary to implement one that is a function.


True enough. So do all macro/function pairs use an "f" prefix
to signify the "function" version?

--
|_ CJSonnack <Ch***@Sonnack.com> _____________| How's my programming? |
|_ http://www.Sonnack.com/ ___________________| Call: 1-800-DEV-NULL |
|_____________________________________________|___ ____________________|
Nov 13 '05 #33

P: n/a
Programmer Dude <cj*******@mmm.com> wrote in message news:<3F***************@mmm.com>...
Mark Gordon wrote:
So do all macro/function pairs use an "f" prefix
to signify the "function" version?
Yes, as Dan said getc/fgetc and putc/fputc do.


I will defer to the experts,


I usually do :-)
but I think it's illogical and
inconsistant that *those* 'f's mean "function"
it may be to you, to some it seems perfectly logical
given the history.
whereas the
'f's in "fopen", "fprintf", "fscanf", "fread", "fwrite",
"fclose" and others surely mean something else. (-;

to put it another way, we use '>' and '<' for 'greater
than' and 'less than' in code like we do in normal
non-programming usage, but we use '==' for 'equals to'
and '=' for assignment.

that is neither logical nor consistent (the pascal
way is much more consistent).
goose,
anyone knows how java does assignment/comparison ?
Nov 13 '05 #34

P: n/a
On Wed, 06 Aug 2003 16:05:18 -0500
Programmer Dude <cj*******@mmm.com> wrote:
Mark Gordon wrote:
So do all macro/function pairs use an "f" prefix
to signify the "function" version?


Yes, as Dan said getc/fgetc and putc/fputc do.


I will defer to the experts, but I think it's illogical and
inconsistant that *those* 'f's mean "function" whereas the
'f's in "fopen", "fprintf", "fscanf", "fread", "fwrite",
"fclose" and others surely mean something else. (-;


Remember that the language was defined by people and people are not
always consistent of logical. I'm sure you will have noticed that some
people here think that bad decisions have been made in writing the
standards.
--
Mark Gordon
Paid to be a Geek & a Senior Software Developer
Although my email address says spamtrap, it is real and I read it.
Nov 13 '05 #35

P: n/a
"Programmer Dude" <cj*******@mmm.com> wrote in message news:3F***************@mmm.com...
goose wrote:

True enough. So do all macro/function pairs use an "f" prefix
to signify the "function" version?


Not all. I remember working with an old version of Microsoft C which had both macro and function implementations for character
classification (isdigit(), etc). The macros and functions had the same name, but which you got was determined by the header file you
included - ctype.h for macros and fctype.h for functions.

Of course this was long before the days of standardisation....

--
#include <stdio.h>
char*f="#include <stdio.h>char*f=%c%s%c;main(){printf(f,34,f,34,10) ;}%c";
main(){printf(f,34,f,34,10);}
Nov 13 '05 #36

P: n/a
In <3F***************@mmm.com> Programmer Dude <cj*******@mmm.com> writes:
Mark Gordon wrote:
So do all macro/function pairs use an "f" prefix
to signify the "function" version?


Yes, as Dan said getc/fgetc and putc/fputc do.


I will defer to the experts, but I think it's illogical and
inconsistant that *those* 'f's mean "function" whereas the
'f's in "fopen", "fprintf", "fscanf", "fread", "fwrite",
"fclose" and others surely mean something else. (-;


Historical issues are seldom logical or consistent. Compare the
priorities of the equality operators vs the bitwise &, ^ and | and provide
a logical and consistent explanation. Ritchie has already explained the
historical reasons for this anomaly.

But, going back to <stdio.h>, the f prefix serves more than one purpose:

fopen, fclose, fread, fwrite: avoid the conflict with the low level I/O
routines open, close, read, write which presumably predate their high
level counterparts. Both sets operate on files, right? If logic
mattered, they would have been prefixed with s from "stream" rather than
f.

fprintf, fscanf: select one of the members of the printf, respectively
scanf families. It makes sense to assume that f stands for file.

fseek, ftell, fsetpos, fgetpos, fflush, fputc, fgetc, fgets: it would
be tempting to say that the f stands for file, but then how about
rewind, getc, putc, rename, remove and ungetc which also operate
on files?

Can you detect anything logical or consistent in the last paragraph?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #37

P: n/a
On 5 Aug 2003 10:35:29 GMT,
Dan Pop <Da*****@cern.ch> wrote
in Msg. <bg**********@sunnews.cern.ch>
The fscanf equivalent is so simple that it can be used inline whenever
needed:

char s[NN + 1] = "", c;

int rc = fscanf(fp, "%NN[^\n]%1[\n]", s, &c);
if (rc == 1) fscanf("%*[^\n]%*c);
if (rc == 0) getc(fp);


I agree that it's short and compact, but I'd call it cryptic.


What is the cryptic part?


The unterminated string constant, probably.

--Daniel

--
"With me is nothing wrong! And with you?" (from r.a.m.p)
Nov 13 '05 #38

P: n/a
goose wrote:
to put it another way, we use '>' and '<' for 'greater
than' and 'less than' in code like we do in normal
non-programming usage, but we use '==' for 'equals to'
and '=' for assignment.

that is neither logical nor consistent (the pascal
way is much more consistent).


Yet "==" and "!=" go well (logically) together, to my eye.
(Certainly no issue with two chars; consider "<=" and ">=".)

Also, C needs to differentiate assigment and equality, because
both are expressions which return values. You need that to know
that this...

int a = 2;
int b = (a = 4);

....sets b to 4, not 0.

As for Pascal, I never could get comfortable typing ":" and "="
in quick succession! (-:

--
|_ CJSonnack <Ch***@Sonnack.com> _____________| How's my programming? |
|_ http://www.Sonnack.com/ ___________________| Call: 1-800-DEV-NULL |
|_____________________________________________|___ ____________________|
Nov 13 '05 #39

P: n/a
Dan Pop wrote:
Ritchie has already explained the historical reasons for this
anomaly.
I haven't had a chance to check K&R, yet. Is there any *text*
that addresses this issue? (I'm quite certain there's nothing
in the standard.)
But, going back to <stdio.h>, the f prefix serves more than one
purpose: fopen, fclose, fread, fwrite: avoid the conflict with
the low level I/O routines open, close, read, write which
presumably predate their high level counterparts. Both sets
operate on files, right?
True, but only the f* group take a (FILE*) argument.
If logic mattered, they would have been prefixed with s from
"stream" rather than f.
Or named after that all-important struct, FILE.
fprintf, fscanf: select one of the members of the printf,
respectively scanf families. It makes sense to assume that
f stands for file.
Indeed.
fseek, ftell, fsetpos, fgetpos, fflush, fputc, fgetc, fgets: it
would be tempting to say that the f stands for file,...
All take a (FILE*) argument...
...but then how about rewind,...
And clearerr, set(v)buf & tmpfile.

These (plus below) are the *only* exceptions to the 'f' means
(FILE*) argument rule. As you mentioned recently, "the exception
to the rule."
...getc, putc, rename, remove and ungetc which also operate on
files?


(Also getwc, putwc, ungetwc.) rename and remove take filenames.
getc and putc are macros. (So it would seem quite logical to assume
that the *absense* of the 'f' signifys "macro" here. :-)

Which leaves ungetc as one more exception. Making a total of
seven exceptions compared to, by my quick count, 30 places where
'f' seems to mean (FILE*) argument. Does it make *more* or
*less* sense that the 'f' means "function" in just these two
places compared to all others?

If 'v' stands for varargs arguments, and 'w' stands for wide char
parameters, it still seems to me 'f' stands for (FILE*) parameter.

But if the experts say different,... the experts say different.

(-;

--
|_ CJSonnack <Ch***@Sonnack.com> _____________| How's my programming? |
|_ http://www.Sonnack.com/ ___________________| Call: 1-800-DEV-NULL |
|_____________________________________________|___ ____________________|
Nov 13 '05 #40

P: n/a
ab*****@yahoo.com (Abby) wrote in message news:<b4**************************@posting.google. com>...
My .dat file will contain information like below.

///////////
First
0x04
0x05
0x06

Second
0x07
0x08
0x09

Third
0x0E
0x0F
0x0D
///////////

In my main program, it will open this dat file, read line by line.
When it hits the string I'm searching for (e.g. "First"), the program
will know that the next line will be the variables to be stored. Are
there any C function to read file line by line? Please give me some
clue. Thanks a lot.

Abby.


As others have mentioned, fgets() is a good starting point, but it
needs some supporting logic to handle various errors and edge
conditions. If you *know* that your input file will always be
well-formed and that all lines will always be less than so many
characters long, then you don't need too much else, but to handle the
general case of unknown line length, premature EOF, and the like, you
need to do some additional work.

To convert your data values from strings to ints, use strtol().
Nov 13 '05 #41

This discussion thread is closed

Replies have been disabled for this discussion.