473,473 Members | 1,511 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Help with a progam

Hi guys!

I am trying to do an excercise from my C book, which coincidently is very
similar to the one in the recent "program" thread.

Task: Write a program that uses redirection to accept input from a disk
file,
counts the number of times the first three letters of the alphabet (a, b,
c, and A, B, C)
occur in the file.

Below is my attempt:
==========================================
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000 /*Maximum number of characters in the file */

int main( void)
{
char *ptr;
int count,
ctra = 0,
ctrb = 0,
ctrc = 0;

ptr = malloc(1000 * sizeof(char));
gets(ptr);
for (count = 0; count < MAX; count++) {
if( ptr[count] == 'a' || ptr[count] == 'A')
ctra++;
if( ptr[count] == 'b' || ptr[count] == 'B')
ctrb++;
if( ptr[count] == 'c' || ptr[count] == 'C')
ctrc++;
}
printf("ctra = %d\n", ctra);
printf("ctrb = %d\n", ctrb);
printf("ctrc = %d\n", ctrc);
free(ptr);
return 0;
}
==========================================
Problem: This works fine only if the maximum number of characters in
input.txt
is known(less than 1000).

I've tried including:

=======================
while ((ch = getchar()) != EOF) {
ctr++;
}
========================

The reason for this is so that I can use ctr in a malloc to
allocate enough memory to get all the characters in the file.

ie. ptr = malloc(ctr * sizeof(char));
gets(ptr);

However, because getchar *got* all the characters from stdin, the statement
gets(ptr) gets *nothing* from stdin.

I've been working on this for 2 days. It's driving me NUTTTSSSSS!!!
Can someone please give me a hint or 2?

Thanks in advance guys! Love your work!

Buck.

--
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Nov 14 '05 #1
13 2005

[..]
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 1000 /*Maximum number of characters in the file */

int main( void)
{
char *ptr;
int count,
ctra = 0,
ctrb = 0,
ctrc = 0;

ptr = malloc(1000 * sizeof(char));
if ( !ptr )
{
perror ( "Malloc" );
exit ( EXIT_FAILURE );
}
gets(ptr);
gets() is dangerous. Use fgets(3), instead.
for (count = 0; count < MAX; count++) {
if( ptr[count] == 'a' || ptr[count] == 'A')
ctra++;
if( ptr[count] == 'b' || ptr[count] == 'B')
ctrb++;
if( ptr[count] == 'c' || ptr[count] == 'C')
ctrc++;
}
I would prefer this instead:

/* You said redirection? */
while ( fgets ( ptr, MAX, stdin ) )
{
char *a;

a = ptr;
while ( *a )
{
if ( toupper ( *a ) == 'A' )
ctra++;

if ( toupper ( *a ) == 'B' )
ctrb++;

if ( toupper ( *a ) == 'C' )
ctrc++;

a++;
}
} printf("ctra = %d\n", ctra);
printf("ctrb = %d\n", ctrb);
printf("ctrc = %d\n", ctrc);
free(ptr);
return 0;
}
==========================================
Problem: This works fine only if the maximum number of characters in
input.txt
is known(less than 1000).


I guess this is because of gets ()!

[..]
--
Vijay Kumar R Zanvar
My Home Page - http://www.geocities.com/vijoeyz/
Nov 14 '05 #2

"Buck Rogers" <wh*@cares.com.au> wrote in message
news:op**************@news.ozemail.com.au...
Hi guys!

I am trying to do an excercise from my C book, which coincidently is very
similar to the one in the recent "program" thread.

Task: Write a program that uses redirection to accept input from a disk
file,
counts the number of times the first three letters of the alphabet (a, b,
c, and A, B, C)
occur in the file.

Below is my attempt:
==========================================
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000 /*Maximum number of characters in the file */

int main( void)
{
char *ptr;
int count,
ctra = 0,
ctrb = 0,
ctrc = 0;

ptr = malloc(1000 * sizeof(char));
gets(ptr);
for (count = 0; count < MAX; count++) {
if( ptr[count] == 'a' || ptr[count] == 'A')
ctra++;
if( ptr[count] == 'b' || ptr[count] == 'B')
ctrb++;
if( ptr[count] == 'c' || ptr[count] == 'C')
ctrc++;
}
printf("ctra = %d\n", ctra);
printf("ctrb = %d\n", ctrb);
printf("ctrc = %d\n", ctrc);
free(ptr);
return 0;
}
==========================================
Problem: This works fine only if the maximum number of characters in
input.txt
is known(less than 1000).

