С неоднозначностью проблема - PullRequest
1 голос
/ 27 января 2011

Кодируя очень простую программу для удаления пробелов, вкладок, новых строк, я наткнулся на то, чего я на самом деле не поймал первым;даже если , если условие истинно, только когда табуляции, пробела или новой строки не существует, оно по какой-то причине все еще выполняется с упомянутым выше ... вот код

<del>#include <cstdio></del>
<del>#include <cstring></del>
#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();
}

Ответы [ 6 ]

9 голосов
/ 27 января 2011

s[i]!=' ' || s[i]!='\t' || s[i]!='\n' равно всегда верно.Символ не может быть равен и пробелу, и табуляции, и новой строке.

6 голосов
/ 27 января 2011

Проблема в том, что

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

всегда верно.Если s[i] это пробел, то последние две проверки верны.Если это не пробел, то первая проверка верна.

Чтобы исправить это, измените эти ors на ands:

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

Или, что еще лучше, используйте isspace:

 if(isspace(s[i])
2 голосов
/ 27 января 2011

Если вы думаете об этом, любое выражение, подобное следующему, является подозрительным ...

a != x || a != y

Что бы ни было a, оно всегда не будет одним ИЛИ не будет другим. Так что это всегда так. Эквивалентная ошибка с and всегда ложна, а не всегда истинна, и выглядит так:

a == x && a == y

Это немного легче увидеть, верно? Вещи a не могут быть одновременно x И y одновременно. И на самом деле эти утверждения связаны законами де Моргана.

Обновление: Итак, обычно вам нужно a != x && a != y. Для второго случая: a == x || a == y.

2 голосов
/ 27 января 2011

s[i] != x || s[i] != y верно для всех различных значений x и y.

Вы, вероятно, хотите &&.

0 голосов
/ 27 января 2011

Как уже указывали другие, ваше логическое выражение является тавтологией (т. Е. Всегда верно). Вы также можете использовать функцию strpbrk() вместо дублирования функций, предоставляемых стандартной библиотекой:

#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>
Кроме того, при включении заголовков <c…> идентификаторы следует добавлять к std:: или добавлять директиву using Или используйте вместо этого <….h>. Используя функциональность, не унаследованную от стандартной библиотеки C, более идиоматический код C ++ будет выглядеть так:
<del>
#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>
</del>
0 голосов
/ 27 января 2011

попробуйте изменить

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

break;

с

 if(s[i]!=' ' && s[i]!='\t' && s[i]!='\n')
   break;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...