string length questions related to fseek

S

sieg1974

Hi,

The function bellow returns the number of lines of a file.
The length of the char variable __Line is 256, and I think it would
allow me to store strings with up to 255 letters because the 256th
character would always be "0".
My question is why there is a segmentation fault when fseek tries to
read 255 characters from the file if the length of __Line is 256? And
it works fine when it reads up to 254 characters?

Thanks a lot,

Andre

int getNumberLines( const char * _fileName )
{
FILE * __File;
char __Line[ 256 ];
int __NumberLines = 0;

if( ( __File = fopen( _fileName, "r" ) ) == NULL )
return( -1 );

while( fgets( __Line, 254, __File ) )
__NumberLines++;

fclose ( __File );

return( __NumberLines );
}
 
B

Ben Pfaff

The function bellow returns the number of lines of a file.

....assuming that none of the lines are longer than 253
characters.
The length of the char variable __Line is 256, and I think it would
allow me to store strings with up to 255 letters because the 256th
character would always be "0".

'\0' actually but yes.
My question is why there is a segmentation fault when fseek tries to
read 255 characters from the file if the length of __Line is 256? And
it works fine when it reads up to 254 characters?

Your code doesn't make any calls to fseek().
int getNumberLines( const char * _fileName )
{
FILE * __File;
char __Line[ 256 ];
int __NumberLines = 0;

Identifiers beginning with _ are mostly reserved, and you
shouldn't use them. Identifiers beginning with __ are definitely
reserved and you should definitely not use them.

The rest of the code looks okay, although the style is odd. I
don't see cause for a segfault.
 
R

red floyd

sieg1974 said:
Hi,

The function bellow returns the number of lines of a file.
The length of the char variable __Line is 256, and I think it would
allow me to store strings with up to 255 letters because the 256th
character would always be "0".
My question is why there is a segmentation fault when fseek tries to
read 255 characters from the file if the length of __Line is 256? And
it works fine when it reads up to 254 characters?

Thanks a lot,

Andre

int getNumberLines( const char * _fileName )
{
FILE * __File;
char __Line[ 256 ];
int __NumberLines = 0;

if( ( __File = fopen( _fileName, "r" ) ) == NULL )
return( -1 );

while( fgets( __Line, 254, __File ) )
if (__Line[strlen(__Line)-1] == '\n')
__NumberLines++;

fclose ( __File );

return( __NumberLines );
}

I inserted a line in your code to handle lines longer than 254 characters.

However, why use fgets()? getc() is easier.

See below:


int getNumberLines(const char *fileName)
{
FILE *fp;
int c;

int numlines = 0;

if ((fp = fopen(fileName,"r")) == NULL)
return -1;

while ((c = getc(fp)) != EOF)
++numlines;
fclose(fp);

return numlines;
}
 
B

bowsayge

sieg1974 said to us:
Hi,

The function bellow returns the number of lines of a file.
The length of the char variable __Line is 256, and I think it would
allow me to store strings with up to 255 letters because the 256th
character would always be "0".
[...]

When you read using fgets, the line ends with a "\n\0" sequence
(on un*x) or "\r\n\0" (on Windows). If you're on unix, and you
read 255 data characters, the terminating chars of "\n\0" will
take you up to 257 characters required to store all the data.
 
S

sieg1974

Hi,

The function bellow returns the number of lines of a file.
The length of the char variable __Line is 256, and I think it would
allow me to store strings with up to 255 letters because the 256th
character would always be "0".
My question is why there is a segmentation fault when fseek tries to
read 255 characters from the file if the length of __Line is 256? And
it works fine when it reads up to 254 characters?

Thanks a lot,

Andre

int getNumberLines( const char * _fileName )
{
FILE * __File;
char __Line[ 256 ];
int __NumberLines = 0;

if( ( __File = fopen( _fileName, "r" ) ) == NULL )
return( -1 );

while( fgets( __Line, 254, __File ) )
__NumberLines++;

fclose ( __File );

return( __NumberLines );
}


Oops, I mean why there is a segmentation fault when fgets tries to
read 255 characters? And not when fseek tries ...

Sorry for that.

Andre
 
E

Eric Sosman

bowsayge said:
sieg1974 said to us:

Hi,

The function bellow returns the number of lines of a file.
The length of the char variable __Line is 256, and I think it would
allow me to store strings with up to 255 letters because the 256th
character would always be "0".

[...]

When you read using fgets, the line ends with a "\n\0" sequence
(on un*x) or "\r\n\0" (on Windows).

If the stream is opened in text mode (the default),
lines always[*] end with "\n\0", no matter what the
platform. It even works this way if the platform doesn't
use line-delimiting characters at all.

[*] Exception: On some platforms, the very last line
in the file might lack the '\n'.
> If you're on unix, and you
read 255 data characters, the terminating chars of "\n\0" will
take you up to 257 characters required to store all the data.

No, or at any rate not exactly. The second argument to
fgets() is the total size of the buffer, and fgets() will
not store anything at all outside the buffer. So, yes: a
line consisting of 255 alphabetic characters plus a newline
will need a 257-byte buffer, but fgets() already accounts
for the excess and the programmer needn't worry. Oh, and
another thing: That's a C feature, not a Unix feature.
 
K

Keith Thompson

Eric Sosman said:
bowsayge wrote: [...]
If the stream is opened in text mode (the default),
lines always[*] end with "\n\0", no matter what the
platform. It even works this way if the platform doesn't
use line-delimiting characters at all.

[*] Exception: On some platforms, the very last line
in the file might lack the '\n'.

Another exception: If the input line is longer than the buffer you've
provided, you'll get a partial line not ending with '\n' (but it will
always have the trailing '\0').
 