I've tried including:

=======================
while ((ch = getchar()) != EOF) {
ctr++;
}
========================

The reason for this is so that I can use ctr in a malloc to
allocate enough memory to get all the characters in the file.

ie. ptr = malloc(ctr * sizeof(char));
gets(ptr);

However, because getchar *got* all the characters from stdin, the statement gets(ptr) gets *nothing* from stdin.

I've been working on this for 2 days. It's driving me NUTTTSSSSS!!!
Can someone please give me a hint or 2?

Thanks in advance guys! Love your work!

Buck.


Here is some food for thought:

1) why dont you get each char, one at a time. This may not be fast, but it
will work.

2) If you want to load in a block at a time, use fread()

3) If you want to load the complete file in at once, then look at fseek()
and ftell() to get the file size. I believe that this is only reliably
portable for non-binary files, but I could be mistaken.

HTH
Allan
Nov 14 '05 #3
Buck Rogers wrote:
Hi guys!

I am trying to do an excercise from my C book, which coincidently is very
similar to the one in the recent "program" thread.

Task: Write a program that uses redirection to accept input from a disk
file,
counts the number of times the first three letters of the alphabet (a,
b, c, and A, B, C)
occur in the file.

Below is my attempt:
==========================================
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000 /*Maximum number of characters in the file */

