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

Обработать строки, пользуясь указателями - C++

Восстановить пароль Регистрация
 
asdkile
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 12
03.11.2012, 19:05     Обработать строки, пользуясь указателями #1
Помогите решить, заранее спасибо:
Вводится строка в символьный массив размером 80.
Задание:
Рядом с заданным пользователем символом записать такой же. Запрещается использовать дополнительные массивы и блоки.
Например:
Введенная строка - корова
Введенный символ - О
После обработки должно получится коороова
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Kuzia domovenok
 Аватар для Kuzia domovenok
1882 / 1737 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
03.11.2012, 19:28     Обработать строки, пользуясь указателями #2
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
#include <iostream>
#include <stdio.h>
using namespace std;
const int n=80;
int main(int argc, char *argv[])
{
    char text[n];
    int i, j;
    char c, r, h;
    cout<<"input text:  ";
    gets(text);
    cout<<"Input symbol: ";
    cin>>c;
    i=0;
    while(text[i]){
      if (text[i]==c){
        j=i+1;
        r=c;
        while(text[j]){
          h=text[j];
          text[j]=r;
          r=h;  
          j++;             
        }               
        text[j]=r; 
        text[j+1]=0;  
        i++;           
      }
      i++;               
    }
    
    cout<<"String after replacing\n"<<text<<endl;
    
    system("PAUSE");
    return 0;
}
Добавлено через 4 минуты
Ой, а надо было указателями? Так бы сразу указал. как тут догадаешься? Ща переделаю

Добавлено через 4 минуты
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
#include <iostream>
#include <stdio.h>
using namespace std;
const int n=100;
int main(int argc, char *argv[])
{
    char text[n];
    char c, r, h;
    char* cur;
    char* sht;
    cout<<"Enter input text:  ";
    gets(text);
    cout<<"Input symbol: ";
    cin>>c;
    cur=text;
    while(*cur){
      if (*cur==c){
        sht=cur+1;
        r=c;
        while(*sht){
          h=*sht;
          *sht=r;
          r=h;  
          sht++;             
        }               
        *sht=r; 
        sht++;
        *sht=0;  
        cur++;           
      }
      cur++;               
    }
    
    cout<<"String after replacing\n"<<text<<endl;
    
    system("PAUSE");
    return 0;
}
asdkile
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 12
04.11.2012, 12:24  [ТС]     Обработать строки, пользуясь указателями #3
Не могли бы вы пояснить, как работает этот фрагмент кода?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    while(*cur){
      if (*cur==c){
        sht=cur+1;
        r=c;
        while(*sht){
          h=*sht;
          *sht=r;
          r=h;  
          sht++;             
        }               
        *sht=r; 
        sht++;
        *sht=0;  
        cur++;           
      }
      cur++;               
    }
Kuzia domovenok
 Аватар для Kuzia domovenok
1882 / 1737 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
04.11.2012, 16:41     Обработать строки, пользуясь указателями #4
Для начала определимся что есть что
cur и sht это указатели на символ в тексте.
Присваивая cur=text, мы указываем указателем на первый символ текста
увеличивая указатель на единицу(или на любое число), мы двигаем его по тексту вперёд на соотв. количество букв, первая буква, вторая и.т.д.
*cur и *sht - это значения символов, на которые указывают эти указатели (т.е. собственно буквы 'a' 'b' 'c'...)
Если их увеличивать/уменьшать, указатель никуда не сдвинется, а будет изменятся сама буква на этом месте.
Особая буква(символ) это 0. Не текст в кавычках '0', а число 0. Этот символ должен всегда стоять в конце строки, собственно конец строки по другому определить и невозможно.
Именно поэтому, чтобы проверить весть текст от первого до последнего символа, мы задаём цикл

C++
1
2
3
4
5
cur=text;//указатель на текущий символ указывает на первый
while(*cur){//пока *cur (значение текущего символа) не равен нулю, т.е. признаку конца строки
/*проверка текущего символа*/
cur++;//передвижение указателя на 1 символ вперёд, на следующий символ
}
Теперь в цикле нужно не просто перемещать указатель от первого до последнего символа, но и проверять их на необходимость удвоить
Эту проверку выполняет условие if (*cur==c)
*cur это текущий символ, который расположен в месте куда указывает указатель cur (указатель текущего символа).
Если он равен тому, что надо удвоить, выполняется блок удвоения символа.
Что такое удвоение символа? Написать в следующей за cur позицией такой же символ с? Скажем *(cur+1)=c?
Э нет!
Если просто написать на следующем за ним месте такую же букву, то она затрёт букву, что была в тексте на этом месте, и та потеряется.
Поэтому перед тем как удвоить символ, необходимо сдвинуть всю часть текста, следующую за ним
на 1 позицию вправо, и только потом вписывать символ в освободившееся место.
как это происходит? Мы должны снова пройтись по тексту в цикле до конца, заменяя каждую букву на ту, что раньше стояла перед ней, а последнюю букву добавить в конец.
Но мы проходим в цикле не сначала, а начиная с символа с которого начинаем двигать.
Цикл аналогичен главному циклу, который проходит по тексту, только используется указатель не cur, а новый (я назвал его sht)
Цикл выглядит так:
C++
1
2
3
4
5
sht=cur+1;
        while(*sht){
          //двигаем один символ
          sht++;             
        }
Аналогично, не правда ли? Остаётся понять, что значит "двигаем один символ"? Это значит, что мы заменяем символ по указателю sht на предыдущий.
Что может быть проще? Сделаем *sht=*(sht-1) и дело с концом. Но не всё так просто. При таком действии мы не только затрём символ, на который указывает sht,
но и будем копировать этот символ и в следующей итерации цикла, заполнив весь текст одинаковыми символами.
Поэтому, надо всегда сохранять тот символ, что ранее был на месте sht во вспомогательной переменной r
перед тем как затирать его предыдущим сохранённым таким образом символом в операции *sht=r; Более того, необходимо сохранять не только предыдущий но и текущий символ,
потому что *sht=r; как уже замечено ранее затрёт бывший в этом месте символ.
Поэтому операция разбивается на 4 части
C++
1
2
3
4
5
6
//шаг № n
h=*sht; // текущий символ сохраняем в h, чтобы не затёрся, 
*sht=r;  //т.к. на его место встаёт предыдущий символ  
/// готовимся перейти к шагу № n+1
r=h;      // предыдущий символ теперь это тот, который был текущим
sht++;   // а текущий это следующий за ним.
Когда закончится цикл while(*sht), сдвигающий текст sht будет указывать на конечный символ 0
а последним значимым символом в тексте станет бывший предпоследний
Было
sht--------------v
cur-----------v
'у' 'к' 'а' 'з' 'а' 'т' 'е' 'л' 'ь' 0
Стало
h=r='ь'
sht---------------------v
cur-----------v
'у' 'к' 'а' 'з' 'а' 'т' 'т' 'е' 'л' 0

поэтому необходимо записать на место, указывааемое sht последний символ (он сохранился в процессе последней итерации цикла в переменных r и h)
*sht=r;
sht---------------------v
'у' 'к' 'а' 'з' 'а' 'т' 'т' 'е' 'л' 'ь'
и поставить в конец затёртый нами нулевой символ конца строки, увеличив тем самым её длину на 1
sht++;
*sht=0;
sht------------------------v
cur-----------v
'у' 'к' 'а' 'з' 'а' 'т' 'т' 'е' 'л' 'ь' 0

Ну и перед выходом из условия проверки надо ещё раз увеличить cur, потому что в главном цикле он кинется проверять следующую букву, а она уже удвоена, поэтому двигаем его дополнительно на единицу
C++
1
cur++
asdkile
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 12
04.11.2012, 20:38  [ТС]     Обработать строки, пользуясь указателями #5
Очень подробно и понятно все рассказали.
Большое вам спасибо!
Yandex
Объявления
04.11.2012, 20:38     Обработать строки, пользуясь указателями
Ответ Создать тему
Опции темы

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