Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Выражение в С++, что это ?


Автор: EvilsInterrupt 7.1.2010, 00:33
Есть такая ситуация, читая про С++ книгу Эккеля увидел:

что автор говорит о том, что такая строчка не работает:
Код

while((char c=cin.get()) != 'C')


но работает такая:
Цитата

while(char c=cin.get() != 'C')


т.е. без скобочек. Недолго думая, тут же создал proba.cpp и действительно! Почитав пояснение, не совсем понял его. Пояснение сводится к тому что в выражениях недопустимы скобочки.

Не остановился и решил поискать терминологию, а что собственно является выражением в С++ и ... пока не нашел ( Прошу, подсказать мне в чем фокус ? Почему пример, когда выделено в скобочки, не работает ?

Автор: _GRIN_ 7.1.2010, 01:04
EvilsInterrupt, суть в том, что  переменная char c видна только внутри тех скобок, где она объявлена, следовательно при сравнении на неравенство с символом 'С' слева от знакак неравенства по сути ничего нет (как только вышли из скобок переменная "потерялась"). Нормальный компилятор с лишними скобками не скомпилит.

Автор: andrew_121 7.1.2010, 01:17
g++ не компилит.

Добавлено через 32 секунды
у тебя какой компилятор?

Автор: xvr 7.1.2010, 12:15
Цитата

Пояснение сводится к тому что в выражениях недопустимы скобочки.
Гм. Сильно  smile 
Суть сводится к тому, что в while(char c=cin.get() != 'C') внутри while использованно НЕ выражение
Стандарт:
Цитата


iteration-statement:
  while (condition) statement

condition:
  expression
  type-spec-seq declarator = assignment-expression
Т.е. в конструкции
Код

while((char c=cin.get()) != 'C')
condition в while попадет в группу expression, и даст ошибку, т.к. определять переменные внутри выражений нельзя.
Во втором же случае
Код

while(char c=cin.get() != 'C')
это будет type-spec-seq declarator = ..., что синтаксически правильно, но врядли правильно семантически, т.к. в переменную c присвоится не введенный символ, а результат его сравнения с литерой 'C'

Автор: zim22 7.1.2010, 13:35
пол-года назад я тоже задавал подобные вопросы
вот тема: http://forum.vingrad.ru/forum/topic-264505.html

Автор: EvilsInterrupt 7.1.2010, 16:04
все равно не понял, вернусь к этому вопросу позже, спасибо за внимание ;)

Автор: A5uKa 7.1.2010, 23:29
Цитата

в переменную c присвоится не введенный символ, а результат его сравнения с литерой 'C'

а разве get() не выполнится перед этим ?

п.с. мне всегда казалось, что в этом случае сравнивается даже не значение char, а результат операции присвоения :S

Автор: xvr 7.1.2010, 23:52
Цитата(EvilsInterrupt @ 7.1.2010,  16:04)
все равно не понял, вернусь к этому вопросу позже, спасибо за внимание ;)

А чего тут непонятного? В while, if, for и пр. в качестве условия можно использовать выражение или определение переменной. В последнем случае именно значение этой переменной и становится условием.
Определять переменные внутри выражения нельзя.

Цитата

а разве get() не выполнится перед этим ?
Выполнится
Цитата

п.с. мне всегда казалось, что в этом случае сравнивается даже не значение char, а результат операции присвоения :S
Условие while в данном случае - это значение переменной. А значение переменной - это результат операции сравнения
Запись while(char c=cin.get() != 'C') приблизительно эквивалентна такой
Код

char c=(cin.get() != 'C');
while(c)
 {
   ...
   c=(cin.get() != 'C');
 }


Автор: A5uKa 8.1.2010, 00:07
Цитата

Цитата

сравнивается даже не значение char, а результат операции присвоения

....


Я не о том...