int main( void)
{
char *ptr;
You are better off just have an int here,
int c; /* OK, a better name could be chosen */
int count,
ctra = 0,
ctrb = 0,
ctrc = 0;

ptr = malloc(1000 * sizeof(char));
gets(ptr);
just go through the file:
while ((c = fgetc(stdin)) != EOF) {
switch (c) /* using toupper or tolower would reduce
the number of cases */
{
case 'a':
case 'A': ctra++;
break;
case 'b':
case 'B': ctrb++;
break;
case 'c':
case 'C': ctrc++;
break;
default: break;
}
for (count = 0; count < MAX; count++) {
if( ptr[count] == 'a' || ptr[count] == 'A')
ctra++;
if( ptr[count] == 'b' || ptr[count] == 'B')
ctrb++;
if( ptr[count] == 'c' || ptr[count] == 'C')
ctrc++;
}
printf("ctra = %d\n", ctra);
printf("ctrb = %d\n", ctrb);
printf("ctrc = %d\n", ctrc);
free(ptr);
return 0;
}
==========================================
Problem: This works fine only if the maximum number of characters in
input.txt
is known(less than 1000).
See above.

I've tried including:

=======================
while ((ch = getchar()) != EOF) {
ctr++;
}
========================

The reason for this is so that I can use ctr in a malloc to
allocate enough memory to get all the characters in the file.

ie. ptr = malloc(ctr * sizeof(char));
gets(ptr);
Even if you wanted all the characters in the file, using gets() is not the
way to do it. First, gets() is inherently evil. At least use fgets()
instead. But gets() will not get all the text in the file, but just the
first line. You would still need a loop. fread() is the the way to fill a
buffer, but is unnecessary for your exercise, since the input stream will
be buffered, anyway.

However, because getchar *got* all the characters from stdin, the statement
gets(ptr) gets *nothing* from stdin.


See above.
--
Martin Ambuhl
Nov 14 '05 #4
On Wed, 21 Jan 2004 20:46:59 +1100
Buck Rogers <wh*@cares.com.au> wrote:
Hi guys!

I am trying to do an excercise from my C book, which coincidently is very
similar to the one in the recent "program" thread.

Task: Write a program that uses redirection to accept input from a disk
file,
counts the number of times the first three letters of the alphabet (a, b,
c, and A, B, C)
occur in the file.

Below is my attempt:
==========================================
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000 /*Maximum number of characters in the file */

int main( void)
{
char *ptr;
int count,
ctra = 0,
ctrb = 0,
ctrc = 0;

ptr = malloc(1000 * sizeof(char));
gets(ptr);
for (count = 0; count < MAX; count++) {
if( ptr[count] == 'a' || ptr[count] == 'A')
ctra++;
if( ptr[count] == 'b' || ptr[count] == 'B')
ctrb++;
if( ptr[count] == 'c' || ptr[count] == 'C')
ctrc++;
}
printf("ctra = %d\n", ctra);
printf("ctrb = %d\n", ctrb);
printf("ctrc = %d\n", ctrc);
free(ptr);
return 0;
}
==========================================
Problem: This works fine only if the maximum number of characters in
input.txt
is known(less than 1000).

I've tried including:

=======================
while ((ch = getchar()) != EOF) {
ctr++;
}
========================

The reason for this is so that I can use ctr in a malloc to
allocate enough memory to get all the characters in the file.

ie. ptr = malloc(ctr * sizeof(char));
gets(ptr);

However, because getchar *got* all the characters from stdin, the statement
gets(ptr) gets *nothing* from stdin.


Instead of setting an arbitrary limit to the number of characters,
or trying to figure out the exact number of characters before
processing them, consider this option; ignoring the number of
characters and just read until the end of file, i.e.:

while ((ch = getchar()) != EOF) {
/* if ch is A or a, increment ctra */
/* if ch is B or b, ... */ }

Note that although ch is getting chars for you to examine, it
is also going to get EOF as well, which is _not_ a char, but
an int, therefore ch should be declared as an int.

--
donLouis
Nov 14 '05 #5

"Buck Rogers" <wh*@cares.com.au> wrote in message
news:op**************@news.ozemail.com.au...
Hi guys!

I am trying to do an excercise from my C book, which coincidently is very
similar to the one in the recent "program" thread.

Task: Write a program that uses redirection to accept input from a disk
file,
counts the number of times the first three letters of the alphabet (a, b,
c, and A, B, C)
occur in the file.

Below is my attempt:
==========================================
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000 /*Maximum number of characters in the file */

int main( void)
{
char *ptr;
int count,
ctra = 0,
ctrb = 0,
ctrc = 0;

ptr = malloc(1000 * sizeof(char));
gets(ptr);
for (count = 0; count < MAX; count++) {
if( ptr[count] == 'a' || ptr[count] == 'A')
ctra++;
if( ptr[count] == 'b' || ptr[count] == 'B')
ctrb++;
if( ptr[count] == 'c' || ptr[count] == 'C')
ctrc++;
}
printf("ctra = %d\n", ctra);
printf("ctrb = %d\n", ctrb);
printf("ctrc = %d\n", ctrc);
free(ptr);
return 0;
}
==========================================
Problem: This works fine only if the maximum number of characters in
input.txt
is known(less than 1000).

I've tried including:

=======================
while ((ch = getchar()) != EOF) {
ctr++;
}
========================

The reason for this is so that I can use ctr in a malloc to
allocate enough memory to get all the characters in the file.

ie. ptr = malloc(ctr * sizeof(char));
gets(ptr);

However, because getchar *got* all the characters from stdin, the statement gets(ptr) gets *nothing* from stdin.

I've been working on this for 2 days. It's driving me NUTTTSSSSS!!!
Can someone please give me a hint or 2?

Thanks in advance guys! Love your work!

Buck.

If you insist on reading the file into memory first (rather than using
getchar() which is a better solution with stdin) then you can alway use
realloc() to increase the size of the memory buffer as required.

Also don't use gets() or fgets() since this will only read up to the first
newline character and thus you might loose alot of your data. Use fread()
instead - something like this...

#include <stdio.h>
#include <stdlib.h>
#define MAX 1000 /*Maximum number of characters to read each timee */

int main( void)
{
char *ptr;
int count,ctra = 0,ctrb = 0,ctrc = 0;
int bytes_read=MAX,i;

for(i=0;bytes_read==MAX;i++) {
if(i==0)
ptr = malloc(MAX * sizeof(char));
else
ptr=realloc(ptr,MAX*(i+1)*sizeof(char));

bytes_read=fread(ptr+MAX*i,1,MAX,stdin);
printf("bytes_read=%d\n",bytes_read);
for (count = 0; count < bytes_read; count++) {
if( ptr[count] == 'a' || ptr[count] == 'A')
ctra++;
if( ptr[count] == 'b' || ptr[count] == 'B')
ctrb++;
if( ptr[count] == 'c' || ptr[count] == 'C')
ctrc++;
}
}
printf("ctra = %d\n", ctra);
printf("ctrb = %d\n", ctrb);
printf("ctrc = %d\n", ctrc);
free(ptr);
return 0;
}

Nov 14 '05 #6
Sean Kenwrick wrote:
{
if( ptr[count] == 'a' || ptr[count] == 'A')
ctra++;
if( ptr[count] == 'b' || ptr[count] == 'B')
ctrb++;
if( ptr[count] == 'c' || ptr[count] == 'C')
ctrc++;
}


A switch with the lower case cases falling through to the upper,
would be perfect there. As it is, when your code finds an 'a',
it keeps checking to see if the character, is also a 'b' and a 'c'.

--
pete
Nov 14 '05 #7

"pete" <pf*****@mindspring.com> wrote in message
news:40**********@mindspring.com...
Sean Kenwrick wrote:
{
if( ptr[count] == 'a' || ptr[count] == 'A')
ctra++;
if( ptr[count] == 'b' || ptr[count] == 'B')
ctrb++;
if( ptr[count] == 'c' || ptr[count] == 'C')
ctrc++;
}


A switch with the lower case cases falling through to the upper,
would be perfect there. As it is, when your code finds an 'a',
it keeps checking to see if the character, is also a 'b' and a 'c'.

--
pete

Yeh, this code was from the OPs program - I only changed the bits relating
to fread() and realloc().

I also forgot to add an offset to ptr after each realloc, something like
like this:

ch= (ptr+(1000)*(i+1))[count];

switch(ch){
case 'a':
case 'A':
...
}

Sean

Nov 14 '05 #8
On Wed, 21 Jan 2004 15:58:38 +0530, "Vijay Kumar R Zanvar"
<vi*****@hotpop.com> wrote in comp.lang.c:

[snip]
gets() is dangerous. Use fgets(3), instead.


First sentence above, absolutely true. Second sentence above,
nonsense and undefined behavior.

C has a function with this prototype:

char *fgets(char *s, int n, FILE *stream);

....calling it with a single integer argument produces undefined
behavior.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #9
Jack Klein <ja*******@spamcop.net> scribbled the following:
On Wed, 21 Jan 2004 15:58:38 +0530, "Vijay Kumar R Zanvar"
<vi*****@hotpop.com> wrote in comp.lang.c:
gets() is dangerous. Use fgets(3), instead.
First sentence above, absolutely true. Second sentence above,
nonsense and undefined behavior. C has a function with this prototype: char *fgets(char *s, int n, FILE *stream); ...calling it with a single integer argument produces undefined
behavior.


I don't think Vijay meant the (3) as in an integer argument. He meant
the section of the man page it appears on. Yes, man pages are off-
topic here, but Vijay probably didn't know that.

--
/-- Joona Palaste (pa*****@cc.helsinki.fi) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"And according to Occam's Toothbrush, we only need to optimise the most frequent
instructions."
- Teemu Kerola
Nov 14 '05 #10

"Joona I Palaste" <pa*****@cc.helsinki.fi> wrote in message
news:bu**********@oravannahka.helsinki.fi...
Jack Klein <ja*******@spamcop.net> scribbled the following:
On Wed, 21 Jan 2004 15:58:38 +0530, "Vijay Kumar R Zanvar"
<vi*****@hotpop.com> wrote in comp.lang.c:
gets() is dangerous. Use fgets(3), instead.

First sentence above, absolutely true. Second sentence above,
nonsense and undefined behavior.

C has a function with this prototype:

char *fgets(char *s, int n, FILE *stream);

...calling it with a single integer argument produces undefined
behavior.


I don't think Vijay meant the (3) as in an integer argument. He meant
the section of the man page it appears on. Yes, man pages are off-
topic here, but Vijay probably didn't know that.


True. This is what I meant, and also as a habit I wrote that way.

- Vijay
Nov 14 '05 #11
In <ht********************************@4ax.com> Jack Klein <ja*******@spamcop.net> writes:
On Wed, 21 Jan 2004 15:58:38 +0530, "Vijay Kumar R Zanvar"
<vi*****@hotpop.com> wrote in comp.lang.c:

[snip]
gets() is dangerous. Use fgets(3), instead.
First sentence above, absolutely true. Second sentence above,
nonsense and undefined behavior.


Neither nonsense, nor undefined behaviour, merely a common idiom among
Unix-literate people.
C has a function with this prototype:

char *fgets(char *s, int n, FILE *stream);

...calling it with a single integer argument produces undefined
behavior.


If a prototype declaration is in scope, there is no undefined behaviour:
calling fgets with a single integer argument *requires* a diagnostic.

But all this discussion is pointless, because the poster didn't write
fgets(3) inside a piece of C code, but inside a piece of English text.
Big difference!

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #12
> > gets() is dangerous. Use fgets(3), instead.

C has a function with this prototype:

char *fgets(char *s, int n, FILE *stream);

...calling it with a single integer argument produces undefined
behavior.


It isn't required to be a compile error?
(assuming that the prototype is in scope)
Nov 14 '05 #13
On Wed, 21 Jan 2004 10:29:28 -0000, "Allan Bruce"
<al*****@TAKEAWAYf2s.com> wrote:

"Buck Rogers" <wh*@cares.com.au> wrote in message
news:op**************@news.ozemail.com.au... (wants, actually unwisely, to alloc buffer for whole file)
Here is some food for thought:

1) why dont you get each char, one at a time. This may not be fast, but it
will work.

