удалить в строке Char заданный символ

  • Автор темы tanil72
  • Дата начала
Статус
Закрыто для дальнейших ответов.
T

tanil72

Здравствуйте.
Стоит задача ввести строку char с клавиатуры, вывести ее на экран и удалить в ней заданный символ.
Код следующий. Подпрограмма удаления вынесена в отдельную функцию. Но удаление символа проходит неправильно.
Подскажите, в чем ошибка.
Спасибо.
C:
#include <iostream>
#include <stdio.h>
using namespace std;

char* del_char(char* s, char c){
// int s_len=strlen(s); char *p=new char[s_len-1];
char *p=s; int i=0;
while(s!='\0'){
if(s!=c)  p=s;
else  p=s[i+1];
i++;
}
*p='\0';
return p;
}

int main(){
int i, n=100;
char *s=new char[n];
char *tmp=new char[n-1];
char d='p';
cout<<"Vvedite stroku"<<endl;
cin.getline(s,n);
for(i=0;i<n;i++)
cout<<s;cout<<endl;

tmp=del_char(s,d);
for(i=0;i<n;i++)
cout<<tmp;cout<<endl;
return(0);
}
 
G

grigsoft

А отлаживаться вас не учат? Давай я научу. Берешь листик бумаги и ручку, записываешь в строчку имена локальных переменных, палец левой руки ставишь на первую строчку функции, правой записываешь под именами начальные значения. Теперь делаешь шаг левой рукой вниз на одну строчку, правой записываешь изменившиеся переменные. Продолжать пока реальные значения переменных не станут отличаться от ожидаемых. В результате даже без компьютера находишь ошибки у себя в программе. Заодно начинаешь понимать что же собственно у тебя написано.
 
T

tanil72

Может логика неправильная- поправьте (я новичок).
Длина строка с удаленным символом будет на 1 меньше.
Переписываю в новую строку по-элементно символы введенной строки,
а заданный символ пропускаю (пока не конец введенной строки).
Может есть станд. функция удаляющая символ?

А отлаживаться вас не учат? Давай я научу. Берешь листик бумаги и ручку, записываешь в строчку имена локальных переменных, палец левой руки ставишь на первую строчку функции, правой записываешь под именами начальные значения. Теперь делаешь шаг левой рукой вниз на одну строчку, правой записываешь изменившиеся переменные. Продолжать пока реальные значения переменных не станут отличаться от ожидаемых. В результате даже без компьютера находишь ошибки у себя в программе. Заодно начинаешь понимать что же собственно у тебя написано.
 
D

Dimmuborgir

думаю, дело в алгоритме удаления.)
C:
if(s[i]!=c) 
p[i]=s[i];
else 
p[i]=s[i+1];
неверное условие. по этому условию сдвигается на единицу только символ стоящий после нужного. Необходимо как я понимаю сдвигать все символы находящиеся после заданного. Как это сделать, я думаю сами додумаетесь.
 
S

shisik

Так всё работает :)
C:
#include <iostream>

using namespace std;

char * del_char(const char * src, char * res, char c)
{
char *tmp = res;
do
if (*src != c)
*res++ = *src;
while (*src++);
return tmp;
}

int main(int argc, char *argv[])
{
char str[256], buf[256];

cin >> str;

cout << del_char(str, buf, 'a') << endl;

return 0;
}
Даже символ '\0' в конец строки добавляет автоматически из строки исходной :)
 
T

tanil72

Спасибо. так действительно удаляет все вхождения заданного символа во введенной строке.
а первоначальный код подправлен, но он не все делает,
если, например, символ идет подряд 2 раза,
он один удаляет, а следующий такой же оставляет не удаленным.

C:
#include <iostream>
using namespace std;

char * del_char(char * s, char c){
int count=0;
char *p, char*r, char*res;
for(r=s;r=strchr(r,c);r+=sizeof(с))++count;
p=result=(char*)malloc(strlen(s)-sizeof(с)*count+1);
int i=0,j=0;
while(s!='\0'){
if(s!=c) p[j]=s;
else p[j]=s[++i];
i++;j++;
}
p[j]='\0';
return p;
}

