Program not giving any output

E

Eric Sosman

On Sun, 07 Nov 2010 17:55:55 -0500, Eric Sosman

...

That's not a new bug. The OP's original code would have left the
initial 'o' as an 'o'.

The new bug (one of them) shows up just after the part
you snipped.
 
M

Maxx

Maxx said:
Here i have a program which was supposed to do the following:
Example INPUT:::
Dolorian refused to release the
lyrics for the track 'A Part Of Darkness'
on 'When All The Laughter Has Gone',
and several parts of the lyrics on almost
Example OUTPUT:::::
Dolorian refused to release the
Lyrics for the track 'A Part Of Darkness'
On 'When All The Laughter Has Gone',
And several parts of the lyrics on almost
What this program does is basically checks the first letter of every
line and changes it to upper case.
Here is the program:::::
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define BUFFER     5000

There is no obvious need to store a large number of anything in this
program.  It's a good exercise to re-think it so that the data you need
to store is unrelated to how long the input or input lines might be.
int main(int argc, char **argv)
{
   FILE *fp;
   int a[BUFFER];
   int ch,*p=a,*c=a;

These are not very helpful names.
   if((fp=fopen(argv[1],"a")) == NULL)

What do you think "a" does here?  If you are not sure, look it up.  I
could tell you, but you'll need to look up other stuff tomorrow, so find
some book or on-line reference now and be prepared.

But there are other points.  What happens if argc is zero or one?  Why
limit this program to files that can be named an opened?  That might
have been part of the specification (it's not at all clear) but if not,
it would be better to make this program a filter: one that (at least
when no arguments are supplied) reads stdin and writes the modified data
to stdout.
   {
           fprintf(stderr,"%s can't open file %s",argv[0],argv[1]);
           exit(1);
   }
   while((ch=getc(fp))!=EOF)
   {
           *p++=ch;

Add more white space to your code!  What happens when 'p' runs off the
end of 'a'?
   }*p='\0';
   for(;*c!='\0';c++)

It's possible that 'c' can run past the end of you data.  Can you work
out how that can happen?
   {
           if(*c==10 || *c==13)

(1) C makes sure that system dependent line terminations are converted
into the single '\n' character (for text streams).  (2) Why write a
non-portable and mysterious number rather than '\n'?
           {
                   ++c;
                   if(islower(*c))
                   {
                           *c=toupper(*c);
                   }
           }
   }

Assuming that you don't run off the array, one thing you can be sure of
here is that *c is == 0 or the for loop would not have finished...
   while(*c++!='\0')

so this loop won't do anything at all.
   {
           putc(*c,fp);
   }
   fclose(fp);
   return 0;
}
It's get compiled with zero error/warning but when i run it against
any file it produces no output or change.The input remains the
same.please help i'm having tough time solving it.


I was actually hoping for it to work against quite large files, so i
set the BUFFER to 5000.
Here i'm trying to append some characters to a file, so i used file
mode "a".Yeah i've foolishly omitted the error check, for argc=0.

another mistake i learnt was not to check the bounds for a. p could
have easily run past the limit and that would have been a disaster.

An i was confused with that c. I thought as it was an integer so the
compiler would throw me an error if i tried to compare it against a
character(a error that i seldom encountered in Java). Thats why i 've
used the ascii values for carriage-return and line-feed to compare it
against the int. Thanks for your help, actually i've learnt a lot from
it.
 
M

Maxx

Here i have a program which was supposed to do the following:
Example INPUT:::
Dolorian refused to release the
lyrics for the track 'A Part Of Darkness'
on 'When All The Laughter Has Gone',
and several parts of the lyrics on almost
Example OUTPUT:::::
Dolorian refused to release the
Lyrics for the track 'A Part Of Darkness'
On 'When All The Laughter Has Gone',
And several parts of the lyrics on almost
What this program does is basically checks the first letter of every
line and changes it to upper case.
Here is the program:::::
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#define BUFFER     5000
int main(int argc, char **argv)
{
   FILE *fp;
   int a[BUFFER];
   int ch,*p=a,*c=a;
   if((fp=fopen(argv[1],"a")) == NULL)

     Do you know what "a" means here?  It means "open for appending."
You are opening a stream for *output* to the end of the file, not
for input of any kind.  You probably mean "r+", which means "open
for reading and updating."  A safer alternative might be to read
from one file and write another; "safer" because if your program
does something weird it won't have trashed the original input.

     (Also, it would be a good idea to check that argv[1] is actually
present before trying to use it.)
   {
           fprintf(stderr,"%s can't open file %s",argv[0],argv[1]);
           exit(1);
   }
   while((ch=getc(fp))!=EOF)
   {
           *p++=ch;
   }*p='\0';
   for(;*c!='\0';c++)
   {
           if(*c==10 || *c==13)

     Side-note: You probably mean '\n' and '\r' instead of
those mysterious magic numbers.  Furthermore, you don't need
to worry about the '\r' at all: C's text I/O streams always
use a single '\n' to mark the end of a line, regardless of
what's actually recorded in a file.
           {
                   ++c;
                   if(islower(*c))
                   {
                           *c=toupper(*c);
                   }
           }
   }

     At this moment in your program, where does `c' point?
With that in mind, how many times will the body of the next
loop execute?
   while(*c++!='\0')
   {
           putc(*c,fp);
   }
   fclose(fp);
   return 0;
}
It's get compiled with zero error/warning but when i run it against
any file it produces no output or change.The input remains the
same.please help i'm having tough time solving it.

     Side-note, this program is considerably more complicated (and
self-limited) than it needs to be to accomplish its stated task.
As you learn more, you'll see ways to simplify and improve it --
but right now, let's focus on the basics.

I wasn't aware of "r+" so i thought that "a" would accomplish the
desired task. and yeah i was actually trying to mean '\n' and '\r' but
i thought comparing characters against intgers would give me an error
so resorted to using those mysterious numbers.

And i was hoping that the c would point to the first character of the
new line.thanks for your help, it was great learning from the
mistakes...
 
M

Maxx

     Side-note, this program is considerably more complicated (and
self-limited) than it needs to be to accomplish its stated task.
As you learn more, you'll see ways to simplify and improve it --
but right now, let's focus on the basics.

I don't think this is what the op was looking for, but like, here is
what I came up with...

[cdalten@localhost oakland]$ more dol
Dolorian refused to release the
lyrics for the track 'A Part Of Darkness'
on 'When All The Laughter Has Gone',
and several parts of the lyrics on almost
[cdalten@localhost oakland]$
[cdalten@localhost oakland]$ more lotoup.c
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define PATH "/home/cdalten/oakland/dol"

int main(void)
{
  FILE *fp;
  char buf[BUFSIZ];

  if ((fp = fopen(PATH, "r")) == NULL) {
    fprintf(stderr, "Can't open input file\n");
    exit(EXIT_FAILURE);
  }

  while (fgets(buf, BUFSIZ, fp) != NULL) {
    printf("%c%s",toupper(buf[0]), &buf[1]);
  }

  printf("\n");

  fclose(fp);
  exit(EXIT_SUCCESS);}

[cdalten@localhost oakland]$ gcc -Wall -Wextra lotoup.c -o lotoup
[cdalten@localhost oakland]$ ./lotoup
Dolorian refused to release the
Lyrics for the track 'A Part Of Darkness'
On 'When All The Laughter Has Gone',
And several parts of the lyrics on almost
[cdalten@localhost oakland]$

Yeah yeah this is exactly what i was trying to achieve but failed
miserably...
 
K

Keith Thompson

Maxx said:
There is no obvious need to store a large number of anything in this
program.  It's a good exercise to re-think it so that the data you need
to store is unrelated to how long the input or input lines might be.
[snip]
   if((fp=fopen(argv[1],"a")) == NULL)

What do you think "a" does here?  If you are not sure, look it up.  I
could tell you, but you'll need to look up other stuff tomorrow, so find
some book or on-line reference now and be prepared.
[snip]

I was actually hoping for it to work against quite large files, so i
set the BUFFER to 5000.

What is the significance of the number 5000? A "large" file is going
to be *much* larger than that (megabytes or more).

The point is that, regardless of the size of the input file, you don't
need to store more than a few bytes at a time -- probably not more than
one.
Here i'm trying to append some characters to a file, so i used file
mode "a".Yeah i've foolishly omitted the error check, for argc=0.

Why are you appending to a file? Your problem description talks about
input and output.

[...]
An i was confused with that c. I thought as it was an integer so the
compiler would throw me an error if i tried to compare it against a
character(a error that i seldom encountered in Java). Thats why i 've
used the ascii values for carriage-return and line-feed to compare it
against the int. Thanks for your help, actually i've learnt a lot from
it.

"char" is an integer type in C.

When you read from a file in text mode, each end-of-line appears
as a '\n' character. Don't make any assumptions about the integer
value of '\n'.
 
J

J. J. Farrell

Maxx said:
... yeah i was actually trying to mean '\n' and '\r' but
i thought comparing characters against intgers would give me an error
so resorted to using those mysterious numbers.

Comparing chars against ints wouldn't give you an error (a warning
perhaps on some very unusual systems) but that wouldn't come into it
anyway - '\n' and '\r' are ints.
 
L

Lew Pitcher

I don't think this is what the op was looking for, but like, here is
what I came up with...

Ditto....

----------------------------cut------------------------------

/*
** capit.c - capitalize first letter of each input line
**
** Input: stdin
** Process: capitalize the first alphabetic character of
** each input line.
**
** If ALLOWLEADINGBLANKS is defined, only capitalize
** if letter is preceeded by zero or more whitespace;
** *DO NOT* capitalize if first letter is preceeded
** by non-whitespace.
** Output: stdout
*/

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

#define ALLOWLEADINGBLANKS 1

void capit(FILE *input, FILE *output)
{
int datum, linestart;

for (linestart = 1,datum = getc(input);datum != EOF;datum = getc(input))
{
if (linestart)
{
#ifdef ALLOWLEADINGBLANKS
for (;isblank(datum); datum = getc(input)) putc(datum,output);
#endif
if (islower(datum)) datum = toupper(datum);
}
putc(datum,output);
linestart = (datum == '\n' ? 1 : 0);
}
}

int main(void)
{
capit(stdin,stdout);
return EXIT_SUCCESS;
}

----------------------------cut------------------------------

/var/nfs/merlin/lpitcher/code/clc $ cc -o capit capit.c
/var/nfs/merlin/lpitcher/code/clc $ cat capit.txt
first line of the file, starts with lower case letter
line with lower case preceeded by whitespace
& another line
%line preceeded by something
two spaces
Line starts with upper case
Line starts with Upper case
& Line starts with something, then upper case
LINE WITH LOTS OF UPPER CASE
LINE WITH LOTS of UPPER CASE
abcdef
line that preceeds two newlines


line that follows two newlines
/var/nfs/merlin/lpitcher/code/clc $ ./capit <capit.txt
First line of the file, starts with lower case letter
Line with lower case preceeded by whitespace
& another line
%line preceeded by something
Two spaces
Line starts with upper case
Line starts with Upper case
& Line starts with something, then upper case
LINE WITH LOTS OF UPPER CASE
LINE WITH LOTS of UPPER CASE
Abcdef
Line that preceeds two newlines


Line that follows two newlines
/var/nfs/merlin/lpitcher/code/clc $ ./capit <capit.txt >capit.new.txt
/var/nfs/merlin/lpitcher/code/clc $ cat capit.new.txt
First line of the file, starts with lower case letter
Line with lower case preceeded by whitespace
& another line
%line preceeded by something
Two spaces
Line starts with upper case
Line starts with Upper case
& Line starts with something, then upper case
LINE WITH LOTS OF UPPER CASE
LINE WITH LOTS of UPPER CASE
Abcdef
Line that preceeds two newlines


Line that follows two newlines
/var/nfs/merlin/lpitcher/code/clc $
 
K

Keith Thompson

Lew Pitcher said:
int datum, linestart;
[...]
linestart = (datum == '\n' ? 1 : 0);
[...]

A minor style point: why not just write:

linestart = (datum == '\n');

?
 
L

Lew Pitcher

Lew Pitcher said:
int datum, linestart;
[...]
linestart = (datum == '\n' ? 1 : 0);
[...]

A minor style point: why not just write:

linestart = (datum == '\n');

?

No reason. I hadn't optimized my logic that far, yet.

<Aside>
Usually, my first cut at this sort of demo is pretty raw. I try to
write "verbose" code, so that I can make certain that the code expresses
the logic I'm trying to develop. Once I get a working version, I
start "compacting" the code. So, my first attempt was
if (datum == '\n')
linestart = 1;
else
linestart = 0;
and my first attempt at a "compacted" version was
linestart = (datum == '\n' ? 1 : 0);
Had I iterated my development and compacted again, I'd probably have hit on
your expression.
</Aside>
 
I

ImpalerCore

[...]>   int datum, linestart;

[...]
    linestart = (datum == '\n' ? 1 : 0);    

[...]

A minor style point: why not just write:

    linestart = (datum == '\n');

?

I prefer the 'condition ? 1 : 0' to emphasize that the value returned
is an integer rather than a boolean. I do this in particular when the
result will be an array index, or other numerical value. A recent
example that comes to mind would be something like:

\code snippet
static const int days_in_month_table[2][12] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};

typedef enum
{
JANUARY = 0;
...
DECEMBER = 11;
} month;

....

days = days_in_month_table[is_leap_year(2010) ? 1 : 0][NOVEMBER];
\endcode

The type of 'linestart' in the statement 'linestart = (datum == '\n')'
is of type 'int', and my personal preference would be to make the
integer assignment explicit. The main reason is that there isn't a
1-1 match between boolean expressions and their integer counterparts,
since any integer != 0 is interpreted as true. I don't have a problem
with people who use it, since I can read it just fine, but I still
prefer to avoid implicit boolean to int conversions in code that I
write.

Best regards,
John D.
 
I

ImpalerCore

In this example, "linestart" was being used a s a boolean value.  Its
value was only tested with if (linestart).

Good point. I didn't look closely enough at his example. In
retrospect I would go with KT's version then. I suppose I'm so used
to using 'bool' to declare boolean types that I autoregister 'int' to
conceptually represent integer numbers.

Best regards,
John D.
 
B

Ben Bacarisse

Lew Pitcher said:
Ditto....

----------------------------cut------------------------------

/*
** capit.c - capitalize first letter of each input line
**
** Input: stdin
** Process: capitalize the first alphabetic character of
** each input line.
**
** If ALLOWLEADINGBLANKS is defined, only capitalize
** if letter is preceeded by zero or more whitespace;
** *DO NOT* capitalize if first letter is preceeded
** by non-whitespace.
** Output: stdout
*/

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

#define ALLOWLEADINGBLANKS 1

void capit(FILE *input, FILE *output)
{
int datum, linestart;

for (linestart = 1,datum = getc(input);datum != EOF;datum = getc(input))
{
if (linestart)
{
#ifdef ALLOWLEADINGBLANKS
for (;isblank(datum); datum = getc(input)) putc(datum,output);
#endif
if (islower(datum)) datum = toupper(datum);
}
putc(datum,output);
linestart = (datum == '\n' ? 1 : 0);
}
}

The ALLOWLEADINGBLANKS version will go wrong when the input ends after
an initial blank. It's possible that such an input (as a text file) is
considered to trigger undefined behaviour, but prefer to handle them
since they are no rare "in the wild".

I would not normally comment on style but, since I'm posting, I'll
mention that I find

for (linestart = 1,datum = getc(input);datum != EOF;datum = getc(input))

a little odd. For one thing, linestart has nothing to do with the loop,
so I's initialise it to 1 in the declaration rather than here but, more
significantly,

while ((datum = getc(input)) != EOF)

is such a widely-know idiom, it took me while to grok yours as being the
same loop!
int main(void)
{
capit(stdin,stdout);
return EXIT_SUCCESS;
}
<snip>
 
M

Maxx

Maxx said:
Here i have a program which was supposed to do the following:
Example INPUT:::
Dolorian refused to release the
lyrics for the track 'A Part Of Darkness'
on 'When All The Laughter Has Gone',
and several parts of the lyrics on almost
Example OUTPUT:::::
Dolorian refused to release the
Lyrics for the track 'A Part Of Darkness'
On 'When All The Laughter Has Gone',
And several parts of the lyrics on almost
What this program does is basically checks the first letter of every
line and changes it to upper case.
Here is the program:::::
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define BUFFER     5000
There is no obvious need to store a large number of anything in this
program.  It's a good exercise to re-think it so that the data you need
to store is unrelated to how long the input or input lines might be.
[snip]
   if((fp=fopen(argv[1],"a")) == NULL)
What do you think "a" does here?  If you are not sure, look it up.  I
could tell you, but you'll need to look up other stuff tomorrow, so find
some book or on-line reference now and be prepared.
[snip]

I was actually hoping for it to work against quite large files, so i
set the BUFFER to 5000.

What is the significance of the number 5000?  A "large" file is going
to be *much* larger than that (megabytes or more).

The point is that, regardless of the size of the input file, you don't
need to store more than a few bytes at a time -- probably not more than
one.
Here i'm trying to append some characters to a file, so i used file
mode "a".Yeah i've foolishly omitted the error check, for argc=0.

Why are you appending to a file?  Your problem description talks about
input and output.

[...]
An i was confused with that c. I thought as it was an integer so the
compiler would throw me an error if i tried to compare it against a
character(a error that i seldom encountered in Java). Thats why i 've
used the ascii values for carriage-return and line-feed to compare it
against the int. Thanks for your help, actually i've learnt a lot from
it.

"char" is an integer type in C.

When you read from a file in text mode, each end-of-line appears
as a '\n' character.  Don't make any assumptions about the integer
value of '\n'.

--
Keith Thompson (The_Other_Keith) (e-mail address removed)  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"


I get it, i should read a few bytes at a time rather than set aside a
buffer of random size. And the integer confusion is also
resolved...thanks
 
K

Keith Thompson

Maxx said:
What is the significance of the number 5000?  A "large" file is going
to be *much* larger than that (megabytes or more).

The point is that, regardless of the size of the input file, you don't
need to store more than a few bytes at a time -- probably not more than
one.
[...]
I get it, i should read a few bytes at a time rather than set aside a
buffer of random size. And the integer confusion is also
resolved...thanks

Why "a few"? (Yes, I know I wrote "a few bytes at a time" myself;
I was being sloppy.)

The most obvious solution only reads one byte at a time.

And please trim quoted text when posting a followup. There's no need
to quote (and make your readers wade through) material that you're
not commenting on. I particular, don't quote signatures (the stuff
following the "-- " line) unless you're actually commenting on them.
Just be sure to keep the attribution lines ("So-and-so wrote:")
for any text you quote.
 

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
474,079
Messages
2,570,575
Members
47,207
Latest member
HelenaCani

Latest Threads

Top