Я просто хочу сказать, что сравнение идёт не с переменной.
Код


    int x=0;
    if (x=2 == x)
        cout << "So";
    else
        cout << "Or So";

присвоение происходит после сравнения. Точнее присвоения вообще НЕ происходит, при выходе из тела if или while оно вернётся и станет тем, чем было.

то есть не 
Код

while(c)

а 
Код

while (то чему c равно)

Автор: mes 8.1.2010, 00:41
Цитата(xvr @  7.1.2010,  22:52 Найти цитируемый пост)
char c=(cin.get() != 'C');
while©
 {
   ...
   c=(cin.get() != 'C');
 }


имхо с for смотрится симпатичнее :
Код

for  (char c; c = (cin.get() != 'C'); ) {...}

хотя тоже не до конца соответсвует примеру..

Автор: A5uKa 8.1.2010, 00:55
Цитата

имхо с for смотрится симпатичнее

почему ?

только не понимаю зачем вообще char переменная тут
у 
Код

char c;
for  (;cin.get() != 'C';) ; суть та же

Ведь в условии присвоения не происходит.

Автор: mes 8.1.2010, 01:00
Цитата(A5uKa @  7.1.2010,  23:55 Найти цитируемый пост)
Ведь в условии присвоения не происходит.

как это не происходит ?

Цитата(A5uKa @  7.1.2010,  23:07 Найти цитируемый пост)
при выходе из тела if или while оно вернётся и станет тем, чем было.

а нам за телом и не нужно.. мы ее внутри тела будем использовать smile

Добавлено через 2 минуты и 24 секунды
ммм..  а что Вы называете телом while ? описание или блок цикла ?

Добавлено через 3 минуты и 58 секунд
Цитата(A5uKa @  7.1.2010,  23:55 Найти цитируемый пост)
Цитата

имхо с for смотрится симпатичнее


почему ?

потому что условие/присвоение пишется один раз.. т.е. нет копи-паста..

Автор: A5uKa 8.1.2010, 01:13
Цитата(mes @ 8.1.2010,  01:00)
Цитата(A5uKa @  7.1.2010,  23:55 Найти цитируемый пост)
Ведь в условии присвоения не происходит.

как это не происходит ?

Цитата(A5uKa @  7.1.2010,  23:07 Найти цитируемый пост)
при выходе из тела if или while оно вернётся и станет тем, чем было.

а нам за телом и не нужно.. мы ее внутри тела будем использовать smile

Добавлено @ 01:02
ммм..  а что Вы называете телом while ? описание или блок цикла ?

Код

for  (char c; c = (cin.get() != 'C'); )    
{ }

Только НЕ этого тела, а того, что в круглых скобках после равно
То есть вообще не будем.
Можете cout << c; для примера поставить...

п.с. рекурсия ещё лучше :P

Автор: mes 8.1.2010, 02:16
Цитата(A5uKa @  8.1.2010,  00:13 Найти цитируемый пост)
Только НЕ этого тела, а того, что в круглых скобках после равно
То есть вообще не будем.

Вы имеете ввиду что
Код

while(char c=std::cin.get() != 'C')
{
// здесь, в теле цикла c не будет равно результату приравнему выше ?
}


позвольте тогда узнать куда девалось выше присвоенное значение  ? 
а также что хранит тогда сейчас c ? неужто мусор ? 
или может та "c" в теле цикла не существует ?
 _________________ 
| хочу подробностей |
|_________________|
             |
             | smile 



Автор: A5uKa 8.1.2010, 02:33
Именно это я и хочу сказать.

Цитата

куда девалось выше присвоенное значение  ? 

Я могу соврать, если скаже, что присвоения как такового не было вообще, но я его не наблюдаю smile

Цитата

неужто мусор ? 

Грязный и вонючий  smile 

вот ещё пример

Код

int j=5;
while(int i=j == 5)
{
    cout << i;
    cout << "FAIL";
}