int main()
{int n=100;
char *s=new char[n];
char *tmp=new char[n];
char d='p';
cout<<"vvedite stroku"<<endl;
cin.getline(s,n);
cout<<s<<endl;

tmp=del_char(s,d);

cout<<tmp<<endl;
return 0;
}
 
S

shisik

а первоначальный код подправлен, но он не все делает,
если, например, символ идет подряд 2 раза,
он один удаляет, а следующий такой же оставляет не удаленным.
Это потому, что алгоритм неправильный. Ошибка заключается в том, что в операторе
C:
if (s[i] != c)
p[j]=s[i];
else
p[j]=s[++i];
i++;j++;
не нужно писать else. Я имею ввиду, что ты принудительно смещаешь исходную строку на один символ и без всяких проверок записываешь этот символ в результат. Поэтому второе подряд вхождения оно и не удаляет. Собственно, если этот участок переписать
C:
if (s[i] != c)
p[j++]=s[i];
i++;
то эта проблема должна решиться (извини, проверять сейчас как-то неохота).

И ещё вопрос. Зачем под p выделять память динамически? Да ещё и через malloc (в C++, имхо, проще использовать new). Получается, что теперь после вызова del_char() следует вызывать free() или delete (в случае использования new). И ещё меня смущает вызов
C:
char *tmp=new char[n];
а затем
C:
tmp=del_char(s,d);
 
T

tanil72

Спасибо. Это была ошибка в логике. else не нужно.
Я думала, что важно знать точно длину результирующей строки и поэтому вычисляла
C:
char* r; for(r=s;r=strchr(r,c);r+=sizeof(с))++count;
unsigned int tmp_len=strlen(s)-sizeof(d)*count+1;
char tmp[tmp_len];
а у вас работает верно и без этих вычислений
т.е. просто char tmp[n];

C:
#include <iostream>
using namespace std;
char * del_char(char *s, char *temp, char c){
char *p=temp;
int i=0,j=0;
while(s[i]!='\0'){
if(s[i]!=c) p[j++]=s[i];
i++;}
p[j]='\0';
return p;}

int main(){
int n=100;
char s[n];
char d='p';
cout<<"vvedite stroku"<<endl;
cin.getline(s,n);
cout<<s<<endl;
int count=0;
char* r; for(r=s;r=strchr(r,d);r+=sizeof(d))++count;
unsigned int tmp_len=strlen(s)-sizeof(d)*count+1;
char tmp[tmp_len];

del_char(s,tmp,d);
cout<<tmp<<endl;
return 0;}
 
S

shisik

Я думала, что важно знать точно длину результирующей строки и поэтому вычисляла
C:
char* r;
for (r = s; r = strchr(r, c); r += sizeof(с))
++count;
unsigned int tmp_len = strlen(s) - sizeof(d) * count + 1;
char tmp[tmp_len];
а у вас работает верно и без этих вычислений
т.е. просто char tmp[n];
Строки в C/C++ устроены таким образом, что обрабатываются до первого вхождения символа '\0', т.е. если строка определена как char str[256]; и в неё записать строку "Hello", то получится
C:
str[0] = 'H';
str[1] = 'e';
str[2] = 'l';
str[3] = 'l';
str[4] = 'o';
str[5] = '\0';
а str[6] и до str[255] просто будут игнорироваться. Поэтому совсем необязательно знать точный размер строки, достаточно выделить для неё заведомо больше (в разумных пределах, конечно).

И ещё одно. Советую в дальнейшем всегда стараться свой код форматировать, чтоб он легко читался. Я тоже вначале не обращал на это внимание. Но потом понял, что так даже самому мне легче работать, не говоря уже про окружающих...
 
Статус
Закрыто для дальнейших ответов.
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!