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

Указатели в массиве - C++

Восстановить пароль Регистрация
 
aleksand
21 / 9 / 2
Регистрация: 18.06.2011
Сообщений: 185
25.09.2012, 10:44     Указатели в массиве #1
В книжке нет описания к данному коду и мне немного не понятно в некоторых моментах: 1). while (*p) { (не понятно какое условие понимается под *p) 2). while(*p!=' ' && *p) { (*p!= ' ' - это понятно, что если будет пробел, а вот && *p - это что за условие?)
Ответьте пожалуйста на мои вопросы и напишите краткое описание того, как работает программа, у меня в голове немного не укладывается что заем и почему.

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
#include <iostream>
#include <cstdio>
using namespace std;
 
int main()
{
    char str[80];
    char token[80];
    char *p, *q;
 
    cout << "Enter any message: \n";
    gets(str);
 
    p = str;
 
    while (*p) {
        q = token;
 
        while(*p!=' ' && *p) {
            *q = *p;
            q++; p++;
        }
        if(*p) p++;
        *q = '\0';
        cout << token << '\n';
    }
 
    system("pause");
    return 0;
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Nixy
ComfyMobile
 Аватар для Nixy
399 / 280 / 8
Регистрация: 24.07.2012
Сообщений: 916
25.09.2012, 10:46     Указатели в массиве #2
указывать на 0, в С++ 0 тождественно равен False
но p у тебя указывает на тип char и там
C++
1
'\0'
эквивалент 0
фактически проверяется конец строки
и программа выводит по отдельности разделенные пробелом символьные массивы("слова") до конца строки
aleksand
21 / 9 / 2
Регистрация: 18.06.2011
Сообщений: 185
25.09.2012, 10:49  [ТС]     Указатели в массиве #3
Цитата Сообщение от Nixy Посмотреть сообщение
указывать на 0, в С++ 0 тождественно равен False
Вы имеете ввиду первый вопрос как я понял. Т.е. конструкция типа while(*p) { - проверяет нет ли конца строки, т.е. знака \0 в конце, если есть то прекратить?
John Prick
754 / 687 / 123
Регистрация: 27.07.2012
Сообщений: 1,974
Завершенные тесты: 3
25.09.2012, 10:50     Указатели в массиве #4
Цитата Сообщение от aleksand Посмотреть сообщение
1). while (*p) { (не понятно какое условие понимается под *p)
*p - разыменовывание указателя p. Разыменовывая указатель, мы получаем значение той переменной, на которую он указывает. Отсюда while (*p) будет работать (в цикл будет заходить), пока то, на что указывает p будет отличным от нуля.

Цитата Сообщение от aleksand Посмотреть сообщение
2). while(*p!=' ' && *p) { (*p!= ' ' - это понятно, что если будет пробел, а вот && *p - это что за условие?)
*p - опять же, то же самое, что и выше. Условие: то, на что указывает p, не равно пробелу и отлично от нуля.

Здесь работа со строкой. Строки в С должны заканчиваться символом 0. Вот на него проверка и делается. Возможно, будет понятнее, если условия с *p заменить на (*p != '\0').
Fooly
 Аватар для Fooly
21 / 17 / 1
Регистрация: 26.03.2012
Сообщений: 147
25.09.2012, 10:52     Указатели в массиве #5
судя по всему p - это адрес, на который указывает указатель. Таким образом while (*р) означает "пока есть какое-то введенное значение str". Хотя я сам ничего теперь не понимаю =) Зачем пишется while(*p!=' ' && *p), если достаточно while(*p!=' ') на мой взгляд, ведь этот цикл уже вложен в первый цикл, в котором второе условие уже проверено while (*р). И что означает q = token; интересно, если q ничего не присвоено, то что присваивается token? Возможно это только часть программы в примере книжки? =) Либо я тугодум =D
Andsteadur
152 / 136 / 3
Регистрация: 23.05.2009
Сообщений: 275
25.09.2012, 10:54     Указатели в массиве #6
*p - разыменовываем указатель, получаем значение.
В условных операторах любое значение отличное от нуля дает true.

Добавлено через 1 минуту
while(*p!=' ' && *p) выполняется внутри цикла while (*р). Так что во избежание проблем по достижению конца строки тут тоже нужно проверять на нуль символ
Fooly
 Аватар для Fooly
21 / 17 / 1
Регистрация: 26.03.2012
Сообщений: 147
25.09.2012, 10:56     Указатели в массиве #7
Цитата Сообщение от Andsteadur Посмотреть сообщение
while(*p!=' ' && *p) выполняется внутри цикла while (*р). Так что во избежание проблем по достижению конца строки тут тоже нужно проверять на нуль символ
А поясните плз почему так надо? Разве первым циклом не проверится достижение нуль символа? Если достигнет конца строки то оно и не даст пройтись вложенному циклу.
Andsteadur
152 / 136 / 3
Регистрация: 23.05.2009
Сообщений: 275
25.09.2012, 10:58     Указатели в массиве #8
Простой пример:
C++
1
2
3
4
5
6
7
8
9
10
 // p = {'s', 't', 'r', '\0'};
        while (*p) {//*p = 's' => true
 
//если проверять только *p!=' ' , то мы пройдем нуль символ, залезем в память, 
//которая непонятно чем заполнена
        while(*p!=' ' && *p) { 
             p++;
        }
        if(*p) p++;
    }
т.е. это условие нужно для последнего слова в строке, которое заканчивается не пробелом, а символом конца строки.
Fooly
 Аватар для Fooly
21 / 17 / 1
Регистрация: 26.03.2012
Сообщений: 147
25.09.2012, 11:05     Указатели в массиве #9
Цитата Сообщение от Andsteadur Посмотреть сообщение
Простой пример:
C++
1
2
3
4
5
6
7
8
9
10
 // p = {'s', 't', 'r', '\n'};
        while (*p) {//*p = 's' => true
 
//если проверять только *p!=' ' , то мы пройдем нуль символ, залезем в память, 
//которая непонятно чем заполнена
        while(*p!=' ' && *p) { 
             p++;
        }
        if(*p) p++;
    }
т.е. это условие нужно для последнего слова в строке, которое заканчивается не пробелом, а символом конца строки.
непонятно ничего=(
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
while (*p) { //мы проверяем здесь, и входим в цикл, если *p не является /0
        q = token;
 
        while(*p!=' ' && *p) { //т.к мы уже проверили и знаем, что *p не является концом строки, 
                                      // то достаточно проверить не является ли *р пробелом. 
                                      // Зачем проверять второй раз, если мы уже знаем, что *р - не конец строки???
            *q = *p;
            q++; p++;
        }
        if(*p) p++;
        *q = '\0';
        cout << token << '\n';
    }
aleksand
21 / 9 / 2
Регистрация: 18.06.2011
Сообщений: 185
25.09.2012, 11:05  [ТС]     Указатели в массиве #10
Теперь стало ясно как работает программа. Всем спасибо, вопрос исчерпан.
Nixy
ComfyMobile
 Аватар для Nixy
399 / 280 / 8
Регистрация: 24.07.2012
Сообщений: 916
25.09.2012, 11:08     Указатели в массиве #11
Fooly, если ты уберешь это условие то
C++
1
2
3
4
while(*p!=' ') {
            *q = *p;
            q++; p++;
        }
будет работать вечно так как в конце последнего слова p указывает не на ' ' а на '\0' они не равны
Fooly
 Аватар для Fooly
21 / 17 / 1
Регистрация: 26.03.2012
Сообщений: 147
25.09.2012, 11:15     Указатели в массиве #12
Цитата Сообщение от aleksand Посмотреть сообщение
Теперь стало ясно как работает программа. Всем спасибо, вопрос исчерпан.
Мне вообще ничего не понятно теперь Поясните мне всё
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
while (*p) { //мы проверяем здесь, и входим в цикл, если *p не является /0
        q = token;
 
        while(*p!=' ' && *p) { //т.к мы уже проверили и знаем, что *p не является концом строки, 
                                      // то достаточно проверить не является ли *р пробелом. 
                                      // Зачем проверять второй раз, если мы уже знаем, что *р -                                    
                                     //  не конец строки???
            *q = *p;
            q++; p++;
        }
        if(*p) p++; //Опять 25. Зачем тут if объясните?
        *q = '\0';   // ???
        cout << token << '\n'; // и что нам тут выведет? ничего же ведь не выведет? а когда 
                                       // тут что-нибудь выводиться будет? никогда же, зачем тогда писать?
    }
Nixy
ComfyMobile
 Аватар для Nixy
399 / 280 / 8
Регистрация: 24.07.2012
Сообщений: 916
25.09.2012, 11:17     Указатели в массиве #13
Fooly, я же вверху ответил посмотри внимательно
C++
1
if(*p) p++; //Опять 25. Зачем тут if объясните?
операция p++ увеличивает адрес на величину типа ,на который указывает , то есть происходит смещение в право и мы движемся по строке , как я писал в теме '\0' конец строки эквивалент 0 и false соответственно , дальше конца строки двигатся мы не должны , это будет считатся выходом за пределы символьного массива
Fooly
 Аватар для Fooly
21 / 17 / 1
Регистрация: 26.03.2012
Сообщений: 147
25.09.2012, 11:18     Указатели в массиве #14
Цитата Сообщение от Nixy Посмотреть сообщение
Fooly, если ты уберешь это условие то
C++
1
2
3
4
while(*p!=' ') {
            *q = *p;
            q++; p++;
        }
будет работать вечно так как в конце последнего слова p указывает не на ' ' а на '\0' они не равны
Т.е сразу первый цикл проверяет не по одному символу, а сразу загружает весь массив? Если так, то понятно. А я думал по одному символу проверяет из массива. Или я опять неправильно понял?

ЗЫ
оно же по одному всё-таки символу проверяет начиная с нулевого. Тогда почему не написать

C++
1
2
3
4
if(*p!=' ') {
            *q = *p;
            q++; p++;
        }
и почему этот цикл не будет также бесконечным?
C++
1
2
3
4
   while(*p!=' ' && *p) {
            *q = *p;
            q++; p++;
        }
У меня сейчас опять взорвётся мозг, т.к у меня ничего не может уложиться в голове =) Видать я с этими указателями дуб дубом, но сколько не читал, вс равно с ними постоянно проблемы =(
Nixy
ComfyMobile
 Аватар для Nixy
399 / 280 / 8
Регистрация: 24.07.2012
Сообщений: 916
25.09.2012, 11:27     Указатели в массиве #15
первое условие проверяет конец всей строки , второе проверяет конец строки + конец отрезка строки "слова" разделеного пробелом ' ' для того чтобы обновить q
C++
1
2
3
4
5
6
7
8
9
10
11
while (*p) { //мы проверяем здесь, и входим в цикл, если *p не является /0
        q = token; // тут q указывает на массив символов token а точнее на все что в ней записано до первого '\0' и так далее
 
        while(*p!=' ' && *p) {
            *q = *p; // тут в q записывается содержимое p
            q++; p++;
        }
        if(*p) p++; //Объяснил чуть выше
        *q = '\0';   // переход на следующую строку в массиве token
        cout << token << '\n'; // а выводить будет то что было записано в q
    }
Добавлено через 1 минуту
Fooly, есть такая клевая штука дебаг режим , пока твой мозг не стал компилятором кода используй его и проверяй все что происходит, в будующем если ты будешь усложнять код и не понимать что там происходит , будешь разбивать его на части , и также дебагом пробегать , пока твой мозг не станет компилятором
Fooly
 Аватар для Fooly
21 / 17 / 1
Регистрация: 26.03.2012
Сообщений: 147
25.09.2012, 11:36     Указатели в массиве #16
Так, я практически всё понял кроме одного... так сказать
Допустим у нас записан массив "stasik mihajlov/0"
Первый цикл
C++
1
while (*p)
проверяет по одному символу, праивльно? Т.е сначала буковку "s", потом "t" итд.
Когда же доходим до "/0", то мы не входим даже в цикл. И вообще цикл закончится на этом. Правильно? =)
Так вот... Хоть убейте, но я не понимаю зачем нам проверять
C++
1
while(*p!=' ' && *p)
если мы знаем, что *p не может быть равным /0
И более того, я не понимаю зачем тут цикл while, если правильнее (на мой взгляд) будет иф
C++
1
2
3
4
if(*p!=' ') {
            *q = *p;
            q++; p++;
        }
и Опять
C++
1
if(*p) p++;
я понял что мне написали выше, но я не пойму зачем он тут, если опять-таки *p никак не может быть тут равен /0 , т.к мы не войдём даже в вышестоящий цикл while.
Извиняюсь, что я туплю, но я хочу полностью понять это ситуацию, чтобы больше не возникало вопросов =)