2) If you want to load in a block at a time, use fread()

3) If you want to load the complete file in at once, then look at fseek()
and ftell() to get the file size. I believe that this is only reliably
portable for non-binary files, but I could be mistaken.

It's not reliably portable at all, but it is somewhat *more* likely to
work for binary; ftell on text isn't even required to be a byte count.
FAQ 19.12.

An alternative, or fallback, is to malloc a buffer large enough for
"ordinary" or "typical" use, and realloc (geometrically rather than
linearly to keep the total cost from going quadratic) if (and
repeatedly while) needed.

- David.Thompson1 at worldnet.att.net
Nov 14 '05 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Patrick Reany | last post by:
I wrote a C++ progam nine years ago and I haven't been in C++ since then. I re-installed Visual C++ 4.0 on a Win98 machine and tried to compile the program value.cpp but I get the error message ...
9
by: tym | last post by:
HELP!!! I'm going round the twist with this... I have a VB6 application which is using DAO to access a database (Please - no lectures on ADO, I know what I'm doing with DAO!!) Ok, problem...
2
by: Gunnar Petersson | last post by:
Hi, I have some more complicated things (for me) that I want to do in an Access survey database. I'm totally new to VBA-syntax and I don't have time to dig into it to much. I would appreciate...
4
by: nick | last post by:
hi I'm tryin to write a program that keeps track of the contents of the clipboard to a textbox, but i keep getting "An unhandled exception of type 'System.NullReferenceException' occurred in...
1
by: beGentle-Learner | last post by:
I have a query which looks like this :"INSERT INTO demo (idperson, name)SELECT idperson,name FROM ptolemy_person WHERE idperson = @original" and I have declared a parameter in this way:...
0
by: hugo | last post by:
I need urgent help with this program: Using C, write a calendar progam so that the user provides only a year. The program should print a calendar for the given year to the file calendar.dat. The...
1
by: boatmoon | last post by:
I want to write a progam : random image (3 seconds will change ) with C# and aspx page. Please help me. Thanks
6
by: asif929 | last post by:
I have been trying to create this chess program from many hours and still couldn't figure out how to complete it. After consume all these efforts i come here for the first time for help. i would...
1
by: learningvb123 | last post by:
I have about 400 rows of data in Excel. Each Row is a record set. I want to read each cell in each row into VB6 (one row at a time) and then do calculations on the cells in the same row and then...
1
by: JVFord | last post by:
Hello. We were having trouble displaying our photos (inserted as OLE Objects) in our database using Access 2003. (you can think of it as a contacts database where it housed info on the person and...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.