Re: Code Comprehension



jj@xxxxxxxxxxxx writes:

I regularly find myself staring at a bit of (usually terse) code for
frustratingly long periods of time before I can, hopefully, understand
what it does. Does this get easier with experience/practise? Is there
anything I can do to help improve things or am I just a bit dim?

Learning about program proofs, assertions, etc, and program
transformation, can help.


Here's an example of the kind of thing I'm talking about, even knowing
what it does it takes me quite a while to figure out *how* it does it:

The example is badly written, even if "idiomatic" C.


void fun(char *a, const char *b) {
int apos = 0, i, j;

if (!a || !b)
return;

if((a==NULL)||(b==NULL)){return;}
/* Avoid the confusion between boolean ( ! && || )
logical (bits) ( ~ & | ^ )
and pointer ( == != *x &x ) types. */


for (i = 0; a[i]; i++) {

for(i=0;a[i]!='\0';i++){
/* Avoid confusion between boolean and characters */


for (j = 0; b[j] && a[i] != b[j]; j++)
;

for(j=0;(b[j]!='\0')&&(a[i]!=b[j]);j++);
/* idem */


if (!b[j]) {

if(b[j]!='\0'){

a[apos++] = a[i];
}
}

a[apos] = '\0';
}

So that gives:

void fun(char *a, const char *b) {
int apos = 0, i, j;
if((a==NULL)||(b==NULL)){return;}
for(i=0;a[i]!='\0';i++){
for(j=0;(b[j]!='\0')&&(a[i]!=b[j]);j++);
if(b[j]!='\0'){
a[apos++] = a[i]; }}
a[apos]='\0'; }

Note that any program that calls itself a compiler should produce the
same object code for both these versions.


When a or b are NULL it does nothing.

The for(j=0;...) loop finds the position of the first character in b
that is not a[i]. If there is none (when j reaches the length of b,
b[j]='\0'), the the ith character of a is copied over a the beginning of a.
At the end, the new end of the string a is marked at apos.

So, this function removes from a all the characters that are not in b.

char a[]="Hello World!";
fun(a,"abcdefghijklmnopqrstuvwxyz");
assert(strcmp(a,"elloorld")==0);



I would have written it as:

void remove_characters(char* string,const char* bag){
int dst,src;
if((string=NULL)||(bag==NULL)){return;} /* Actually no, my _strings_
are not NULL! */
for(dst=0,src=0;a[src]!='\0';src++){
if(strchr(bag,string[src])!=NULL){
string[dst++]=string[src];}}
string[dst]='\0';}


--
__Pascal Bourguignon__
.



Relevant Pages

  • Re: Code Comprehension
    ... Reproducing the example for comparison ... void fun(char *a, const char *b) { ... int apos = 0, i, j; ...
    (comp.programming)
  • Re: Code Comprehension
    ... void fun(char *a, const char *b) { ... int apos = 0, i, j; ... that, because you did not eliminate the "for" loop, which is ...
    (comp.programming)
  • Re: regex in filenames
    ... static int chmatch(const char *target, ... str - the target string ... while((gobble = chmatch(target, pat))) ... match a character. ...
    (comp.lang.c)
  • Re: Typecast clarification
    ... A void* you can convert without a typecast but you can't dereference. ... char* you can dereference but not convert automatically. ... A "char *" is a pointer to a byte ... You're looking through a pointer to a character; ...
    (comp.lang.c)
  • Re: Help a beginner - simple lowercase to uppercase and so on function
    ... void test (void) ... void UppStrg(char *Low, char *Upp, int cnt); ... you know about character constants why start using integers? ...
    (comp.lang.c)