highlevelcoder
highlevelcoder

Reputation: 355

C ambiguity problem

While coding very simple program for removing blanks, tabs, newlines I came across something I don't actually catch on first; even though if condition is true only when tab, space or newline doesn't exist it's still executed with the mentioned for some reason.. here is the code

#include <cstdio>
#include <cstring>
#include <stdio.h>
#include <string.h>

#define LGT 100

void rem(char s[])
{
 int i;
 for(i=(strlen(s)-1);i>=0;i--)
  if(s[i]!=' ' || s[i]!='\t' || s[i]!='\n')
   break;
  s[i+1]='\0';

}
int main(void)
{
 char v[LGT]={"sdsfg\t"};

 rem(v);
 printf("%s\n",v);
 getchar();
}

Upvotes: 1

Views: 1450

Answers (6)

Christoph
Christoph

Reputation: 169683

As others already pointed out, your boolean expression is a tautology (ie always true). You might also want to use the function strpbrk() instead of duplicating functionality provided by the standard library:

#include <stdio.h>
#include <string.h>

// …

char text[] = "foo\tbar\n";
char *tail = strpbrk(text, " \t\n");
if(tail) *tail = 0;
printf("<%s>", text); // prints <foo>
Also, when including <c…> headers, you should prefix identifiers with std:: or add a using directive. Alternatively, use <….h> instead. Using functionality not inherited from the C standard library, more idiomatic C++ code would look like this:

#include <iostream>
#include <string>

// …

std::string text = "foo\tbar\n";
std::size_t pos = text.find_first_of(" \t\n");
if(pos != std::string::npos)
    text.erase(pos);
std::cout << '<' << text << '>'; // prints <foo>

Upvotes: 0

DigitalRoss
DigitalRoss

Reputation: 146143

If you think about it, any expression like the following is suspect...

a != x || a != y

Whatever a is, it will always not be one thing OR not be another. So this is always true. The equivalent mistake with and is always false rather than always true, and it looks like:

a == x && a == y

It's a little easier to see, right? Thing a can't possibly be both x AND y at the same time. And in fact these statements are related by De Morgan's laws.

Update: So, typically what you want is a != x && a != y. For the second case: a == x || a == y.

Upvotes: 2

templatetypedef
templatetypedef

Reputation: 372982

The problem is that

  if(s[i]!=' ' || s[i]!='\t' || s[i]!='\n')

Is always true. If s[i] is a space, then the latter two checks are true. If it's not a space, them the first check is true.

To fix this, change these ors to ands:

if(s[i]!=' ' && s[i]!='\t' && s[i]!='\n')

Or, even better, use isspace:

 if(isspace(s[i])

Upvotes: 6

Ass3mbler
Ass3mbler

Reputation: 3915

try changing

if(s[i]!=' ' || s[i]!='\t' || s[i]!='\n')

break;

with

 if(s[i]!=' ' && s[i]!='\t' && s[i]!='\n')
   break;

Upvotes: 0

Wooble
Wooble

Reputation: 89997

s[i] != x || s[i] != y is true for all different values of x and y.

You probably want &&.

Upvotes: 2

escargot agile
escargot agile

Reputation: 22389

s[i]!=' ' || s[i]!='\t' || s[i]!='\n' is always true. A character can't be equal to both a space, a tab and a newline.

Upvotes: 9

Related Questions