PS сейчас всё прокомпилирую, и если разберусь, то сниму все вопросы, а пока убирать свои дотошные вопросики убирать отсюда не буду
Nixy
ComfyMobile
 Аватар для Nixy
399 / 280 / 8
Регистрация: 24.07.2012
Сообщений: 916
25.09.2012, 11:48     Указатели в массиве #17
Цитата Сообщение от Fooly Посмотреть сообщение
никак не может быть тут равен /0
не верно посмотри внимательно где у тебя инкримент p он какраз внутри цикла
C++
1
2
3
4
 while(*p!=' ' && *p) {// если слово было последним у него в конце стоит   '/0'     а не ' '                               
            *q = *p;
            q++; p++;// тут мы сдвигаемся в право и если конец и убрать условие будем делать это вечно ну либо пока в муссоре не попадется нам ' '
        }
C++
1
if(*p) p++;// чтоб не уйти дальше конца строки иначе мы сдвинемся дальше в муссор там не '/0' и внешний цикл продолжит работу
Fooly
 Аватар для Fooly
21 / 17 / 1
Регистрация: 26.03.2012
Сообщений: 147
25.09.2012, 11:55     Указатели в массиве #18
Что загружает
C++
1
while (*p)
1 символ (как я думаю, но мне уже кажется, что так не может быть) или сразу всё слово до пробела? Если всё слово, то всё понятно в коде. ТОлько теперь я не понимаю, почему оно загружает слово сразу, а не по символам?
Andsteadur
152 / 136 / 3
Регистрация: 23.05.2009
Сообщений: 275
25.09.2012, 12:51     Указатели в массиве #19
C++
1
while (*p)
цикл выполняется пока символ, который хранится по адресу p не является нуль символом. Дальше в цикле мы изменяем указатель (++p) и он начинает указывать на другой участок паяти, который хранит другой символ.

Добавлено через 9 минут
Т.е. если p = {'a', 'b', '\0'}, то *p указывает на 'a'
C++
1
2
3
4
5
6
while (*p) {
         while(*p!=' ' && *p) {
                  p++;
        }
        if(*p) p++;
}
Bот так будет выполняться участок кода для p = {'a', 'b', '\0'};

1. Строка 1: разыменовываем указатель *p = 'a', значение отличное от нуля поэтому выполняем итерацию цикла
2. Строка 2: *p != ' ' и *p != 0 (т.к. *p='a'). Выполняем итерацию вложенного цикла
3. Строка 3: смещаем указатель p. p теперь указывает на 'b'
4. Строка 4: конец итерации вложенного цикла
5. Строка 2: *p != ' ' и *p != 0 (т.к. *p='b'). Выполняем итерацию вложенного цикла
6. Строка 3: смещаем указатель p. p теперь указывает на '\0'
7. Строка 2: *p != ' ' и *p == 0 (т.к. *p='\0'). Закончить выполнение вложенного цикла
8. Строка 5: *p == 0 (т.к. *p='\0'). Не входим в true-блок.
9. Строка 6: конец итерации главного цикла.
10. Строка 1: *p == 0 (т.к. *p='\0'). Закончить выполнение главного цикла
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.09.2012, 13:11     Указатели в массиве
Еще ссылки по теме:

Указатели в массиве на сортировку C++
Найти сумму положительных элементов в массиве через указатели C++
Указатели на объекты в массиве C++

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

Или воспользуйтесь поиском по форуму:
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
25.09.2012, 13:11     Указатели в массиве #20
Цитата Сообщение от aleksand Посмотреть сообщение
не понятно какое условие понимается под *p
указывает на не нулевой символ. Что здесь сложного?
Yandex
Объявления
25.09.2012, 13:11     Указатели в массиве
Ответ Создать тему
Опции темы

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