| TIP: Click on subject to list as thread! | ANSI |
| echo: | |
|---|---|
| to: | |
| from: | |
| date: | |
| subject: | C |
Hi Bob - this started out as a normal answer, but turned into THIS.
Ah well, if I gotta stay home cos I'm crook, someone should pay...
RM> One of the big strengths of the profiler is that it can point
RM> out sluggish bits of code in places you never thought of
RM> looking.
BL> I have never used it, but I'll give it a go. I find it incredible
BL> that Borland have an "integrated" IDE that can't call it
directly, so
BL> I gave it the flick.
errmm.. try the little ð symbol at the left end of the menu bar -
the standard mode debugger and profiler can be called from there...
(Btw, bloody Borland dropped the profiler with BC4. Consequently, I
still have a full BC3.0 system installed, although I don't use it
much.)
BL> ... [later - is this profiler any good, or what? It makes it too easy.
sweet, innit.
RM> The delay involved in switching between the IDE and the
RM> profiler didn't really bother me. In each subdir, I had a file
RM> called C.BAT which contained "bc hello.prj" or equivalent.
BL> I'm not sure what you mean here, Roy. Did you have a different batch
BL> file for every project (like .mak), or did you rewrite the c.bat every
BL> time you started a new project? And why in every subdirectory? Why not
BL> just the working directory?
I never really standardized it. One batch file would have done the
trick (bc %1.prj) and I'd just have to type "c hello" to open the
hello project. But projects that take a lot of time (I have a
serial monitoring program I first wrote in abt 1987, it's up to
revision 7, and is now due for a major rewrite using Turbo Vision
and a dos extender) get their own c.bat file.
RM> If I was using the profiler a lot there would also be TP.BAT,
RM> "tf386 hello.exe". (I was using BC3v0, some of the prognames
RM> may be a bit different in 3v1.)
BL> I'm still not clear how this works. I am in the IDE typing away and
BL> I'd like to find out how long the loop is taking in my project the way
BL> I've written it. What do I do? Shell to DOS and type "TP
project.c"
BL> Or do I close the IDE first?
For the TF386 profiler, the IDE has to be shut down. For the
standard profiler, no - see above. TF386 loads entirely into XMS,
making it better for programs that use heaps of low memory. I never
really needed this feature, it was just a snobby habit .
The 386 version of the debugger is worth looking at, though. It is
far more resistant to program crashes than the standard debugger.
Both standalone debuggers have a lot more power than the one built
into the IDE, too. (Hint: check the Debugger settings under
Options/Debugger - the Standalone setting is needed to run the
outboard debugger and the profiler. The exe file gets fatter;
ignore this.)
RM> What's instr()?
BL> It's strstr() with a starting point rather than just the beginning,
BL> that also works for characters... and returns an integer rather than a
BL> pointer that has to have the start subtracted.
But in C, you have to add the integer to a pointer again to
access the substring in the bigstring. A function that returns a
pointer saves a step.
RM> Take a closer look at the strxxx() collection, you'll find a
RM> few that you'll use a lot (eg strcat, strcpy, strncpy, strcmp,
RM> strlen), and the rest just stay in the back of the mind.
BL> I did that some time ago, Roy. I was forced to learn all these
BL> shitty things off by heart, and I *still* missed sprintf() and scanf()
BL> because they were not listed in the "strxxx" group of functions.
You're at that difficult early stage when you don't know enough to
know what you want. Suggestion: spend a few hours with the library
ref manual, away from the computer. Put a bookmark in the section
near the end entitled "Library routines by category". Select a
category of interest, look up each function briefly. Look briefly
at what it does, and note the header file it comes from and any
portability notes. Reason: many of the i/o functions have been
written by Borland for the dos environment (conio.h is full of
them) and don't exist outside of dos. They work ok, but someday you
might strike trouble trying to use them under a different compiler.
Another hint: scanf() is horrible, it can crack up on unexpected
input. A better combination is gets() followed by sscanf(). If the
string read in by gets() is full of crap, your program can react to
it more intelligently.
BL> strcat() for instance is one of my favourites. If I have a buffer
BL> and want to add a bit on the end without destroying the original (so I
BL> can use it later)... how? No way in C; shit-easy in VB.
More info? I'm not sure what you mean here
BL> For instance... what's the difference between strcpy and stpcpy? Can
BL> you remember? I can't, and I've just looked it up.
Different return value. char *s=stpcpy(dest,source) points to the
end of the new string, char *s=strcpy(dest,source) points to the
beginning. stpcpy() could be handy if you're concatenating a number
of stringlets into dest, although I've never used it (thinks - a
bit fiddlier than strcat, but slightly faster in a loop - strcat
has to find the end of dest before it can start copying, stpcpy()
has already supplied the end pointer). Btw, virtually all C
library functions return a value, we just don't use all of them.
stpcpy() does overlap strcat() a bit, and strcpy() a lot. I call
this a bonus, not a drawback. English is a rich language partly
because of its large collection of synonyms (you intellectually
challenged vagina ); something similar can be said about C.
BL> With strncpy(), what if you want to copy from a certain place? How
BL> do you set the starting point? Use strchr or strstr, first... or use
BL> pointers and then have to give it space each time?
More info? I'm not sure what you mean here
BL> With VB, I only have to remember two functions: instr() and mid()...
BL> plus len(). Even strlen() gives me the shits. What is the point of
BL> calling it STRlen?
So you can look it up under "str", silly - you're contradicting
yourself here....
RM> Don't try to memorize them all (I never have), just remember
RM> that "something like that exists, I'll go look it up". In the
RM> IDE that's just an F1 key away.
BL> *where* do you look it up? I have been silly enough to look up the
BL> "str" functions under "str". What a shame that
sprintf() is under "sp"
sprintf is under printf. If they cross referenced everything, the
see-also sections would be enormous.
BL> Borland help is a misnomer, they should call it "stuffup".
It's the standard catch-22 help, you need to have a rough idea what
you're looking for first. And it's a help system, not a tutorial.
Borland used to put a reasonable C tutorial into their manuals, but
they stopped that with version 3.
BL> Unfortunately... I wrote that before I realised that the only way to
BL> write functions is to pass by value and you need pointers to do that.
That's something you have to understand *very* clearly. Stop me if
you know this already, I'm about to go into babytalk mode....
Lesson 1: If you "call by value", the original parameter can't be
changed. If you "call by reference", it can.
----
int square1(int k) /* call by value */
{
return k*k;
}
int square2(int *k) /* call by reference */
{
int j = *k; /* assign temp variable to make next line readable..*/
*k = j*j;
return *k; /* we're returning the square twice here, as k and as
the return value */
}
main()
{
int a,b,x,y;
a=2;b=2;
x = square1(a);
y = square2(b);
printf("a = %d, b = %d, x = %d, y = %d"\n,a,b,x,y);
return(0);
}
----
Result:
a = 2, b = 4, x = 4, y = 4
square1() can't alter the value of i, because we are calling it
with 2 as the parameter. square2() *can* alter the value of b,
because we are calling it with the actual memory address of b as a
parameter.
Lesson 2: Calling by reference can be more efficient, if the
parameter is a large object.
----
typedef struct /* this defines a new "type" called
"person". */
{ /* No memory allocation is done here, we are */
char name[20], /* just telling the compiler what "person" is. */
address[40];
int sales[4096];
} person;
int sales1( person p) /* call by value */
{ return p.sales[1]; }
int sales2( person *q) /* call by reference */
{ return q->sales[1]; } /* C shorthand, same as *q.sales[1] */
int main(void)
{
person pp; /* actual memory allocation done here */
int i;
i = sales1(pp);
i = sales2(&pp);
return 0;
}
----
When sales1() is called, the program has to make a complete copy of
the structure pp for sales1() to play with. When sales2() is
called, only the address of the structure is passed, and sales2()
works with the original copy of pp in main(). Considerably quicker,
but you need to be aware that if you change something in q, you are
changing pp.
C++ has a more elegant way of calling by reference, but we'll leave
that well alone for now.
RM> J = strlen(Instr);
RM> if( (M < J) && ((M+K) <= J))
RM> {
RM> strncpy( Outstr, Instr+M, K); /* direct equivalent of mid() */
RM> Outstr[J] = '\0'; /* see strncpy() docs for why */
RM> }
RM> else
RM> printf("K and/or M too big...\n");
BL> Are you kidding, Roy? I don't believe that you expect me to write
BL> all that shit...
So make it into a function. Write plenty of comments. Stick it in a
file called MYFAVES.C, give it a header file called MYFAVES.H, and
include both in your projects.
BL ...instead of: out$=mid$(in$, start, length) which
BL> automatically takes care of wrong lengths, and that instr is a pointer
BL> and outstr has space allocated.
Which is why, line for line, Basic is inherently slower than C. All
that overhead. If you already know that outstr has enough space,
and M and K are sensible, then a bald
strncpy( Outstr, Instr+M, K);
is heaps faster. With Basic you don't get the choice.
BL> The only way to be sure it will work,
BL> is to make both instr and outstr pointers, and do a char * malloc(J)
BL> in the middle of the function to get a dynamic allocation of memory.
BL> Either that, or I am *still* confused by pointers.
Close. Instr is already a pointer, it's the input to the function.
In most circumstances, you know the max length that outstr will be,
so you just set it up as
char outstr[MAXLEN];
near the beginning of the function. If you don't know what the
maxlen will be, then yes, a call to malloc() or one of its cousins
is needed. But that's what your Basic program is doing in the
background anyway, and you have no control over how (or when) it is
done.
RM> How does mid() react if the input string is too short?
BL> It does the best it can... and writes what's there. This is a vast
BL> improvement on copying command.com (or whatever happens to be in
BL> memory at the time) the way that C does it. ROFL!!
What exactly happens when you call out$=mid$("Hello",20,10) ? If
you write in enough guards to allow your program to react
intelligently, you'd end up with roughly the same thing I wrote
above. Once again, with C you have a choice.
Cheers
--- PPoint 1.88
* Origin: Silicon Heaven (3:711/934.16)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™.