Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
dima__
0 / 0 / 0
Регистрация: 29.03.2014
Сообщений: 20
#1

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

01.07.2014, 12:48. Просмотров 1219. Ответов 13
Метки нет (Все метки)

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++? Заранее спасибо!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.07.2014, 12:48
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Присвоение в условии цикла while (C++):

Ошибка в условии цикла - C++
Кароч пишу крестики-нолики и тут на пути появилась непонятная ошибка int cell; if (num==1) { cout &lt;&lt;...

Логическое ИЛИ в условии цикла while - C++
Доброго времени суток. Комрады, ситуация следующая, цикл должен завершатся после введения одного из каких-либо 2-х (или более) символов....

Операторы в условии выполнения цикла while - C++
do{ m = atof(p); if (i&gt;9) break; }while(p = strchr(p, ','), p++); Объясните, пожалуйста, что означает последняя строка? Это...

При любом условии вылетает из цикла - C++
while(str.empty()==false){ cout&lt;&lt;&quot;выберите операцию&quot;&lt;&lt;endl&lt;&lt;&quot;1.Добавить элемент&quot;&lt;&lt;endl; int k=0; cin&gt;&gt;k;//если убрать cin&gt;&gt;k...

Битовая инверсия переменной в условии цикла for - C++
Доброго времени суток. Возможно ли ещё как-то использовать/применять конструкцию с битовой инверсией итератора в условии цикла for? ...

Вычисление арифметических выражений в условии цикла с параметром - C++
Здравствуйте! Объясните, пожалуйста. Уже, вроде, кучу сайтов перечитал, но так и не нашел ответа. Есть цикл for (i = st1.length()-1;...

13
castaway
Эксперт С++
4920 / 3028 / 372
Регистрация: 10.11.2010
Сообщений: 11,085
Записей в блоге: 10
Завершенные тесты: 1
01.07.2014, 13:03 #2
Значение *pa присваивается *pb, и если оно не равно нулю то цикл продолжается.
0
dima__
0 / 0 / 0
Регистрация: 29.03.2014
Сообщений: 20
03.08.2014, 16:43  [ТС] #3
а если написать просто while (( *pa)!='\0') ведь, насколько я понял, цикл должен работать пока исходная строка не закончится, то почему-то не получается. Какую роль играет присвоение *pb = *pa?
0
gru74ik
Эксперт CЭксперт С++
4278 / 1866 / 198
Регистрация: 20.02.2013
Сообщений: 4,997
Записей в блоге: 22
03.08.2014, 16:50 #4
Цитата Сообщение от dima__ Посмотреть сообщение
И нет разницы писать pb++ или *pb++?
Есть, и существенная.
0
GetHelp
-7 / 61 / 6
Регистрация: 27.02.2013
Сообщений: 1,112
03.08.2014, 16:52 #5
Цитата Сообщение от dima__ Посмотреть сообщение
И нет разницы писать pb++ или *pb++?
pb++ увеличивает значение указателя (сдвигает его)
*pb++ увеличивает значение переменной записанной по адресу куда указывает указатель
0
gru74ik
Эксперт CЭксперт С++
4278 / 1866 / 198
Регистрация: 20.02.2013
Сообщений: 4,997
Записей в блоге: 22
03.08.2014, 17:01 #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;
}
0
Миниатюры
Присвоение в условии цикла while  
gru74ik
Эксперт CЭксперт С++
4278 / 1866 / 198
Регистрация: 20.02.2013
Сообщений: 4,997
Записей в блоге: 22
03.08.2014, 17:07 #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; 
}
0
Mr.X
Эксперт С++
3054 / 1699 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
03.08.2014, 17:52 #8
Цитата Сообщение от GetHelp Посмотреть сообщение
*pb++ увеличивает значение переменной записанной по адресу куда указывает указатель
Цитата Сообщение от gru74ik Посмотреть сообщение
Если Вы пишите в коде pb - то это адрес той переменной, на которую указывает указатель pb. А если Вы пишите в коде *pb - то это значение, которое лежит в той переменной, на которую указывает указатель pb. Соответственно, инкремент адреса (то есть запись в коде pb++) даст смещение на одну позицию в массиве (поскольку в Вашем случае изначально указатель ссылается на первый элемент массива), а инкремент значения даст прибавку единицы к тому значению, которое лежит в переменной, на которую указывает указатель.
Постфиксные операторы имеют приоритет над префиксными, поэтому в выражении *pb++ инкрементируется указатель.
0
GetHelp
-7 / 61 / 6
Регистрация: 27.02.2013
Сообщений: 1,112
03.08.2014, 18:10 #9
Цитата Сообщение от Mr.X Посмотреть сообщение
Постфиксные операторы имеют приоритет над префиксными, поэтому в выражении *pb++ инкрементируется указатель.
не думаю, вы же не станете спорить что ++pb выполнится раньше чем pb++?
0
gru74ik
Эксперт CЭксперт С++
4278 / 1866 / 198
Регистрация: 20.02.2013
Сообщений: 4,997
Записей в блоге: 22
03.08.2014, 18:27 #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;
}
0
Mr.X
Эксперт С++
3054 / 1699 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
03.08.2014, 19:03 #11
Цитата Сообщение от gru74ik Посмотреть сообщение
*pb++ = *pa++; // Сперва происходит разыменование указателя pb, // затем инкремент указателя pb - теперь pb будет // указывать на следующий элемент массива b[]. Затем // то же самое происходит с указателем pa: происходит // разыменование указателя pa, затем инкремент указателя // pa - теперь pa будет указывать на следующий элемент // массива a[]. Затем присваиваем значение, на которое // указывает теперь указатель pa, элементу массива, на // который теперь указывает указатель pb.
Немножко наоборот. Сначала происходит присваивание значений, а потом инкременты указателей.

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