на самом деле сравнивается j и 5 
А i вообще не при делах выводится единицой.
Бурной фантазией можно предположить почему int i = (int)(bool)(5==5) но как знать smile 

p.s. ну всё ... 
Вы наверное уснули =)
Пойду и я спать ... 

Автор: artsb 8.1.2010, 09:33
A5uKa, все работает правильно:

Автор: mes 8.1.2010, 10:02
Цитата(A5uKa @  8.1.2010,  01:33 Найти цитируемый пост)
на самом деле сравнивается j и 5 
А i вообще не при делах выводится единицой.

А теперь давайте подумаем откуда взялась единица..
и почему если
Цитата(A5uKa @  8.1.2010,  01:33 Найти цитируемый пост)
i вообще не при делах

и
Цитата(A5uKa @  8.1.2010,  01:33 Найти цитируемый пост)
выводится единицой.

то заменив == на != (ну или одну из 5 заменить другим значением)
начнет выводиться ноль ?!

ну и ответ:
Цитата(xvr @  7.1.2010,  22:52 Найти цитируемый пост)
А значение переменной - это результат операции сравнения

кстати он был дан еше в 4м посту и Вы его даще цитировали:
Цитата(A5uKa @  7.1.2010,  22:29 Найти цитируемый пост)

в переменную c присвоится не введенный символ, а результат его сравнения с литерой 'C'

 smile 

Автор: A5uKa 8.1.2010, 12:39
Цитата(artsb @ 8.1.2010,  09:33)
A5uKa, все работает правильно:

vcl60.bpl >____<

Цитата

начнет выводиться ноль ?!


не знаю, но это было одной из моих догадок (Привидение с типа BOOL)
в любом случае в Char мы получаем Смайли  smile 
Не уж то (char)True == '  smile  '

Автор: mes 8.1.2010, 14:04
Цитата(A5uKa @  8.1.2010,  11:39 Найти цитируемый пост)
в любом случае в Char мы получаем Смайли  smile 

смайлик получите не в char а при выводе значения как char.
напишите cout << (int)c; и увидите значение.

Цитата(A5uKa @  8.1.2010,  11:39 Найти цитируемый пост)
Не уж то (char)True == '  smile  ' 

ага. 
думаю Вам будет полезен для разбора этой ситуации следующий пример 
Код

void print_smile (bool flag)
{
    std::cout << (char) (1+flag);
}

int main() {

print_smile (true);
print_smile (false);
}


Автор: artsb 8.1.2010, 14:46
Цитата(A5uKa @  8.1.2010,  12:39 Найти цитируемый пост)
vcl60.bpl >____<

Проект на BCB 6

Автор: A5uKa 8.1.2010, 14:47
Цитата(mes @ 8.1.2010,  14:04)
Цитата(A5uKa @  8.1.2010,  11:39 Найти цитируемый пост)
в любом случае в Char мы получаем Смайли  smile 

смайлик получите не в char а при выводе значения как char.
напишите cout << (int)c; и увидите значение.

Однако всё же я вывожу значение char как char , значит там всё же смайл  smile 
Цитата

ага

только зачем 
Код

1+flag
 ...

Автор: artsb 8.1.2010, 14:47
mes, может лучше так:
Код

std::cout << (int) (char) (1+flag);

чтобы понятней было smile

Автор: A5uKa 8.1.2010, 14:50
Цитата(artsb @ 8.1.2010,  14:46)
Цитата(A5uKa @  8.1.2010,  12:39 Найти цитируемый пост)
vcl60.bpl >____<

Проект на BCB 6

я знаю даже то, что кто-то не убрал галочки в свойствах проекта  smile

Добавлено @ 14:53
Цитата(artsb @ 8.1.2010,  14:47)
mes, может лучше так:
Код

std::cout << (int) (char) (1+flag);

чтобы понятней было smile

Тогда это уже не смайл  smile 
И зачем 
Код

1+
 ???

