Помощник
Здравствуйте, гость ( Вход | Регистрация )
|
|
25:04:2008, 11:12
|
|
Новенький ![]() Группа: Новенький Сообщений: 11 Регистрация: 7:04:2008 Пользователь №: 16 436 Репутация: 0
|
Здравствуйте.
Стоит задача ввести строку char с клавиатуры, вывести ее на экран и удалить в ней заданный символ. Код следующий. Подпрограмма удаления вынесена в отдельную функцию. Но удаление символа проходит неправильно. Подскажите, в чем ошибка. Спасибо. CODE #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[i]!='\0'){ if(s[i]!=c) p[i]=s[i]; else p[i]=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[i];cout<<endl; tmp=del_char(s,d); for(i=0;i<n;i++) cout<<tmp[i];cout<<endl; return(0); } Сообщение отредактировал tanil72 - 25:04:2008, 12:00
Причина редактирования: Установка тегов кода
|
|
Сообщение
#1
|
|
![]() |
|
|
25:04:2008, 11:31
|
|
Мегагуру ![]() ![]() ![]() ![]() Группа: Модеры Сообщений: 715 Регистрация: 15:11:2005 Пользователь №: 2 573 Репутация: 6
|
А отлаживаться вас не учат? Давай я научу. Берешь листик бумаги и ручку, записываешь в строчку имена локальных переменных, палец левой руки ставишь на первую строчку функции, правой записываешь под именами начальные значения. Теперь делаешь шаг левой рукой вниз на одну строчку, правой записываешь изменившиеся переменные. Продолжать пока реальные значения переменных не станут отличаться от ожидаемых. В результате даже без компьютера находишь ошибки у себя в программе. Заодно начинаешь понимать что же собственно у тебя написано.
|
|
Сообщение
#2
|
|
|
|
25:04:2008, 12:07
|
|
Новенький ![]() Группа: Новенький Сообщений: 11 Регистрация: 7:04:2008 Пользователь №: 16 436 Репутация: 0
|
Может логика неправильная- поправьте (я новичок).
Длина строка с удаленным символом будет на 1 меньше. Переписываю в новую строку по-элементно символы введенной строки, а заданный символ пропускаю (пока не конец введенной строки). Может есть станд. функция удаляющая символ? А отлаживаться вас не учат? Давай я научу. Берешь листик бумаги и ручку, записываешь в строчку имена локальных переменных, палец левой руки ставишь на первую строчку функции, правой записываешь под именами начальные значения. Теперь делаешь шаг левой рукой вниз на одну строчку, правой записываешь изменившиеся переменные. Продолжать пока реальные значения переменных не станут отличаться от ожидаемых. В результате даже без компьютера находишь ошибки у себя в программе. Заодно начинаешь понимать что же собственно у тебя написано. |
|
Сообщение
#3
|
|
|
|
25:04:2008, 13:50
|
|
Новенький ![]() Группа: Программист Сообщений: 61 Регистрация: 27:12:2007 Пользователь №: 14 492 Репутация: 0
|
думаю, дело в алгоритме удаления.)
Код if(s[i]!=c) p[i]=s[i]; else p[i]=s[i+1]; неверное услоиве. по этому условию сдвигается на единицу только символ стоящий после нужного. Необходимо как я понимаю сдвигать все символы находящиеся после заданного. Как это сделать, я думаю сами додумаетесь. |
|
Сообщение
#4
|
|
|
|
25:04:2008, 15:18
|
|
Продвинутый ![]() ![]() Группа: Новенький Сообщений: 141 Регистрация: 26:08:2007 Из: Харьков Пользователь №: 12 480 Репутация: 2
|
Так всё работает
Код #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' в конец строки добавляет автоматически из строки исходной Сообщение отредактировал shisik - 25:04:2008, 15:24 |
|
Сообщение
#5
|
|
|
|
25:04:2008, 16:15
|
|
Новенький ![]() Группа: Новенький Сообщений: 11 Регистрация: 7:04:2008 Пользователь №: 16 436 Репутация: 0
|
Спасибо. так действительно удаляет все вхождения заданного символа во введенной строке.
а первоначальный код подправлен, но он не все делает, если, например, символ идет подряд 2 раза, он один удаляет, а следующий такой же оставляет не удаленным. CODE #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[i]!='\0'){ if(s[i]!=c) p[j]=s[i]; 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; } Сообщение отредактировал European - 28:04:2008, 07:32 |
|
Сообщение
#6
|
|
|
|
25:04:2008, 16:39
|
|
Продвинутый ![]() ![]() Группа: Новенький Сообщений: 141 Регистрация: 26:08:2007 Из: Харьков Пользователь №: 12 480 Репутация: 2
|
а первоначальный код подправлен, но он не все делает, если, например, символ идет подряд 2 раза, он один удаляет, а следующий такой же оставляет не удаленным. Это потому, что алгоритм неправильный. Ошибка заключается в том, что в операторе Код if (s[i] != c) p[j]=s[i]; else p[j]=s[++i]; i++;j++; не нужно писать else. Я имею ввиду, что ты принудительно смещаешь исходную строку на один символ и без всяких проверок записываешь этот символ в результат. Поэтому второе подряд вхождения оно и не удаляет. Собственно, если этот участок переписать Код if (s[i] != c) p[j++]=s[i]; i++; то эта проблема должна решиться (извини, проверять сейчас как-то неохота). И ещё вопрос. Зачем под p выделять память динамически? Да ещё и через malloc (в C++, имхо, проще использовать new). Получается, что теперь после вызова del_char() следует вызывать free() или delete (в случае использования new). И ещё меня смущает вызов Код char *tmp=new char[n]; а затем Код tmp=del_char(s,d); |
|
Сообщение
#7
|
|
|
|
28:04:2008, 13:17
|
|
Новенький ![]() Группа: Новенький Сообщений: 11 Регистрация: 7:04:2008 Пользователь №: 16 436 Репутация: 0
|
Спасибо. Это была ошибка в логике. else не нужно.
Я думала, что важно знать точно длину результирующей строки и поэтому вычисляла Код 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]; Код #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;} Сообщение отредактировал European - 29:04:2008, 06:32 |
|
Сообщение
#8
|
|
|
|
28:04:2008, 13:34
|
|
Продвинутый ![]() ![]() Группа: Новенький Сообщений: 141 Регистрация: 26:08:2007 Из: Харьков Пользователь №: 12 480 Репутация: 2
|
Я думала, что важно знать точно длину результирующей строки и поэтому вычисляла Код 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", то получится Код str[0] = 'H'; str[1] = 'e'; str[2] = 'l'; str[3] = 'l'; str[4] = 'o'; str[5] = '\0'; а str[6] и до str[255] просто будут игнорироваться. Поэтому совсем необязательно знать точный размер строки, достаточно выделить для неё заведомо больше (в разумных пределах, конечно). И ещё одно. Советую в дальнейшем всегда стараться свой код форматировать, чтоб он легко читался. Я тоже вначале не обращал на это внимание. Но потом понял, что так даже самому мне легче работать, не говоря уже про окружающих... |
|
Сообщение
#9
|
|
![]() |
|
Текстовая версия | Сейчас: 5:09:2008 - 13:53 |