TIP: Click on subject to list as thread! ANSI
echo: locsysop
to: Bob Lawrence
from: Roy McNeill
date: 1995-04-26 21:25:40
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™.