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

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

Войти
Регистрация
Восстановить пароль
 
Dimka-novitsek
14 / 14 / 0
Регистрация: 26.04.2012
Сообщений: 1,091
#1

По. разобрать программу с указателями и массивами ( авторы Либерти, Дмитрий ) - C++

25.09.2013, 14:22. Просмотров 386. Ответов 3
Метки нет (Все метки)

Программа

В строках 26, 28 мы создаем массивы?

С помощю getline мы вводим строку. И о чудо! я вижу, что теперь в массиве не 225 символов, а столько, сколько
я вводил.

bool GetWord(char* string, char* word, int& wordOffset) указатели на массив? int& нну забыл, и не сображу, это что?

cout << "string[wordOffset]: " << string[wordOffset] << endl; ( стр.63 ) выводит 284 символа, причем сначала 4 строки бог знает каких символов и тут же без перехода введённую строку.

char *p1, *p2; (стр.71) самая непонятка!!!!! Это же указатель. Вот мы ег обьявили

p1 = p2 = string+wordOffset; Что же в нем хранится? Указатель? почему при прямом выводе выводится не адрес, а строка? Я ожидал, что так буде вывиден cout << "p1: " << p1 << endl;адрес, а так cout << "*p1: " <<*p1 << endl;
строка, однако строка выводится прямо!!

Мало того, при операции p1++; из строки сначала вычитается по символу на каждый шаг!! Как это???? Офигеть!!

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//Листинг 8.11. Выделение слов из массива символов
#include <string> 
#include <iostream> // для объекта cout
using namespace std;
 
#include<iomanip>
//Этот файл содержит большую часть манипуляторов C++. Если вы не знаете, что такое манипулятор, не беспокойтесь. Просто подключите это файл вместе с iostream, хуже не станет.
#include<fstream> 
//Подключается при работе с файлами.
 
 
 #include <ctype.h>
 
 #include <string.h>
 
 bool GetWord(char* string, char* word, int& wordOffset);
 
 // основная программа
 
 int main()
 
 {   char*  sprobuem;
 
     const int bufferSize = 255;
 
     char buffer[bufferSize+1]; // переменная для хранения всей строки
 
     char word[bufferSize+1]; // переменная для хранения слова
 
     int wordOffset = 0; // начинаем с первого символа
 
     cout << "Enter а string: ";  
 
     cin.getline(buffer,bufferSize);
 
     sprobuem=buffer; cout << "sprobuem: " << sprobuem << endl;
 
     
 
  while (GetWord(buffer,word,wordOffset))
 
   {
    cout << "Got this word: " << word << endl;
   }
 
 
 
  system("pause  ");return(0);
 
 }
 
 
 
 // Функция для выделения слова из строки символов.
 
 bool GetWord(char* string, char* word, int& wordOffset)
 
 {
 
     cout << "string: " << string << endl;
     cout << "word: " << word << endl;
     cout << "wordOffset: " << wordOffset << endl;
     cout << "string[wordOffset]: " << string[wordOffset] << endl;
 
    if (!string[wordOffset]) // определяет конец строки?
 
      return false;
 
 
 
    char *p1, *p2;
 
    p1 = p2 = string+wordOffset; // указатель на следующее слово
     cout << "p1: " << p1 << endl;
       cout << "p2: " << p2 << endl;
 
 
 
    // удаляем ведущие пробелы
       cout << "strlen(p1): " << strlen(p1) << endl;  cout << "isalnum(p1[0]): " << isalnum(p1[0]) << endl;
 
    for (int i = 0; i<(int)strlen(p1) && !isalnum(p1[0]); i++){// strlen Возвращает длину строки с завершающим нулевым символом
 
      p1++; //Функция isalnum() возвращает ненулевое значение, если ее аргумент ch является либо буквой, либо цифрой. 
      cout << "p1: " << p1 << endl; cout << "i: " << i << endl;}
 
 
    // проверка наличия слова
 
   // if (!iKalruj[n(pl[0]))
 
   //   return false;
 
 
 
    // указатель р1 показание начало сдолующего слова
 
    // iа к жо как и p2
 
    p2 = p1;  
 
 
 
    // перпмещавм p2 и конец олова
 
    while (isalnum(p2[0]))
 
    {   p2++;    cout << "p2++: " << p2 << endl; }
 
 
 
    // p2 указывает на конец слова
 
    // а p1 - в начало
 
    // разность указатолой показываот длину слова
 
    int len = int (p2 - p1);     cout << "len: " << len << endl;   cout << "p2 - p1: " << p2 - p1 << endl; 
 
 
 
    // копируем слово в буфер
 
    strncpy (word,p1,len);  // Функция strncpy() копирует до count символов из строки, адресуемой параметром str2, в массив, адресуемый параметром str1. Параметр str2 должен указывать на строку с завершающим нулевым символом.
 
    cout << "word: " << word << endl;   cout << "strlen(word): " << strlen(word) << endl;
 
 
 
    // и добавляем символ разрыва сроки
 
    word[len]='\0';   for (int i = 0; i<=len; i++) cout << "word[i]: " << word[i] << "    [i]: " << i  <<  endl;
    cout << "word: " << word << endl;
 
 
    // ищем начало следующего слова
 
    for (int i = int(p2-string); i<(int)strlen(string) && !isalnum(p2[0]); i++) // strlen Возвращает длину строки с завершающим нулевым символом
 
      p2++;   //Функция isalnum() возвращает ненулевое значение, если ее аргумент ch является либо буквой, либо цифрой. 
 
 
 
    wordOffset = int(p2-string);
 
 
 
    return true;
 
 }
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.09.2013, 14:22
Здравствуйте! Я подобрал для вас темы с ответами на вопрос По. разобрать программу с указателями и массивами ( авторы Либерти, Дмитрий ) (C++):