Добавлено через 8 минут
Вот все ругаем Страуструпа, а для кого он целую страницу отвел для разбора этого выражения в пункте 6.2.5.?
0
gru74ik
Эксперт CЭксперт С++
4278 / 1866 / 198
Регистрация: 20.02.2013
Сообщений: 4,997
Записей в блоге: 22
03.08.2014, 19:07 #12
Цитата Сообщение от Mr.X Посмотреть сообщение
Сначала происходит присваивание значений, а потом инкременты указателей.
А я чё сказал? Я так и сказал - сперва разыменование указателей (разыменование - операция взятия значения, то что со звёздочкой там), потом инкремент, потом присваивание одной части выражения другому.
0
Mr.X
Эксперт С++
3054 / 1699 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
03.08.2014, 19:11 #13
Цитата Сообщение от gru74ik Посмотреть сообщение
А я чё сказал? Я так и сказал - сперва разыменование указателей (разыменование - операция взятия значения, то что со звёздочкой там), потом инкремент, потом присваивание одной части выражения другому.
Ну, если строго, то сначала инкремент, так как он имеет наивысший приоритет, но, так как он постфиксный, то в выражении используются старые значения указателей, затем разыменование и присваивание старых значений.
0
dima__
0 / 0 / 0
Регистрация: 29.03.2014
Сообщений: 20
03.08.2014, 22:36  [ТС] #14
Цитата Сообщение от gru74ik Посмотреть сообщение
while *((*pb = *pa)!='\0')
* * * // Запись (*pb = *pa)!='\0' означает: сохранить значение, на которое
* * * // указывает указатель pa в переменную, на которую указывает указатель pb,
* * * // и если это значение не символ \0, то продолжить цикл
Маленький уточняющий вопрос - выражение while (( *pa)!='\0') вставленное вместо ((*pb = *pa)!='\0') делает код нерабочим. Но почему? Ведь и в первом и во втором случае цикл должен остановиться когда *pa = '\0'?
0
03.08.2014, 22:36
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.08.2014, 22:36
Привет! Вот еще темы с ответами:

Нюансы синтаксиса: что значит std::cin в условии цикла while? - C++
do { int v1, v2; cout &lt;&lt; &quot;Please enter two numbers of sum:&quot;; if (cin &gt;&gt; v1, v2) cout &lt;&lt; &quot;Sum is: &quot; &lt;&lt; v1 + v2 &lt;&lt; endl; ...

Применение цикла if для определения простых чисел. If внутри цикла for - 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++
вывод на экран чисел 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12, с использованием одного цикла и что бы все printf были только в теле...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru