| TIP: Click on subject to list as thread! | ANSI |
| echo: | |
|---|---|
| to: | |
| from: | |
| date: | |
| subject: | C |
RM> Hi Bob - this started out as a normal answer, but turned into
RM> THIS. Ah well, if I gotta stay home cos I'm crook, someone
RM> should pay...
... [later... much, later]
That was not a fair warning, Roy. I've been an hour answering this
and it is only now that I see what you mean - a complete lesson in C!
I hope you haven't suffered a relapse... because I certainly have!
This is my second-coming to C, this time with some idea of what
writing a program is all about, and it is fairly obvious that what I
learned in VB is pretty useless when applied specifically to C.
I am rewiting pkt2wk that was 600 lines in VB, and after a
fortnight, I have 800 lines to go :-). I haven't even got to the hard
part of the program yet, because I can't read the bloody data file...
let alone the PKT! But at least I am beginning to see how C expects
me to use pointers. Your previous stuff on strstr() and strncpy() has
proved to be a bit of an eye-opener to me, and I now see why they do
it the way they do.
Now read on... and it serves you right! :-)
BL> I find it incredible that Borland have an "integrated" IDE that
BL> can't call it directly, so I gave it the flick.
RM> errmm.. try the little ð symbol at the left end of the menu bar
RM> - the standard mode debugger and profiler can be called from
RM> there...
Oh. ROFL!!! This confirms my opinion of Borland!! How the hell am I
supposed to guess that? What a good idea!
RM> (Btw, bloody Borland dropped the profiler with BC4.
RM> Consequently, I still have a full BC3.0 system installed,
RM> although I don't use it much.)
Yes... as I found out. I spent a fortune buying BC4 on a pensioner
discount and everything, and it hasn't got any goodies. Can you use
the old TASM with BC4?
RM> For the TF386 profiler, the IDE has to be shut down.
Yair... I discovered that. I like the way Borland writes its
warnings: "You have just destroyed the World! Shut everything down
and run for your life!"
RM> The 386 version of the debugger is worth looking at, though. It
RM> is far more resistant to program crashes than the standard
RM> debugger.
The standard debugger is useless.
Q: Why do Borland have two debuggers?
A: Because one of them is useless.
ROFL!! I *love* Borland. In fact, since using BC++, I have a whole
new appreciation for Microsoft.
RM> (Hint: check the Debugger settings under Options/Debugger - the
RM> Standalone setting is needed to run the outboard debugger and
RM> the profiler. The exe file gets fatter; ignore this.)
I don't believe it! I open the standalone debugger... and I have to
remember to change the options *as well*? Why can't they just do it
automatically? Borland are idiots.
RM> But in C, you have to add the integer to a pointer again to
RM> access the substring in the bigstring. A function that returns
RM> a pointer saves a step.
I have since discovered that. strstr() is the one I wanted... as
long as I remember that I'm dealing in pointers. I haven't quite
worked out the ramifications of this yet... I have this buffer, and I
can access it all sorts of ways. It's totally different than VB.
RM> You're at that difficult early stage when you don't know enough
RM> to know what you want. Suggestion: spend a few hours with the
RM> library ref manual, away from the computer. Put a bookmark in
RM> the section near the end entitled "Library routines by
RM> category".
I don't need a bookmark. I just snap my fingers and the book falls
open at page 618. I really admire Borland for their use of creative
English. I am awestruck that they can repeat everything twice and
still manage to use headings that relate to nothing. "Manipulation
Routines" is one of my favourites. Or how can I go past "Inline
Routines". Who would expect to find strncpy in there, washing its
hands with something called _rotl? It was obviously a typo, so I
renamed it _royl.
RM> Select a category of interest, look up each function briefly.
RM> Look briefly at what it does, and note the header file it comes
RM> from and any portability notes.
ROFL!! Next you'll be telling me to use the index. This is where
Borland excell: "Files| access, see also modes" ROFL!! "FAT - see
file allocation table... file allocation table(FAT)" ROFL!! This is so
bad it's a classic! All they had to do was put the page number beside
"FAT" so they write a line instead... completely ignoring the fact that
you are *already* looking up "FAT".
As I said: the guys who did this need a good kicking, and I'm just
about ready to do it.
RM> Reason: many of the i/o functions have been written by Borland
RM> for the dos environment (conio.h is full of them) and don't
RM> exist outside of dos. They work ok, but someday you might
RM> strike trouble trying to use them under a different compiler.
Paul goes on about this, but in fact I'd prefer that my code only
compiles on *my* compiler, to make it harder for some prick to steal
it. I don't want it to be portable, and it if won't work unbder UNIX I
will be so happy that I'll dance around the room.
RM> Another hint: scanf() is horrible, it can crack up on
RM> unexpected input.
So what else is new in C? Everything seems to crack up at one time
or another.
RM> English is a rich language partly because of its large
RM> collection of synonyms (you intellectually challenged vagina
RM> ); something similar can be said about C.
I agree entirely. C is a dopey cunt of a thing.
BL> With strncpy(), what if you want to copy from a certain place?
BL> How do you set the starting point? Use strchr or strstr,
BL> first... or use pointers and then have to give it space each
BL> time?
I may be using it wrong, but strncpy() copies to the same address
each time. In VB, with MID$() I get a string I can use, but strncpy()
uses the same address for the next time, and I end up with nothing but
the last one. In VB, I can say name$ = mid$(buf$, start, length) and
then then put name$ into an array or whatever. In C, using
strncpy(name, buf + start, length);
name[length] = '\0'; //I *have* to do this! Mad!
I can't use name as a string, because the next time I call strncpy()
it is overwritten. I can't even use the address becasue it's the same
addresds. I suppose I have to allocate new memory each time, but I
haven't tried that yet.
BL> Even strlen() gives me the shits. What is the point of calling
BL> it STRlen?
RM> So you can look it up under "str", silly - you're contradicting
RM> yourself here...
The name of the game is CONSISTENCY, Roy. There are several "string"
functions not listed under "strxxx" (sprintf, sscanf). You either do
it one way, or the other. In Borland, strcpy and strncpy are a pair...
but they are nowhere near each other alphabetically. The same applies
to strchr, strstr. They should be listed in groups that do similar
things, and emphasise the differences. The whole thing has been
designed by an idiot or an incompetent, and probably all three.
BL> I have been silly enough to look up the "str" functions under
BL> "str". What a shame that sprintf() is under "sp"
RM> sprintf is under printf. If they cross referenced everything,
RM> the see-also sections would be enormous.
You think so...? I could *halve* the size of that book, double the
information, and make it ten-times as accessible - and I don't even do
that sort of thing for a living.
There is a classic example of a well-laid-out book and a bad one
with VB. VB/DOS is awful, with many of the Borland incompetencies;
VB/Win is a wonder. VB/DOS was laid out in an effort to save room,
with the same silly cross-referencing that BC++ uses; VB/Win just put
it ALL in. They are almost exactly the same book, and almost exactly
the same size, but VB/DOS was laid out by a fool and VB/WIN was done
by a professional. Brains don't cost extra, but you have to use them.
RM> square1() can't alter the value of i, because we are calling it
RM> with 2 as the parameter. square2() *can* alter the value of b,
RM> because we are calling it with the actual memory address of b
RM> as a parameter... [crunch to tutorial]
Yair... in my mind, if you change it inside the function, then you
have to expect that it comes out changed. That happens with VB too,
and is a trap for young players... but now write me one using
strings. I don't have any trouble passing characters and integers...
but do it with strings and you *have* to pass addresses, and you
*have* to allocate space.
RM> Lesson 2: Calling by reference can be more efficient, if the
RM> parameter is a large object.
If the parameter is a large object how can you pass it unless you
use the address? Even when you *think* you're not, C is doing it
automatically.
RM> typedef struct /* this defines a new "type" called
"person". */
RM> { /* No memory allocation is done here, we are */
RM> char name[20], /* just telling the compiler what "person" is. */
RM> address[40];
RM> int sales[4096];
RM> } person;
You are telling the compiler that "person" is 20 + 40 + 4096. That's
what a struct does! You just haven't used it yet.
RM> int main(void)
RM> {
RM> person pp; /* actual memory allocation done here */
RM> int i;
RM> i = sales1(pp);
RM> i = sales2(&pp);
RM> return 0;
RM> }
RM> When sales1() is called, the program has to make a complete
RM> copy of the structure pp for sales1() to play with. When
RM> sales2() is called, only the address of the structure is
RM> passed, and sales2() works with the original copy of pp in
RM> main(). Considerably quicker, but you need to be aware that if
RM> you change something in q, you are changing pp.
Structs do not confuse me, Roy. It seems obvious to me, that if
I am defining a new type, then I have to say how big it will be, and
passing by value or by reference seems perfectly sensible to me. What
roots me is having to do the same thing with strings.
How do I know how big a string is going to be when I haven't read
the file yet? VB is dynamic, and if I want to increase the size of a
string it happens as I do it. In C, I have to allocate memory at every
stage... sometimes at the beginning, and sometimes with malloc()
halfway through. It's a bloody shambles and too easy to get crossed up -
for what? What do I gain?
The whole basis of C, is to ignore the distinction bewteen pointers
and real memory. I have to do that for myself, at every stage, and if
I stuff up, C does something entirely different than what I expect it
to do. What do I get out of it? Not a lot, as far as I can work out.
BL> Are you kidding, Roy? I don't believe that you expect me to
BL> write all that shit...
RM> So make it into a function.
That just what I did. I called it mid() and did a malloc in the
middle to make it dynamic, and counted one character at a time in a
loop.
RM> If you already know that outstr has enough space, and M and K
RM> are sensible, then a bald
RM> strncpy( Outstr, Instr+M, K);
RM> is heaps faster. With Basic you don't get the choice.
Yair... but what if I *don't* know how big the file is? Then I have
to write a whole new loop.
RM> Close. Instr is already a pointer, it's the input to the
RM> function. In most circumstances, you know the max length that
RM> outstr will be, so you just set it up as
RM> char outstr[MAXLEN];
RM> near the beginning of the function. If you don't know what the
RM> maxlen will be, then yes, a call to malloc() or one of its
RM> cousins is needed.
For God's sake, Roy! I *know* that. If I can define out as an array
there's no problem,. My problem is that I haven't got a clue how big
it is... *that's* why I have to read the file!
RM> But that's what your Basic program is doing in the background
RM> anyway, and you have no control over how (or when) it is done.
This is what I mean by: what do I gain? VB is not a fair comparison
to C, because it's functions are general-purpose and rather large, and
C is the exact opposite. That's why I am going to try Pascal next.
As a general rule, VB is about 2- 4 times slower than C, for the
same program, but optimised for both. It will be interesting to see
how much better Pascal does. Frank's approach is looking much better
now that I understand C: write in Pascal because it is nice (and
fairly fast), and when you want it to run *really* fast, write a bit
of ASM inline. It seems to me that you then get the best of both
worlds... but I'll have to go through this all again to find out, and
I'm not quite done with C, yet. I still have to find out how to use
arrays properly.
... [later]
Waaall... I'm not sure that I'll bother, now. I was fiddling with my
pkt2qwk program a few minutes ago, trying variuous ways of dealing
with the pointers that strstr() produces... and BC++ ate the .c file!
ROFL!!! Gone forever.
I had about a hundred lines of code in there that worked... gone!
Undelete doesn't want to know! I can't make up my mind whether to
laugh or cry, but I think this may have helped me make up my mind
about C. It ate the .c file!! It took one big bite and... zero bytes.
RM> What exactly happens when you call out$=mid$("Hello",20,10) ?
It returns zero... but who gives a bugger anyway?
RM> If you write in enough guards to allow your program to react
RM> intelligently, you'd end up with roughly the same thing I wrote
RM> above. Once again, with C you have a choice.
The VB approach is to write an error handler at the end, rather than
do it as you go along. You can make your error handler as intelligent
as you like (assuming that you are intelligent to begin with, which
is doubtful if you are using C).
I can't believe this! It ate the fucking pkt2qwk.c file! All that
work has gone to the great bit-bucket in the sky. The bloody elves in
BC++ stole it. They zero-byted the whole file!
But it could be worse. The bastards might have got me too!
Regards,
Bob
___ Blue Wave/QWK v2.12
@EOT:
---
* Origin: Precision Nonsense, Sydney (3:711/934.12)SEEN-BY: 711/934 @PATH: 711/934 |
|
| SOURCE: echomail via fidonet.ozzmosis.com | |
Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.