Разобрать код, демонстрирующий работу с указателями - C++
Здравствуйте. Помогите пожалуйста разобраться с работой указателей. #include &lt;iostream&gt; using namespace std; int main() { ...

Работа с массивами/указателями - C++
я чего-то туплю, задача такая, надо в i строку двумерного массива записать ptr_buffer. Вот код: но там получается, что во всех строчках...

Работа с массивами, указателями и функциями. - C++
Я вот рли не знаю, как отправить в свою созданную функцию массив, как потом обработанный массив в функции возвратить.Т.е., например...

Работа с указателями/массивами /функциями - C++
Запутался с указателями/в лабе нужно провести через указатели /Дан одномерный массив из К элементов. Получить из него матрицу, размером N x...

Разработка и реализация программ с указателями и динамическими одномерными массивами - C++
Составить программу, которая заполняет одномерный динамический массив с помощью случайных чисел, затем меняет массив. Примечание: ...

Особенности и порядок работы с указателями, обмен данными между динамическими массивами - C++
Написать программу обмена данными между двумя динамическими массивами,как можно проще. Заранее большое спасибо)

3
HedgehogLu
147 / 68 / 1
Регистрация: 04.09.2013
Сообщений: 260
25.09.2013, 16:09 #2
С помощю getline мы вводим строку. И о чудо! я вижу, что теперь в массиве не 225 символов, а столько, сколько
я вводил.
- каким образом вы определяете что там меньше 255? Массив как был так и остался на 255 символов, просто getline в конец строки добавляет 0 (символ конца строки) и поэтому отображаются только те символы которые считала функция getline, однако дальнейшие значения в массиве как были так и остались.

bool GetWord(char* string, char* word, int& wordOffset) указатели на массив? int& нну забыл, и не сображу, это что?
тут все просто последний параметр передается ссылкой. Соответственно все изменения значения данной переменной внутри функции отобразятся на передаваемой переменной, по сути сюда и будет возвращаться позиция в строке с которой начинается слово.

Не по теме:

Ох же блин и выводов на экран тут. наверное для дебага



cout << "string[wordOffset]: " << string[wordOffset] << endl; ( стр.63 ) выводит 284 символа, причем сначала 4 строки бог знает каких символов и тут же без перехода введённую строку.
а вы уверенны что именно в этой стоке проблема, т.к. тут выводится только 1 символ а вот
строка выше
cout << "word: " << word << endl;
по началу выведет кто знает что и вообще кажется может вызвать ошибку, т.к. память под word выделяется, а вот значения не инициализируется. А строка как нам известно выводится то символа окончания строки (а именно нуля), чего может не оказаться, т.к. кто его знает что было в той памяти что выделена ранее.

char *p1, *p2; (стр.71) самая непонятка!!!!! Это же указатель. Вот мы ег обьявили

p1 = p2 = string+wordOffset; Что же в нем хранится? Указатель? почему при прямом выводе выводится не адрес, а строка? Я ожидал, что так буде вывиден cout << "p1: " << p1 << endl;адрес, а так cout << "*p1: " <<*p1 << endl;
строка, однако строка выводится прямо!!
ну тут тоже все ясно р1 и р2 указатели но в то же время мы помним, что строки мы так же объявляем через указатели и потому при выводе р1 и р2 выводятся как строки.
опять таки string это ведь тоже указатель и хранит в себе адрес памяти где начинается строка. Соответственно мы знаем, что char занимает 1 байт памяти, поэтому string+wordOffset по сути эквивалентно &string[wordOffset] т.е. адрес смещенный в строке.
По такому-же принципу p1++ производит смещение на 1 символ
1
Dimka-novitsek
14 / 14 / 0
Регистрация: 26.04.2012
Сообщений: 1,091
25.09.2013, 18:44  [ТС] #3
Спасибо!!!!!

Добавлено через 1 час 57 минут
Вобще не понял где ошибка.

C++
1
2
3
4
5
6
7
8
9
sprobuem=buffer; cout << "sprobuem: " << sprobuem << endl;
 
     for (int i=0;i<bufferSize+10;i++0)
     {   cout << "sprobuem: " << sprobuem+i << endl;}
 
 
     
 
  while (GetWord(buffer,word,wordOffset))

1>d:\проги\widelenyeslovmassiva\widelenyeslovmassiva\widelenyeslovmassiva.cpp(38): error C2143: синтаксическая ошибка: отсутствие ")" перед "константа"
1>d:\проги\widelenyeslovmassiva\widelenyeslovmassiva\widelenyeslovmassiva.cpp(38): error C2059: синтаксическая ошибка: )
1>d:\проги\widelenyeslovmassiva\widelenyeslovmassiva\widelenyeslovmassiva.cpp(39): error C2143: синтаксическая ошибка: отсутствие ";" перед "{"
1>d:\проги\widelenyeslovmassiva\widelenyeslovmassiva\widelenyeslovmassiva.cpp(39): error C2065: i: необъявленный идентификатор
1>d:\проги\widelenyeslovmassiva\widelenyeslovmassiva\widelenyeslovmassiva.cpp(47): error C2065: i: необъявленный идентификатор
1> Выход из команды с кодом "2".

Добавлено через 25 минут
Логика вопроса. Мы допустим обьявили переменную как ссылку, но поместили в нее не ссылку на массив, а массив.
Не так sprobuem=&buffer; а так sprobuem=buffer;. Положим, в ней лежит как-бы то ни было массив.

Как мы тогда с ним работаем так p1++; сдвигая пошагово? Или проще не заморачиваться а пытаться использовать, в дальнейшем?
0
HedgehogLu
147 / 68 / 1
Регистрация: 04.09.2013
Сообщений: 260
26.09.2013, 11:31 #4
Цитата Сообщение от Dimka-novitsek Посмотреть сообщение
for (int i=0;i<bufferSize+10;i++0)
я бы сказал там нулик лишний в конце после ++
Смотри
ссылки и указатели это по сути переменные типа лонг, в которых хранится адрес памяти по которому лежат какие-то данные. Соответственно ожидаемый тип данных мы указываем при определении указателя. т.е. char *c означает что в переменной с будет находится адрес памяти по которому мы ожидаем считать значение типа чар.

Таким образом по идее код
Цитата Сообщение от Dimka-novitsek Посмотреть сообщение
sprobuem=&buffer
не должен работать, т.к. у тебя тип данных указатель на чар, а ты передаешь адрес памяти указателя на чар, т.е получаешь указатель на указатель чар.

Логика пока понятна думаю.
Теперь допустим у тебя в коде получается
C++
1
p2 = string;
, таким образом обе переменные хранят в себе один и тот же адрес.Мы помним что по сути указатель это длинное целое, следовательно он поддерживает все стандартные арифметические операторы следовательно если мы сделаем команду p2++, то р2 уже будет хранить адрес на 1 болше чем ранее, следовательно будет уже указывать не на начало строки а на 2 символ в строке, однако если бы переменная стринг являлась бы не строкой а например массивом типа ворд, тогда после выполнения команды р2++ получается, что р2 уже не указывает на начало массива, но еще не указывает на следующий элемент массива, т.к. размер памяти занимаемый типом ворд равен 2 байтам а не одному.

Т.ч. на самом деле лучше арифметические операции с указателями не делать, лучше пользоваться механизмом индексации типизированных указателей.

Ссылки и указатели свою суть хранят в названии они не хранят данные они хранят в себе информацию о том где эти данные брать.
1
26.09.2013, 11:31
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.09.2013, 11:31
Привет! Вот еще темы с ответами:

Объясните правила работы с delete с указателями и массивами (корректное освобождение выделенной памяти) - C++
Указатель содержал ссылку на динамический массив. Массив удалил. Имеет ли смысл применять delete на указатель?

Переделать программу с указателями С++ - C++
Подскажите пжлст ,как переделать эту программу ,чтобы не использовать квадратные скобки?и чтобы когда вхождение символа не найдено...

Написать программу с указателями - C++
Заданы 3 трехмерных вектора a,b,c. Найти скалярное произведение a*b, векторное произведение a*b, смешанное произведение векторов,...

Разобрать код с указателями - C (СИ)
Если делать так, то приложение крэшится: char *str = &quot;71903asgd5&quot;; *(str+1) = 'd'; Если так, то все нормально: ...


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

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

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