armhold@topaz.rutgers.edu (George Armhold) (05/30/89)
I started using my C compiler today (Manx Aztec V3.6a), and I'm really frustrated with I/O. I have the K&R book, _Understanding C_ by Bruce Hunter, as well as the documentation that came with Manx. All three of them left me bewildered with the various file I/O conventions. There's open, fopen, creat, etc... Which do I use when? What about writing to the console? Can anyone recommend a GOOD book that explains the various methods of I/O and also points out differences between "standard" and "machine specific"? Also, here's some source I tried today. What I'm trying to do is simply copy one file to another. When I compile it, I get error 125 which means "too many subscripts or indirection on integer". It occurs wherever I mention argv[x]. #include <stdio.h> main(argc, argv) { int c; FILE *fp1, *fp2; if ((fp1=fopen(argv[1], "r"))==NULL) { printf("Can't open %s", argv[1]); exit(); } if ((fp2=fopen(argv[2], "w"))==NULL) { printf("Can't open %s", argv[2]); exit(); } while ((c=getc(fp1)!=EOF)) putc(fp2); } Thanks -George
deven@rpi.edu (Deven Corzine) (05/30/89)
In article <May.29.21.40.18.1989.8866@topaz.rutgers.edu> armhold@topaz.rutgers.edu (George Armhold) writes:
I started using my C compiler today (Manx Aztec V3.6a), and I'm really
frustrated with I/O.
Poor guy... you'll surely be baffled by Amiga Exec I/O...
Also, here's some source I tried today. What I'm trying to do is
simply copy one file to another. When I compile it, I get error 125
which means "too many subscripts or indirection on integer". It occurs
wherever I mention argv[x].
#include <stdio.h>
main(argc, argv)
{
[...]
This error has nothing to do with the I/O; you never declared what the
parameters rto main were, so the compiler assumed integer for both.
argc is an integer, but argv is a char **. You need to add a line
after main(argc,argv) but BEFORE the "{" which reads "char **argv;" or
"char *argv[];" (take your pick; they mean the same.) and you *should*
add right before it "int argc;" but you don't need to, since the
compiler will assume it.
It thought argv was an integer, and argv[x] was the indirection on
integer causing the error.
Deven
--
shadow@[128.113.10.2] <shadow@pawl.rpi.edu> Deven T. Corzine (518) 272-5847
shadow@[128.113.10.201] <shadow@acm.rpi.edu> 2346 15th St. Pi-Rho America
deven@rpitsmts.bitnet <userfxb6@rpitsmts> Troy, NY 12180-2306 <<tionen>>
"Simple things should be simple and complex things should be possible." - A.K.
armhold@topaz.rutgers.edu (George Armhold) (05/30/89)
Thanks to the many people who responded to my cries for help with C. Only a few hours after I posted, I receieved around 20 replies! Now I feel silly, of course declaring argv and argc was the problem! Thanks again. -George
grwalter@watmath.waterloo.edu (Fred Walter) (05/31/89)
In article <DEVEN.89May30033457@daniel.rpi.edu> deven@rpi.edu (Deven Corzine) writes: >In article <May.29.21.40.18.1989.8866@topaz.rutgers.edu> armhold@topaz.rutgers.edu (George Armhold) writes: >> I started using my C compiler today (Manx Aztec V3.6a), and I'm really >> frustrated with I/O. >argc is an integer, but argv is a char **. You need to add a line >after main(argc,argv) but BEFORE the "{" which reads "char **argv;" or >"char *argv[];" (take your pick; they mean the same.) and you *should* >add right before it "int argc;" As well, the following code segment has a problem... while ((c=getc(fp1)!=EOF)) putc(fp2); ^^^^^^^^^^ You really want to be using putc(c, fp2). (Not to mention adding spaces would increase the readability of your code IMHO). fred
Yuklung_Morris_Ng@cup.portal.com (05/31/89)
You haven't define the type of argc and argv on main(). Remember, main() is a
a function, not a particular program like Pascal.
Try this:
main(argc,argv)
int argc;
char *argv[];
{
......;
}
- Morris
doug@xdos.UUCP (Doug Merritt) (05/31/89)
In article <May.29.21.40.18.1989.8866@topaz.rutgers.edu> armhold@topaz.rutgers.edu (George Armhold) writes: > >Also, here's some source I tried today. What I'm trying to do is >simply copy one file to another. When I compile it, I get error 125 >which means "too many subscripts or indirection on integer". It occurs >wherever I mention argv[x]. Oh well, I may as well join the hundreds of others who will all point out the same problems. I usually resist but I feel like burning bandwidth for once: >main(argc, argv) >{ You need to declare the parameters here, like for instance: main(argc, argv) int argc; char **argv; > while ((c=getc(fp1)!=EOF)) > putc(fp2); There are two problems here...one is that the while() is misparenthesized, it should be: > while ((c=getc(fp1)) != EOF) As written it was doing (c = (getc(fp1) != EOF)), which always assigns either a zero or a one to 'c'. Second, you're not giving the right parameters, 'c' is missing from the call: putc(c, fp2); These are all pretty obvious bugs, so I suspect that your original frustration in not being sure which functions to use in the first place became a problem in itself. Pirsig called this a "gumption trap" in "Zen and the Art of Motorcycle Maintenence". The recommended cure is to stop, cool off, relax, and then go back to what you were doing. For various reasons (style, portability, forming bug-avoiding habits) you should also close the files before exiting, and also call exit explicitly: fclose(fp1); fclose(fp2); exit(0); The explicit exit provides a clean return code so that your programs could be used in your 'make' scripts. For the same reason, your error exits should give a non-zero exit code: if (...open fails...) exit(1); Or on the Amiga, perhaps: exit(10); Programming in C is fun once you get used to it. Doug -- Doug Merritt {pyramid,apple}!xdos!doug Member, Crusaders for a Better Tomorrow Professional Wildeyed Visionary "Welcome to Mars; now go home!" (Seen on a bumper sticker off Phobos)
dhesi@bsu-cs.bsu.edu (Rahul Dhesi) (05/31/89)
In article <365@xdos.UUCP> doug@xdos.UUCP (Doug Merritt) writes: > putc(c, fp2); and > fclose(fp1); May I respectfully suggest error-checking: if (putc(c, fp2) == EOF) ... handle error ... And yes, even fclose! if (fclose(fp1) == EOF) ... handle error ... It seems like overkill, but not detecting a full device is a *very* common bug in C programs. (However, a possible optimization is to call ferror() just once before the output stream is closed instead of testing the value from putc all the time.) -- Rahul Dhesi <dhesi@bsu-cs.bsu.edu> UUCP: ...!{iuvax,pur-ee}!bsu-cs!dhesi Career change search is on -- ask me for my resume
pat@mirror.TMC.COM (06/01/89)
/* Written 9:40 pm May 29, 1989 by armhold@topaz.rutgers.edu in mirror:comp.lang.c */ /* ---------- "C problems" ---------- */ >I started using my C compiler today (Manx Aztec V3.6a), and I'm really >frustrated with I/O. I have the K&R book, _Understanding C_ by Bruce >Hunter, as well as the documentation that came with Manx. All three of >them left me bewildered with the various file I/O conventions. There's >open, fopen, creat, etc... Which do I use when? What about writing to >the console? Can anyone recommend a GOOD book that explains the >various methods of I/O and also points out differences between >"standard" and "machine specific"? What I think that you should do, since it sounds like you are still learning, is to use the higher level functions like fopen(), fclose(), fscanf(), and such. These functions take care of the needs for the I/O stream (with buffer allocation and such) for you and in that way while you are learning you don't have to be bogged down with the sordid details of I/O. As you progress and understand how the pointers work and how to safely allocate memory and other needed things, then you can get into lower level I/O with open, write, and things along that nature. If you are learning, be patient, those pointers can be a b***h! Also: >Also, here's some source I tried today. What I'm trying to do is >simply copy one file to another. When I compile it, I get error 125 >which means "too many subscripts or indirection on integer". It occurs >wherever I mention argv[x]. Whenever you define a function (and main() IS a function) you must declare the types of the arguments. If you don't then the compiler will (at best) default them to integers. This is where you get "too many subscripts or indirection on integer." Here's how you correct it: #include <stdio.h> main(argc, argv) int argc; char **argv; /* since you are learning it may be easier to understand this syntax better by defining it as: char *argv[] */ { int c; FILE *fp1, *fp2; ___subscript on an integer before fix. / if ((fp1=fopen(argv[1], "r"))==NULL) { printf("Can't open %s", argv[1]); exit(); } . . . } Good luck, George.
bill@twwells.uucp (T. William Wells) (06/02/89)
In article <7511@bsu-cs.bsu.edu> dhesi@bsu-cs.bsu.edu (Rahul Dhesi) writes:
: It seems like overkill, but not detecting a full device is a *very*
: common bug in C programs. (However, a possible optimization is to call
: ferror() just once before the output stream is closed instead of
: testing the value from putc all the time.)
Not quite: if you are going to do this, call fflush and then ferror
and you still need to check the results of fclose.
The fflush is needed so that the final write occurs; the fclose to
deal with things like failing to update directory entries.
(I suppose that the fclose should return error on a failure to write
the final buffer, thus eliminating the need for any checks other than
on the fclose, but several stdio implementations I've seen don't.)
Even better is to determine some points in your program that don't
occur too frequently, say <5% of the frequency of character writes,
and call ferror there as well. That way you catch the error after only
a few "file system full" messages get printed on the console rather
than 600 billion. :-) Frequently, a good place for a text file is
after each newline is written.
The message printing, BTW, is a serious problem with some UNIX's: a
good way to bring those systems to their knees is to get the kernel to
generate an unending series of messages. What happens is that, since
kernel message writing for these systems is polled, while a message is
being written, nothing other than interrupts are processed.
---
Bill { uunet | novavax } !twwells!bill
porges@inmet.UUCP (06/02/89)
>/* Written 3:34 am May 30, 1989 by deven@rpi.edu.UUCP in inmet:comp.lang.c */ #include <stdio.h> main(argc, argv) { [...] >This error has nothing to do with the I/O; you never declared what the >parameters rto main were, so the compiler assumed integer for both. >argc is an integer, but argv is a char **. You need to add a line >after main(argc,argv) but BEFORE the "{" which reads "char **argv;" or >"char *argv[];" (take your pick; they mean the same.) and you *should* >add right before it "int argc;" but you don't need to, since the >compiler will assume it. > Since noone else jumped in on this: char **argv and char *argv[] are NOT the same thing in delcarations. In the first case you have a pointer to a pointer to a character; you may in fact have a pointer to an array of pointer to characters. In the second case, however, you have an array of unknown size of character pointers on the argument stack. You almost certainly want char *argv[]. -- Don Porges porges@inmet.com {...mirror,ima}!inmet!porges
porges@inmet (06/03/89)
OK, nobody send me mail reminding me I'm wrong: I'm wrong. I was misled by the section 3 routines, execl and execle, that are called as if you put a series of string addresses on the stack. They call execve (on Sun Unix, at least) which pass in argc, argv, and envp, which are one integer and two pointers to pointers to characters. K&R version 1 explicitly states that char *x[] and char **x are identical IN FORMAL PARAMETERS. Sorry to have cluttered -- I tried to delete my posting but it was too late. -- Don Porges porges@inmet.com {...mirror,ima}!inmet!porges
karl@haddock.ima.isc.com (Karl Heuer) (06/03/89)
In article <236100015@mirror> pat@mirror.TMC.COM writes: >char **argv; /* since you are learning it may be easier to understand > this syntax better by defining it as: char *argv[] */ On the other hand, since this use of [] is a special case which exists nowhere else in the language (it works *only* for formal arguments), it may be less confusing to stick with "char **argv" after all. (Just my opinion. Decide for yourself.) Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
ark@alice.UUCP (Andrew Koenig) (06/05/89)
In article <124200016@inmet>, porges@inmet.UUCP writes: > Since noone else jumped in on this: char **argv and char *argv[] are NOT > the same thing in delcarations. True; except for declarations of formal parameters. That is: void f(x) char *x; { /* stuff */ } means precisely the same thing as void f(x) char x[]; { /* stuff */ } but void f() { char x[10]; } is different from void f() { char *x; } -- --Andrew Koenig ark@europa.att.com
les@chinet.chi.il.us (Leslie Mikesell) (06/06/89)
In article <13566@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: >>char **argv; /* since you are learning it may be easier to understand >> this syntax better by defining it as: char *argv[] */ >On the other hand, since this use of [] is a special case which exists nowhere >else in the language (it works *only* for formal arguments), it may be less >confusing to stick with "char **argv" after all. Umm, isn't that the same as: char *list[] = { "one", "two", "three", 0 }; which seems to work as a global definition. Argv is something similar so the char *argv[]; declaration makes sense. Les Mikesell
chris@mimsy.UUCP (Chris Torek) (06/07/89)
>In article <13566@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) >writes: >>... since this use of [] is a special case which exists nowhere >>else in the language (it works *only* for formal arguments), it may be >>less confusing to stick with "char **argv" after all. In article <8639@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell) writes: >Umm, isn't that the same as: > >char *list[] = { "one", "two", "three", 0 }; > >which seems to work as a global definition. No, it is not the same---it only looks the same to the casual observer. As Karl stated, `char *argv[]' is a special case because argv is a formal parameter. A C compiler is required silently to pretend that you actually wrote `char **argv'. That is: char *list[] = { 0, "hello", 0 }; void foo() { (void) main(2, list); } int main(int argc, char *argv[]) { if (argc > 1) puts(argv[1]); else foo(); return 0; } is treated by the compiler as though argv (and only argv) were declared with int main(int argc, char **argv) { The declaration for `list' is *not* altered, because it is not a formal parameter. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris