5

A pattern recognition program must print all lines containing the patter if the input is find pattern. If the input is find -x pattern, the program must print all lines except the lines containing pattern.

// .....
switch(c)
{
case 'x':
    except=1;
    break;
// ......
}

// ......
while(getline(line,MAXLINE)>0)
    {
    line_num++;
    if( (strstr(line,*argv)!=NULL) != except)
        {
        if(number)
            printf("%ld:",linenum);
        printf("%s",line);
        found++;
        }
    }
// ......

In the above code from K&R except can either be 1 or 0. How does if(strstr...) block functions effectively to handle -x ?

Ziezi
  • 6,375
  • 3
  • 39
  • 49
ThunderPunch
  • 483
  • 1
  • 4
  • 16

3 Answers3

3

I am not familiar with the code, however this statement will evaluate to a boolean (0 or 1) as strstr() will return a pointer to word being searched for or NULL if not found:

strstr(line, *argv) != NULL

So I guess except is set to 0 or 1 to effect the "was not found" or "was found" condition.

If -x is not passed then except is 0:

if ((strstr(line, *argv) != NULL) != 0)

which means if the word was found enter the if clause.

If -x is passed then except is 1:

if ((strstr(line, *argv) != NULL) != 1)

which means if the word was found don't enter the if clause.

It's confusing code, so I would recommend breaking it down to:

const char *word = strstr(line,*argv);
int wasfound = word != NULL;
if (wasfound != except)
{

}

and then stepping through with a debugger. Learning to use a debugger is also vital.

trojanfoe
  • 120,358
  • 21
  • 212
  • 242
3

The logic is simple. If the pattern is "-x" we should print all lines that do not contain the pattern.

For this pattern except is equal to 1.

So lines that contain the pattern satisfy the condition

strstr(line,*argv)!=NULL

that is this condition will be always equal to 1 if a line contains the pattern.

Thus if except is equal to 1 and the condition strstr(line,*argv)!=NULL is equal to 1 we should skip the pattern.

Otherwise if the condition strstr(line,*argv)!=NULL is not equal to 1 that is if the pattern is not found then the if statement

if( (strstr(line,*argv)!=NULL) != except)

yields true and its compound statement is executed.

On the other hand if except is equal to 0 then to achieve that the condition in the if statement would evaluate to true we need that the condition strstr(line,*argv)!=NULL would be equal to 1.

In fact you can rewrite the if statement

if( (strstr(line,*argv)!=NULL) != except)

the following way

if( ( ( strstr(line,*argv) != NULL ) == 1 && except == 0 ) ||
    ( ( strstr(line,*argv) != NULL ) == 0 && except == 1 ) )

Shortly speaking the if statement does the work if either

1 and 0

or

0 and 1

If either

1 and 1

or

0 and 0

then the if statement will not be executed.

Here 1 and 0 are results of evaluating of the two sub expressions in the if statement.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

The != operator has the same truth value as an XOR operation. So you can break up

if( (strstr(line,*argv)!=NULL) != except)
    {
    if(number)
        printf("%ld:",linenum);
    printf("%s",line);
    found++;
    }

into (less efficient but maybe more clear)

char found_one_match;
if( strstr(line,*argv) != NULL )
{
    found_one_match = 1;
}
else
{
    found_one_match = 0;
}
found_one_match ^= except;
if (found_one_match)
{
    if(number)
        printf("%ld:",linenum);
    printf("%s",line);
}
found += found_one_match;

In other words, except reverses the effect of what happens when a pattern is found in the string.

Dmitry Rubanovich
  • 2,471
  • 19
  • 27