может вы имели ввиду
Код

bool flag;
flag=true;
std::cout << (char)(int)(flag);

то, что 1 - это смайл, а - 0 соотвественно пробел ... ну я знаю >_<

Автор: artsb 8.1.2010, 14:54
Цитата(A5uKa @  8.1.2010,  14:50 Найти цитируемый пост)
я знаю даже то, что кто-то не убрал галочки в свойствах проекта

Эт да. Чтобы по легче был. Я же не знал, что у тебя среды нет. Но судя по всему, он уже и не нужен. Уже и так разобрались.  smile 

Автор: A5uKa 8.1.2010, 15:00
Цитата(artsb @ 8.1.2010,  14:54)
Цитата(A5uKa @  8.1.2010,  14:50 Найти цитируемый пост)
я знаю даже то, что кто-то не убрал галочки в свойствах проекта

Эт да. Чтобы по легче был. Я же не знал, что у тебя среды нет. Но судя по всему, он уже и не нужен. Уже и так разобрались.  smile

 smile 
Я боюсь устанавливать - ведь работать прийдётся >_<
Завтра установлю и буду мучать мою старую тему про нашествие терминаторов
http://forum.vingrad.ru/forum/topic-285001.html

Автор: mes 8.1.2010, 15:16
Цитата(A5uKa @  8.1.2010,  13:50 Найти цитируемый пост)
может вы имели ввиду

нет: я имел в ввиду именно 1+flag.
Вы бы попробовали .. запустили бы.. Дело в том что служебные символы (с кодами 0-31) не ограничиваются одним смайликом..
в примере в зависимости от флага будет печататься либо норамльный, либо инверсный смайлик.



Автор: mes 8.1.2010, 15:33
вот набросал еще один примерчик, надеюсь поинтересней:

Код

const unsigned MinCard = 6;
const unsigned MaxCard = 14;

void print_card (std::ostream& out, unsigned id, unsigned char color)
{
    static const char * highcards = "BDKA";
    static const unsigned hc_id = 11;
    
    if (id < MinCard || id > MaxCard) return;
    if (id < hc_id )  out << id;
    else              out << highcards[id - hc_id];
    
    out << char(3 + color % 4);    
}


int main() {

   for (int card = MinCard; card <= MaxCard; ++card)
   {
     for (char clr = 0; clr < 4; ++clr )
     {
         std::cout.width(3);
         print_card (std::cout, card, clr);
         std::cout << " ";
     }
     std::cout << std::endl;
   }
}

Автор: mes 8.1.2010, 15:55
чего то потянуло меня на консоль..
предыдущие два примера могут пригодиться при составлении консольной игры карты,
вот еще один в довесок для определения значка пола противника :
Код

char gender_char (unsigned id)
{ 
    static const char data [] = { 11, 12, 15 };
    return data [ (id<3)? id : 2 ];            
}

int main() {

    for (unsigned i =0; i<3; ++i)
      std::cout << gender_char (i)<<" ";
}


Автор: mes 8.1.2010, 16:17
вот еще один примерчик..правда мало применимый, но для разбора пойдет :
кричащий и мигающий смайлик;

Код

    static const char data [] = {1,7,8,2,7,8 } ; // магические числа :)

    std::cout << std::endl << "    ";
    
    for (int i=10; --i; )
      for (int j=0; j<6; ++j)
        std::cout << data[j];

Автор: artsb 8.1.2010, 17:16
mes сам себе приятный... smile

Автор: mes 8.1.2010, 17:56
Цитата(artsb @  8.1.2010,  16:16 Найти цитируемый пост)
сам себе приятный...

сам себе это как ?!  smile 

Автор: artsb 8.1.2010, 18:54
Цитата(mes @  8.1.2010,  17:56 Найти цитируемый пост)
сам себе это как ?! 

т.е. никто тебе не нужен. smile Разговариваешь сам с собой.
Без обид  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)