Форум программистов, компьютерный форум CyberForum.ru

Присвоение в условии цикла while - C++

Восстановить пароль Регистрация
 
dima__
0 / 0 / 0
Регистрация: 29.03.2014
Сообщений: 20
01.07.2014, 12:48     Присвоение в условии цикла while #1
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
void main ()
{
      char a[140],b[140],*pa=a,*pb=b;
      /* -------------------------------- */
      cout << "Enter word..."; gets(a);
      int pr = 2*strlen(a);
      *(pb+pr+1) = '\0';
      while  ((*pb = *pa)!='\0')
      {
         pb++; 
        *pb++ = *pa++;
      }
      cout << "\n Result:"; puts(b);
}

Доброе время суток! Подскажите, каким образом работает while ((*pb = *pa)!='\0') , по типу логического выражения? если можно присвоить указателю pb значение указателя pa, тогда true? И нет разницы писать pb++ или *pb++? Заранее спасибо!
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.07.2014, 12:48     Присвоение в условии цикла while
Посмотрите здесь:

Применяя оператор цикла FOR вычислить y. Оператор if в теле цикла не использовать. Значение m и n вводить с клавиатуры. C++
При любом условии вылетает из цикла C++
вывод на экран чисел 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12, с использованием одного цикла и что бы все printf были только в теле цикла C++
Используя одну переменную цикла укажите возможные способы объявления заголовка счетного цикла. C++
Операторы в условии выполнения цикла while C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
castaway
Эксперт С++
4842 / 2981 / 367
Регистрация: 10.11.2010
Сообщений: 11,013
Записей в блоге: 10
Завершенные тесты: 1
01.07.2014, 13:03     Присвоение в условии цикла while #2
Значение *pa присваивается *pb, и если оно не равно нулю то цикл продолжается.
dima__
0 / 0 / 0
Регистрация: 29.03.2014
Сообщений: 20
03.08.2014, 16:43  [ТС]     Присвоение в условии цикла while #3
а если написать просто while (( *pa)!='\0') ведь, насколько я понял, цикл должен работать пока исходная строка не закончится, то почему-то не получается. Какую роль играет присвоение *pb = *pa?
gru74ik
Модератор
 Аватар для gru74ik
3116 / 1342 / 167
Регистрация: 20.02.2013
Сообщений: 3,809
Записей в блоге: 17
03.08.2014, 16:50     Присвоение в условии цикла while #4
Цитата Сообщение от dima__ Посмотреть сообщение
И нет разницы писать pb++ или *pb++?
Есть, и существенная.
GetHelp
-8 / 60 / 6
Регистрация: 27.02.2013
Сообщений: 1,112
03.08.2014, 16:52     Присвоение в условии цикла while #5
Цитата Сообщение от dima__ Посмотреть сообщение
И нет разницы писать pb++ или *pb++?
pb++ увеличивает значение указателя (сдвигает его)
*pb++ увеличивает значение переменной записанной по адресу куда указывает указатель
gru74ik
Модератор
 Аватар для gru74ik
3116 / 1342 / 167
Регистрация: 20.02.2013
Сообщений: 3,809
Записей в блоге: 17
03.08.2014, 17:01     Присвоение в условии цикла while #6
Цитата Сообщение от dima__ Посмотреть сообщение
И нет разницы писать pb++ или *pb++?
Если Вы пишите в коде pb - то это адрес той переменной, на которую указывает указатель pb. А если Вы пишите в коде *pb - то это значение, которое лежит в той переменной, на которую указывает указатель pb. Соответственно, инкремент адреса (то есть запись в коде pb++) даст смещение на одну позицию в массиве (поскольку в Вашем случае изначально указатель ссылается на первый элемент массива), а инкремент значения даст прибавку единицы к тому значению, которое лежит в переменной, на которую указывает указатель.

Добавлено через 5 минут
Чтобы было понятнее, вот Вам простой пример из книги Стивена Праты:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// pointer.срр -- наша первая переменная-указатель
 
#include <iostream> 
int main() 
{ 
    using namespace std;
     
    int updates =6;         // объявление переменной 
    int * p_updates;        // объявление указателя на int 
    p_updates = &updates;   // присвоить адрес int указателю
    
    // Выразить значения двумя способами:
    cout << "Values: updates = " << updates; 
    cout << ", *p_updates = " << *p_updates << endl;
    
    // Выразить адреса двумя способами:
    cout << "Addresses: &updates = " << &updates; 
    cout << ", p_updates = " << p_updates << endl;
    
    // Изменить значение через указатель:
    *p_updates = *p_updates + 1;
     
    cout << "Now updates = " << updates << endl;
     
    return 0;
}
Миниатюры
Присвоение в условии цикла while  
gru74ik
Модератор
 Аватар для gru74ik
