make a program that count lines in a text

J

jaswinder

I have a program which writes in the date and time into a txt file
everytime I
turn on my computer.

Ex:
Tue 08-03-2010 4:27:21.81p
Wed 08-04-2010 4:19:29.12p
Thu 08-05-2010 6:17:31.65p
Fri 08-06-2010 3:10:21.59p
Fri 08-06-2010 4:42:51.31p

I would like to make a program that counts each line and after it counts
all
the lines in the txt file it should tell me the total number of boots I
made to
date.

Here is what I have so far.

#include<stdio.h> // needed for IO functions
main()
{
int strlen(); // in strings.h but save time reading whole header
int lc=0; // define lc to be an int initialized to 0 (line count)
FILE *f; // pointer to a FILE (log.txt)
char bfr[96+1]; // string buffer w/ NULL terminater
char *bfrptr=&bfr[0]; // pointer to string buffer
f=fopen("log.txt","rb"); // setup FILE
do{
bfrptr=fgets(bfrptr,96,f); // pull a line from the file
if(strlen(bfr)>0) ++lc; // ignore empty lines
}while(!feof(f)); // stop at end of file
printf("Welcome you are entering OS from the %d time!\n",lc); //
display message
}


Any suggestion would be nice! A wrong answer is given.

Thank You.
 
N

Nick

jaswinder said:
I have a program which writes in the date and time into a txt file
everytime I
turn on my computer.

Ex:
Tue 08-03-2010 4:27:21.81p
Wed 08-04-2010 4:19:29.12p
Thu 08-05-2010 6:17:31.65p
Fri 08-06-2010 3:10:21.59p
Fri 08-06-2010 4:42:51.31p

I would like to make a program that counts each line and after it counts
all
the lines in the txt file it should tell me the total number of boots I
made to
date.

Here is what I have so far.

General point. Put some white space in. It costs nothing and makes
things a lot less readable.

People don't like // comments and they can cause problems when posting
articles to Usenet, but if you are going to use them, try to vaguely
align them.
#include<stdio.h> // needed for IO functions
main()
{
int strlen(); // in strings.h but save time reading whole header

In your lifetime it is unlikely to save in compilation time the amount
of time you spent typing that comment in. It has no effect on run time.
int lc=0; // define lc to be an int initialized to 0 (line count)

Anyone who knows any C at all knows what that line does, so the comment
is meaningless (except the bit in brackets, that's worth having (or call
your variable line_count in the first place)).
FILE *f; // pointer to a FILE (log.txt)
char bfr[96+1]; // string buffer w/ NULL terminater
char *bfrptr=&bfr[0]; // pointer to string buffer

// ditto all of the above comments. &bfr[0] is exactly the same as bfr.
In fact there is no need for bfrptr at all, just use bfr throughout (but
don't over-write it with the result of the fgets below).
f=fopen("log.txt","rb"); // setup FILE

You must check that this works. If the file can't be opened fp will be
NULL and horrible things will happen.
do{
bfrptr=fgets(bfrptr,96,f); // pull a line from the file

96 has now appeared twice. That's a good argument for using a
macro constant for it. You ought to check that fgets works (see
comment below).
if(strlen(bfr)>0) ++lc; // ignore empty lines

There's nothing wrong with this, but there are other and perhaps more
ideomatic ways to do it.
}while(!feof(f)); // stop at end of file

See the C FAQ for why this is a bad idea. Far better to check the
return value of fgets.
printf("Welcome you are entering OS from the %d time!\n",lc); //
display message
}


Any suggestion would be nice! A wrong answer is given.

Telling us what it is and why it is wrong would be nice. But I'm
guessing that it's one too high. Look in the FAQ for things about a
program printing the final line of a file twice.
 
I

Ike Naar

In your lifetime it is unlikely to save in compilation time the amount
of time you spent typing that comment in. It has no effect on run time.

What's worse, the declaration is wrong.
It should be ``size_t strlen(const char*);''.
This is a kind of error that can lead to subtle run-time bugs.
 
J

John Kelly

You must check that this works. If the file can't be opened fp will be
NULL and horrible things will happen.

Henry Spencer's 6th commandment is so tempting to ignore.
 
J

Jens Thoms Toerring