C

CBFalconer

sieg1974 said:
sieg1974 said:
The function bellow returns the number of lines of a file.
The length of the char variable __Line is 256, and I think it
would allow me to store strings with up to 255 letters because
the 256th character would always be "0".
My question is why there is a segmentation fault when fseek
tries to read 255 characters from the file if the length of
__Line is 256? And it works fine when it reads up to 254
characters?

int getNumberLines( const char * _fileName )
{
FILE * __File;
char __Line[ 256 ];
int __NumberLines = 0;

if( ( __File = fopen( _fileName, "r" ) ) == NULL )
return( -1 );

while( fgets( __Line, 254, __File ) )
__NumberLines++;

fclose ( __File );

return( __NumberLines );
}

Oops, I mean why there is a segmentation fault when fgets tries to
read 255 characters? And not when fseek tries ...

Possibly because you have interfered with the system namespace
with all those identifiers headed by "__".
 
E

Eric Sosman

Keith said:
Eric Sosman said:
bowsayge wrote:
[...]

If the stream is opened in text mode (the default),
lines always[*] end with "\n\0", no matter what the
platform. It even works this way if the platform doesn't
use line-delimiting characters at all.

[*] Exception: On some platforms, the very last line
in the file might lack the '\n'.


Another exception: If the input line is longer than the buffer you've
provided, you'll get a partial line not ending with '\n' (but it will
always have the trailing '\0').

True, the buffer might not contain the entire line --
but the line itself (except possibly the last) ends with
'\n' anyhow, and if you keep reading you'll come to it.

The main point is that the line terminator *as seen
by the C program* is always '\n', regardless of how the
supporting platform represents its lines. It's the duty
of the C library to mediate between the "internal" and
"external" representations when reading or writing text-
mode streams. The programmer need not anticipate and
write code for all the myriad line-storing conventions
that have been (and will yet be) invented.
 
E

Eric Sosman

CBFalconer said:
sieg1974 said:
sieg1974 said:
The function bellow returns the number of lines of a file.
The length of the char variable __Line is 256, and I think it
would allow me to store strings with up to 255 letters because
the 256th character would always be "0".
My question is why there is a segmentation fault when fseek
tries to read 255 characters from the file if the length of
__Line is 256? And it works fine when it reads up to 254
characters?

int getNumberLines( const char * _fileName )
{
FILE * __File;
char __Line[ 256 ];
int __NumberLines = 0;

if( ( __File = fopen( _fileName, "r" ) ) == NULL )
return( -1 );

while( fgets( __Line, 254, __File ) )
__NumberLines++;

fclose ( __File );

return( __NumberLines );
}

Oops, I mean why there is a segmentation fault when fgets tries to
read 255 characters? And not when fseek tries ...


Possibly because you have interfered with the system namespace
with all those identifiers headed by "__".

Suggested fix: Change `__File' to `__FILE__' and
change `__Line' to `__LINE__'. This is guaranteed to
make the segmentation faults go away. ;-)
 
C

CBFalconer

Eric said:
.... snip ...

If the stream is opened in text mode (the default),
lines always[*] end with "\n\0", no matter what the
platform. It even works this way if the platform doesn't
use line-delimiting characters at all.

[*] Exception: On some platforms, the very last line
in the file might lack the '\n'.

Only if you are receiving them into strings, when the '\0' is an
artifact of the string object. If you process the file char by
char, using fgetc, getc, getchar, etc. or even with scanf, no
extra '\0's appear. On many systems this is just as efficient as
using string input routines, and can give you very fine control.
ungetc() is very useful in making everything play together.

I know you know all this, but the above is for general benefit.
 
E

Eric Sosman

CBFalconer said:
Eric Sosman wrote:

... snip ...
If the stream is opened in text mode (the default),
lines always[*] end with "\n\0", no matter what the
platform. It even works this way if the platform doesn't
use line-delimiting characters at all.

[*] Exception: On some platforms, the very last line
in the file might lack the '\n'.


Only if you are receiving them into strings, when the '\0' is an
artifact of the string object. [...]

The original question concerned fgets(), despite
the slight misspelling in the sujbect line.
 
J

Joe Wright

CBFalconer said:
Eric Sosman wrote:

... snip ...
If the stream is opened in text mode (the default),
lines always[*] end with "\n\0", no matter what the
platform. It even works this way if the platform doesn't
use line-delimiting characters at all.

[*] Exception: On some platforms, the very last line
in the file might lack the '\n'.


Only if you are receiving them into strings, when the '\0' is an
artifact of the string object. If you process the file char by
char, using fgetc, getc, getchar, etc. or even with scanf, no
extra '\0's appear. On many systems this is just as efficient as
using string input routines, and can give you very fine control.
ungetc() is very useful in making everything play together.

I know you know all this, but the above is for general benefit.

Another 'general benefit' observation is that 'lines' are file
things and 'strings' are memory things. In the general case, there
are no strings in a text file (there are no '\0' characters).
fgets() will copy a line from the file into a memory buffer and add
a '\0' to it so that the buffer holds a string.
 

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,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top