3116 / 1342 / 167
Регистрация: 20.02.2013
Сообщений: 3,809
Записей в блоге: 17
03.08.2014, 17:07     Присвоение в условии цикла while #7
И вот ещё из той же книги про указатели и массивы:
Кликните здесь для просмотра всего текста

Цитата Сообщение от Стивен Прата
Родство указателей и имен массивов происходит из арифметики указателей, а также
того, как язык C++ внутренне работает с массивами. Сначала рассмотрим арифметику
указателей. Добавление единицы к целочисленной переменной увеличивает ее
значение на единицу, но добавление единицы к переменной типа указателя увеличивает ее
значение на количество байт, составляющих размер типа, на который она указывает.
Добавление единицы к указателю на double добавляет 8 байт к числовой величине
указателя на системах с 8-байтным double, в то время как добавление единицы к
указателю на short добавляет к его значению 2 байта. Код в листинге 4.19 доказывает
истинность этого утверждения. Он также демонстрирует еще один важный момент:
C++ интерпретирует имена массивов как адреса.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Листинг 4.19. addpntrs.cpp -- pointer addition
#include <iostream>
int main()
{
    using namespace std;
    double wages[3] = {10000.0, 20000.0, 30000.0};
    short stacks[3] = {3, 2, 1};
 
// Here are two ways to get the address of an array
    double * pw = wages;     // name of an array = address
    short * ps = &stacks[0]; // or use address operator
// with array element
    cout << "pw = " << pw << ", *pw = " << *pw << endl;
    pw = pw + 1;
    cout << "add 1 to the pw pointer:\n";
    cout << "pw = " << pw << ", *pw = " << *pw << "\n\n";
 
    cout << "ps = " << ps << ", *ps = " << *ps << endl;
    ps = ps + 1;
    cout << "add 1 to the ps pointer:\n";
    cout << "ps = " << ps << ", *ps = " << *ps << "\n\n";
 
    cout << "access two elements with array notation\n";
    cout << "stacks[0] = " << stacks[0] 
         << ", stacks[1] = " << stacks[1] << endl;
    cout << "access two elements with pointer notation\n";
    cout << "*stacks = " << *stacks
         << ", *(stacks + 1) =  " << *(stacks + 1) << endl;
 
    cout << sizeof(wages) << " = size of wages array\n";
    cout << sizeof(pw) << " = size of pw pointer\n";
    // cin.get();
    return 0; 
}
Mr.X
Эксперт С++
 Аватар для Mr.X
2801 / 1577 / 247
Регистрация: 03.05.2010
Сообщений: 3,663
03.08.2014, 17:52     Присвоение в условии цикла while #8
Цитата Сообщение от GetHelp Посмотреть сообщение
*pb++ увеличивает значение переменной записанной по адресу куда указывает указатель
Цитата Сообщение от gru74ik Посмотреть сообщение
Если Вы пишите в коде pb - то это адрес той переменной, на которую указывает указатель pb. А если Вы пишите в коде *pb - то это значение, которое лежит в той переменной, на которую указывает указатель pb. Соответственно, инкремент адреса (то есть запись в коде pb++) даст смещение на одну позицию в массиве (поскольку в Вашем случае изначально указатель ссылается на первый элемент массива), а инкремент значения даст прибавку единицы к тому значению, которое лежит в переменной, на которую указывает указатель.
Постфиксные операторы имеют приоритет над префиксными, поэтому в выражении *pb++ инкрементируется указатель.
GetHelp
-8 / 60 / 6
Регистрация: 27.02.2013
Сообщений: 1,112
03.08.2014, 18:10     Присвоение в условии цикла while #9
Цитата Сообщение от Mr.X Посмотреть сообщение
Постфиксные операторы имеют приоритет над префиксными, поэтому в выражении *pb++ инкрементируется указатель.
не думаю, вы же не станете спорить что ++pb выполнится раньше чем pb++?
gru74ik
Модератор
 Аватар для gru74ik
3116 / 1342 / 167
Регистрация: 20.02.2013
Сообщений: 3,809
Записей в блоге: 17
03.08.2014, 18:27     Присвоение в условии цикла while #10
Вот, попытался разобраться с Вашим кодом:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
 