jaswinder said:
I have a program which writes in the date and time into a txt file
everytime I
turn on my computer.
Ex:
Tue 08-03-2010 4:27:21.81p
Wed 08-04-2010 4:19:29.12p
Thu 08-05-2010 6:17:31.65p
Fri 08-06-2010 3:10:21.59p
Fri 08-06-2010 4:42:51.31p
I would like to make a program that counts each line and after it counts
all
the lines in the txt file it should tell me the total number of boots I
made to
date.
Here is what I have so far.
#include<stdio.h> // needed for IO functions
main()

int main( void )

since main() is always supposed to return an int...
{
int strlen(); // in strings.h but save time reading whole header

Don't do that, and if you do you should at least use the correct
prototype which is

size_t strlen(const char *s);

How much time do you think it takes to read in a header file?
And how often do you recompile?
int lc=0; // define lc to be an int initialized to 0 (line count)
FILE *f; // pointer to a FILE (log.txt)
char bfr[96+1]; // string buffer w/ NULL terminater
char *bfrptr=&bfr[0]; // pointer to string buffer

No need for that extra variable, 'bfr' will do nicely as a
pointer to the (first element) of the array under most circum-
stances.
f=fopen("log.txt","rb"); // setup FILE

You better check the return value of fopen() - if it's
NULL you know that something went wrong and the program
probably should abort here, perhaps with an error message.
If the file couldn't be opened then nothing of the rest
will do anything useful (the way the program is written
it will even invoke undefined behaviour since the fgets()
won't do anything and you then call strlen() on an unini-
tialized buffer, which is a no-no...).
do{
bfrptr=fgets(bfrptr,96,f); // pull a line from the file

Why do you ask for 97 characters in the buffer when you allow
fgets() to write only 96? fgets() will always put a trailing
'\0' into it the buffer, so it will now stop after having read
only 95 characters from the file and use the last one for '\0'.
Just do

fgets( bfr, sizeof bfr, f );

and you should be fine (assuming there are really no lines with
more that 96 characters, including the '\n' at the end of the
line).
if(strlen(bfr)>0) ++lc; // ignore empty lines

Here are two problems: if fgets reached the end of the file it
returns NULL and you may now be counting the last line of the
file twice (since in that case 'bfr' won't be modified). And
then fgets() always returns the '\n' at the end of a line - if
there's no '\n' in what fgets() returned then the buffer you
passed it was too small to hold the complete line. And since
an empty line thus consists of just that character it will
have a strlen() of 1 and thus you false include it into your
line count.
}while(!feof(f)); // stop at end of file

Here it's a bit late for checking for feof(), you better should
have checked the return value of fgets() and bailed out of the
loop if it was NULL...
printf("Welcome you are entering OS from the %d time!\n",lc); //
display message

A nice program would now close the file it had opened (it's
not really necessary in this simple program but if this pro-
gram becomes a function in a larger program this would become
a real issue). And since main() is supposed to return an int
a line like

return 0;

would also be nice (0 tells the calling system that everything
worked out well).
Regards, Jens
 
K

Keith Thompson

jaswinder said:
I have a program which writes in the date and time into a txt file
everytime I
turn on my computer.

Ex:
Tue 08-03-2010 4:27:21.81p
Wed 08-04-2010 4:19:29.12p
Thu 08-05-2010 6:17:31.65p
Fri 08-06-2010 3:10:21.59p
Fri 08-06-2010 4:42:51.31p

I would like to make a program that counts each line and after it
counts all the lines in the txt file it should tell me the total
number of boots I made to date.

Here is what I have so far.

#include<stdio.h> // needed for IO functions
main()

Should be "int main(void)".
{
int strlen(); // in strings.h but save time reading whole header

Bad idea. The amount of time you save is not noticeable. The amount of
time you could waste because you declared strlen() incorrectly (the
correct declaration is "size_t strlen(const char *s);") could be
int lc=0; // define lc to be an int initialized to 0 (line count)
FILE *f; // pointer to a FILE (log.txt)
char bfr[96+1]; // string buffer w/ NULL terminater

You're assuming no more than 96 characters per line. This is probably a
valid assumption, but you should think about it.
char *bfrptr=&bfr[0]; // pointer to string buffer

You don't really need this variable.
f=fopen("log.txt","rb"); // setup FILE

And what if the fopen call fails? Check the result.
do{
bfrptr=fgets(bfrptr,96,f); // pull a line from the file

You might as well just write:

fgets(bfr, 96, f);

Or, better yet, look at the value returned by fgets() and do something
if it indicates a problem.
if(strlen(bfr)>0) ++lc; // ignore empty lines

The trailing '\n' will be stored in the buffer, so strlen() won't return
0 for "empty" lines.
}while(!feof(f)); // stop at end of file

If you're using feof(), you're probably doing it wrong. Read section 12
printf("Welcome you are entering OS from the %d time!\n",lc); //
display message

And you should have a "return 0;" at the end of your program.
}


Any suggestion would be nice! A wrong answer is given.

Telling us just what the wrong answer is would have been good.

You want to count lines. A line is a sequence of characters
terminated by a new-line ('\n'). So what you're really doing is
counting new-line characters. You could just read a character at
a time and count the '\n's. Don't worry about character-at-a-type
being slower than line-at-a-time; the system will read data in
chunks.

(Or, if you're on a Unix-like system, use the existing "wc" program.)
 
J

Jens Thoms Toerring

Another thing I forgot:

Why open the file in binary mode when it's a text file?

Regards, Jens
 
S

Seebs

Another thing I forgot:
Why open the file in binary mode when it's a text file?

I'm sorta wondering.

So far as I can tell, this program made every conceivable mistake.
Declaring something out of a standard header... incorrectly. Useless
comments on code which doesn't really do anything sane. +1s that don't
make any sense. Etcetera.

Is this real?

-s
 
J

Jens Thoms Toerring

I'm sorta wondering.
So far as I can tell, this program made every conceivable mistake.
Declaring something out of a standard header... incorrectly. Useless
comments on code which doesn't really do anything sane. +1s that don't
make any sense. Etcetera.
Is this real?

I have no problem assuming all of those are honest mistakes
of a person trying to learn C - some of them look like they
were made just because the OP has spend some time trying to
absorb the basics but didn't understand everything at the
first go. I'm rather sure I made similar mistakes when I
started (and probably still do when I start with a new pro-
gramming language;-)
Regards, Jens
 
J

John Kelly

I have no problem assuming all of those are honest mistakes
of a person trying to learn C

Or another daemon who likes to piss off Seebs and watch him dance. Why
not.
 
S

Seebs

Or another daemon who likes to piss off Seebs and watch him dance.

A lot of people would view a compulsion to do anything at all to get
a reaction from other people as unhealthy, not as a source of pride.

I think you could have done better, though. I actually just ignored it
originally.

-s
 
G

Geoff

Corrections made inline.

I have a program which writes in the date and time into a txt file
everytime I
turn on my computer.

Ex:
Tue 08-03-2010 4:27:21.81p
Wed 08-04-2010 4:19:29.12p
Thu 08-05-2010 6:17:31.65p
Fri 08-06-2010 3:10:21.59p
Fri 08-06-2010 4:42:51.31p

I would like to make a program that counts each line and after it counts
all
the lines in the txt file it should tell me the total number of boots I
made to
date.

Here is what I have so far.

Use whitespace! Compacting your source code doesn't make your program
faster, it doesn't make it compile faster and it makes it hard to read
and debug.
#include<stdio.h> // needed for IO functions int main(void)
{
int strlen(); // in strings.h but save time reading whole header
NEVER do this ^
Use the header intended for the purpose.
int lc=0; // define lc to be an int initialized to 0 (line count)
FILE *f; // pointer to a FILE (log.txt)
OK here. But line_count would have been better name for the variable.
Let code document itself, terse C is not fast C.
char bfr[96+1]; // string buffer w/ NULL terminater
Define a constant for the size, in case you need to change the size
you only need to do it once. Using numeric constants is called using
magic numbers, you don't know where or why they occur. Using a
manifest constant like BUF_SIZE or BUF_LEN documents the intent.
char *bfrptr=&bfr[0]; // pointer to string buffer
Unnecessary variable.
f=fopen("log.txt","rb"); // setup FILE
Fails to check if fopen succeeded.
"rb" is a Microsoft extension. This makes the file "untranslated".
Your '\n' at the end of a text file will fail to detect blank lines.
strlen('\n') is greater than 0 on both linux and Windows.
If you are expecting a text file, open it with "r" on Windows, Linux
won't care, but this is not strictly a C question.
do{
bfrptr=fgets(bfrptr,96,f); // pull a line from the file
Magic number here ^, error prone.
if(strlen(bfr)>0)
++lc; // ignore empty lines
Use indentation and separate your conditions from your statements so
you can set breakpoints on either line when debugging.

The above test fails to detect empty lines-.
}while(!feof(f)); // stop at end of file

Nick has already mentioned the C-FAQ.
printf("Welcome you are entering OS from the %d time!\n",lc); //
display message
}

Unclean termination, you didn't close the open file.
So here is an attempt at it:

(I pulled in the printf line to avoid line-wrap.)

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

#define BUF_LEN 97 /* max expected length of a line + 1 */

/* Open a log file for read, count the number of non-blank
lines and output the result.
*/
int main(void)
{
FILE *f;
int line_count = 0;
char bfr[BUF_LEN];

// setup FILE
if (f = fopen("log.txt","r")) {
while(1) {
if (fgets(bfr, BUF_LEN, f) == NULL) /* read a line */
break; // stop if fgets fails
if(strlen(bfr) > 1) /* ignore empty lines */
++line_count;
}
printf("Welcome, the system has been booted %d times!\n", line_count);
fclose(f);
}
}

Input (log.txt):

Tue 08-03-2010 4:27:21.81p
Wed 08-04-2010 4:19:29.12p

Thu 08-05-2010 6:17:31.65p
Fri 08-06-2010 3:10:21.59p
Fri 08-06-2010 4:42:51.31p

Output:
Welcome, the system has been booted 5 times!

A more robust blank line detection would not merely depend on strlen()
but would be able to detect lines like space-space-return, etc. which
are "blank" but won't pass the test above. I'm sure you can solve this
problem on your own.
 
O

osmium

jaswinder said:
I have a program which writes in the date and time into a txt file
everytime I
turn on my computer.

Ex:
Tue 08-03-2010 4:27:21.81p
Wed 08-04-2010 4:19:29.12p
Thu 08-05-2010 6:17:31.65p
Fri 08-06-2010 3:10:21.59p
Fri 08-06-2010 4:42:51.31p

I would like to make a program that counts each line and after it counts
all
the lines in the txt file it should tell me the total number of boots I
made to
date.

Here is what I have so far.

#include<stdio.h> // needed for IO functions
main()
{
int strlen(); // in strings.h but save time reading whole header
int lc=0; // define lc to be an int initialized to 0 (line count)
FILE *f; // pointer to a FILE (log.txt)
char bfr[96+1]; // string buffer w/ NULL terminater
char *bfrptr=&bfr[0]; // pointer to string buffer
f=fopen("log.txt","rb"); // setup FILE
do{
bfrptr=fgets(bfrptr,96,f); // pull a line from the file

I don't see any logic to read a line. I see logic to read 96 characters, if
that happens to be a line, fine business.. I lean towards changing the code
instead of the comment. I would open the file in text mode, just on general
principles.
 
K

Keith Thompson

Geoff said:
On Tue, 17 Aug 2010 21:09:19 +0000 (UTC), jaswinder

Fails to check if fopen succeeded.
"rb" is a Microsoft extension. This makes the file "untranslated".

No, it's not a Microsoft extension; it's standard C. It opens a binary
file for reading. (On Unix-like systems, there's no real distinction
between binary and text files.)

It's unlikely that "log.txt" is a binary file.
Your '\n' at the end of a text file will fail to detect blank lines.
strlen('\n') is greater than 0 on both linux and Windows.

strlen('\n') is a constraint violation (assuming a proper visible
declaration of strlen).

strlen("\n") == 1 on any system.
If you are expecting a text file, open it with "r" on Windows, Linux
won't care, but this is not strictly a C question.

This is better stated as:

If you are expecting a text file, open it with "r".

[...]
Unclean termination, you didn't close the open file.

Open files are automatically closed on program termination. But yes,
closing it yourself (and checking that the fclose() call succeeded)
is a good idea.

[snip]
 
G

Geoff

/* BEGIN boot_count.c output */

Welcome, the system has been booted 5 times!

/* END boot_count.c output */



/* BEGIN boot_count.c */

#include <stdio.h>

int main(void)
{
long unsigned boot_count = 0;
char *fn = "log.txt";
FILE *fp = fopen(fn,"r");

if (fp != NULL) {
int rc;

do{
rc = getc(fp);
if (rc == '.') {
++boot_count;
}
} while (rc != EOF);
fclose(fp);
} else {
printf("Problem with fopen(%s, \"r\")", fn);
}
puts("\n/* BEGIN boot_count.c output */\n");
printf("Welcome, the system has been booted %lu times!\n",
boot_count);
puts("\n/* END boot_count.c output */\n");
return 0;
}

/* END boot_count.c */

Even better. No string.h at all. :)
 
M

Malcolm McLean

Any suggestion would be nice! A wrong answer is given.
You need to start thinking in more of a structured programming way.

Counting the lines in a text file is a natural unit. Many programs
might need to do this. The name of the file isn't important to the
function.

so

int countlines(char *filename)
{
/* code goes here */
}

What if you can't open the file or have an IO error? Return -1.
What if the file has a last line not terminated by a newline, or has
trailing blank lines? You need to decide, there's no obvious right
answer for this.

Once the function is written you can hardcode the file path into
main() if that is appropriate.
 
N

Nick Keighley

On Tue, 17 Aug 2010 21:09:19 +0000 (UTC), jaswinder

So here is an attempt at it:

(I pulled in the printf line to avoid line-wrap.)

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

#define BUF_LEN 97 /* max expected length of a line + 1 */

/* Open a log file for read, count the number of non-blank
   lines and output the result.
*/
int main(void)
{
    FILE *f;
    int line_count = 0;
    char bfr[BUF_LEN];

    // setup FILE
    if (f = fopen("log.txt","r")) {
        while(1) {

I don't like unnecessary "infinite" loops. I'll use an infinite loop
and a break if I think it fits the problem. But in this case it
doesn't
            if (fgets(bfr, BUF_LEN, f) == NULL) /* read a line */
                break; // stop if fgets fails
            if(strlen(bfr) > 1)  /* ignore empty lines */
                ++line_count;
        }
printf("Welcome, the system has been booted %d times!\n", line_count);
        fclose(f);
    }

}

I've fiddled with the layout and coding conventions. I'd probably
output something when the file failed to open.

#include <stdlib.h> /* EXIT_FAILURE */
#include <stdio.h>
#include <string.h>

#define BUF_LEN 97 /* max expected length of a line + 1 */


/* Open a log file for read, count the number of non-blank
lines and output the result.
*/
int main(void)
{
FILE *f;
int line_count = 0;
char bfr [BUF_LEN];

if ((f = fopen ("log.txt","r")) == NULL)
return EXIT_FAILURE;

while (fgets (bfr, BUF_LEN, f) != NULL)
if (strlen (bfr) > 1) /* ignore empty lines */
line_count++;

printf ("Welcome, the system has been booted %d times!\n",
line_count);
fclose(f);

return 0; /* you forgot this! */
}

Input (log.txt):

Tue 08-03-2010  4:27:21.81p
Wed 08-04-2010  4:19:29.12p

Thu 08-05-2010  6:17:31.65p
Fri 08-06-2010  3:10:21.59p
Fri 08-06-2010  4:42:51.31p

Output:
Welcome, the system has been booted 5 times!

I got the same result
 
R

rudra

I dont know about C...just stooped here to search somthing and find
your post. (L)Unix has the exact command wc. the source code is also
available. so you may search for it
 
E

Ersek, Laszlo

I would like to make a program that counts each line
if(strlen(bfr)>0) ++lc; // ignore empty lines


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

int
main(void)
{
long unsigned lno;
unsigned incr;

lno = 0LU;
incr = 0U;

{
int c;

while (EOF != (c = fgetc(stdin))) {
if ('\n' == c) {
lno += incr;
incr = 0U;
}
else {
incr = 1U;
}
}
}

return feof(stdin)
&& 0 <= fprintf(stdout, "%lu\n", lno + incr)
&& 0 == fflush(stdout)
? EXIT_SUCCESS : EXIT_FAILURE;
}

lacos
 
R

Rui Maciel

jaswinder said:
I have a program which writes in the date and time into a txt file
everytime I
turn on my computer.

Ex:
Tue 08-03-2010 4:27:21.81p
Wed 08-04-2010 4:19:29.12p
Thu 08-05-2010 6:17:31.65p
Fri 08-06-2010 3:10:21.59p
Fri 08-06-2010 4:42:51.31p

I would like to make a program that counts each line and after it counts
all
the lines in the txt file it should tell me the total number of boots I
made to
date.
<snip/>

Just as a side note, if you happen to use a unix-like operating system then you already have a
program that does that, which is wc (short for word count). For example:

<example>
rui@kubuntu:~$ cat test.txt
Tue 08-03-2010 4:27:21.81p
Wed 08-04-2010 4:19:29.12p
Thu 08-05-2010 6:17:31.65p
Fri 08-06-2010 3:10:21.59p
Fri 08-06-2010 4:42:51.31p
rui@kubuntu:~$ wc -l test.txt
5 test.txt
</example>



Hope this helps,
Rui Maciel
 

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,829
Messages
2,569,737
Members
45,521
Latest member
maryb

Latest Threads

Top