using namespace std;
int main ()
{
      char a[140], b[140];
 
      char * pa=a;  // указатель pa теперь будет указывать
                    // на первый элемент массива a[]
 
      char * pb=b;  // указатель pb теперь будет указывать
                    // на первый элемент массива b[]
 
      /* -------------------------------- */
      cout << "Enter word: ";
      gets(a);  // функция для чтения строк в стиле C (сишный аналог плюсового cin)
      int pr = 2 * strlen(a);   // узнаём длину строки a[], умножаем её на 2
                                // и присваиваем получившееся значение
                                // переменной pr
      *(pb+pr+1) = '\0';    // массив b теперь будет вдвое длиннее массива а
                            // и последним символом массива b будет символ \0
                            // что сделает его строкой в стиле С
                            
      while  ((*pb = *pa)!='\0')
      // Запись (*pb = *pa)!='\0' означает: сохранить значение, на которое
      // указывает указатель pa в переменную, на которую указывает указатель pb,
      // и если это значение не символ \0, то продолжить цикл
      {
         pb++;  // перейти к следующему элементу массива b[]
         
        *pb++ = *pa++;  // Сперва происходит разыменование указателя pb,
                        // затем инкремент указателя pb - теперь pb будет
                        // указывать на следующий элемент массива b[]. Затем
                        // то же самое происходит с указателем pa: происходит
                        // разыменование указателя pa, затем инкремент указателя 
                        // pa - теперь pa будет указывать на следующий элемент
                        // массива a[]. Затем присваиваем значение, на которое
                        // указывает теперь указатель pa, элементу массива, на
                        // который теперь указывает указатель pb.
                        
      }
      cout << "\n Result: ";
      puts(b);  // Вывести строку b на экран (сишный аналог плюсового cout)
 
      return 0;
}
Mr.X
Эксперт С++
 Аватар для Mr.X
2801 / 1577 / 247
Регистрация: 03.05.2010
Сообщений: 3,663
03.08.2014, 19:03     Присвоение в условии цикла while #11
Цитата Сообщение от gru74ik Посмотреть сообщение
*pb++ = *pa++; // Сперва происходит разыменование указателя pb, // затем инкремент указателя pb - теперь pb будет // указывать на следующий элемент массива b[]. Затем // то же самое происходит с указателем pa: происходит // разыменование указателя pa, затем инкремент указателя // pa - теперь pa будет указывать на следующий элемент // массива a[]. Затем присваиваем значение, на которое // указывает теперь указатель pa, элементу массива, на // который теперь указывает указатель pb.
Немножко наоборот. Сначала происходит присваивание значений, а потом инкременты указателей.

Добавлено через 10 минут
Цитата Сообщение от GetHelp Посмотреть сообщение
не думаю
А чего тут думать, учить надо. И первое - это выучить таблицу приоритетов операторов наизусть, так как в C++ их количество сравнимо с количеством ключевых слов, чтобы не ставить лишних скобок и не затрудняться при чтении кода. В Си приоритет операторов неплохо продуман, так что скобки ставить почти не приходится.

Добавлено через 8 минут
Вот все ругаем Страуструпа, а для кого он целую страницу отвел для разбора этого выражения в пункте 6.2.5.?
gru74ik
Модератор
 Аватар для gru74ik
3116 / 1342 / 167
Регистрация: 20.02.2013
Сообщений: 3,809
Записей в блоге: 17
03.08.2014, 19:07     Присвоение в условии цикла while #12
Цитата Сообщение от Mr.X Посмотреть сообщение
Сначала происходит присваивание значений, а потом инкременты указателей.
А я чё сказал? Я так и сказал - сперва разыменование указателей (разыменование - операция взятия значения, то что со звёздочкой там), потом инкремент, потом присваивание одной части выражения другому.
Mr.X
Эксперт С++
 Аватар для Mr.X
2801 / 1577 / 247
Регистрация: 03.05.2010
Сообщений: 3,663
03.08.2014, 19:11     Присвоение в условии цикла while #13
Цитата Сообщение от gru74ik Посмотреть сообщение
А я чё сказал? Я так и сказал - сперва разыменование указателей (разыменование - операция взятия значения, то что со звёздочкой там), потом инкремент, потом присваивание одной части выражения другому.
Ну, если строго, то сначала инкремент, так как он имеет наивысший приоритет, но, так как он постфиксный, то в выражении используются старые значения указателей, затем разыменование и присваивание старых значений.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.08.2014, 22:36     Присвоение в условии цикла while
Еще ссылки по теме:

Битовая инверсия переменной в условии цикла for C++
C++ Нахождение отрицательного цикла в графе и вывод цикла
C++ Ошибка в условии цикла

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
dima__
0 / 0 / 0
Регистрация: 29.03.2014
Сообщений: 20
03.08.2014, 22:36  [ТС]     Присвоение в условии цикла while #14
Цитата Сообщение от gru74ik Посмотреть сообщение
while *((*pb = *pa)!='\0')
* * * // Запись (*pb = *pa)!='\0' означает: сохранить значение, на которое
* * * // указывает указатель pa в переменную, на которую указывает указатель pb,
* * * // и если это значение не символ \0, то продолжить цикл
Маленький уточняющий вопрос - выражение while (( *pa)!='\0') вставленное вместо ((*pb = *pa)!='\0') делает код нерабочим. Но почему? Ведь и в первом и во втором случае цикл должен остановиться когда *pa = '\0'?
Yandex
Объявления
03.08.2014, 22:36     Присвоение в условии цикла while
Ответ Создать тему
Опции темы

Текущее время: 13:51. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru