Помогите отловить ошибку

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

Linko

#1
Здравствуйте, уважаемые!
Пытаюсь написать программу для замены символов в строке, но не получается, появилась плавающая ошибка. Вот там где я отметил стрелочкой, после этого происходит добавление левых символов в строку, не всегда причем, понять в чем проблема не могу. А когда происходит вызов замены для последней пары из структуры - так там вообще сразу получается мусор.
Проблемы возникают при замене с 'r' на 'р', текст превращается в :
Код:
был: Thиs иs a '#URL#' strиng "#ID#" HA-HA-HA, #ID# for testиng #IDCODE#---
стал: Thиs иs a '#URL#' stЪЪЪЪриng "#ID#" HA-HA-HA, #ID# for testиng #IDCODE#---
Код:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <memory.h>

typedef struct
{
char from[32];
char to[64];
} tagStruct;

char * tagReplacer(char *src, tagStruct * tagS, int count)
{
bool replaced=true;
char *tmp=NULL;
char *res=NULL;
char *pch=NULL;
tmp=(char*) malloc(sizeof(char)+1);
res=(char*) malloc(sizeof(char)+1);
res=(char*)realloc(res,((strlen(src))*sizeof(char*)));
strcpy (res,src);
for(int i=0;i<count;i++) {
while (replaced) {
int lenres=strlen(res);
if(pch = strstr (res,tagS[i].from)) {
replaced=true;
tmp=(char*)realloc(tmp, (lenres-strlen(pch)+1)*sizeof(char));
strncpy(tmp,res,lenres-strlen(pch));
tmp=(char*)realloc(tmp, (strlen(tmp)+strlen(tagS[i].to)+1)*sizeof(char));
strncat(tmp,tagS[i].to,strlen(tagS[i].to));
if((strlen(tmp))<(lenres+strlen(tagS[i].to)-strlen(tagS[i].from))){
-->>>		  tmp=(char*)realloc(tmp, (lenres+strlen(tagS[i].to)-strlen(tagS[i].from)-1)*sizeof(char));
for(int z=(strlen(res)-strlen(pch)+strlen(tagS[i].to));z<((strlen(res)));z++){
tmp[strlen(tmp)]=res[z];
}
}
}
else {
replaced=false;
}
if(replaced) {
res=NULL;
res=(char*)realloc(res,(strlen(tmp)+1));
strncpy (res,tmp,strlen(tmp));
tmp=NULL;
pch=NULL;
}
}
replaced=true;
}
return res;
}

int main ()
{
tagStruct *tagStr=NULL;
tagStr=(tagStruct*) malloc(sizeof(tagStruct));
strcpy(tagStr[0].from,"i");
strcpy(tagStr[0].to,"и");
tagStr=(tagStruct*)realloc(tagStr, (sizeof(tagStruct))*2);
strcpy(tagStr[1].from,"r");
strcpy(tagStr[1].to,"р");
tagStr=(tagStruct*)realloc(tagStr, (sizeof(tagStruct))*3);
strcpy(tagStr[2].from,"t");
strcpy(tagStr[2].to,"т");
tagStr=(tagStruct*)realloc(tagStr, (sizeof(tagStruct))*4);
strcpy(tagStr[3].from,"Th");
strcpy(tagStr[3].to,"В");

const char *foo=tagReplacer("This is a '#URL#' string \"#ID#\" HA-HA-HA, #ID# for testing #IDCODE#---",tagStr,4);
printf("%s\n",foo);
}
 
04.09.2006
2 566
3
#2
Чтобы не иметь таким странных проблем лучше использовать строки из стандартной библиотеки C++

Надеюсь, что двойное использование main - опечатка?
 
L

Linko

#3
Да, извините, двойной main это опечатка при копировании.
А что подразумевается под стандатрными? STL?
Мне надо использование именно char и структуры.
 
Z

zubr

#5
Первое что бросается в глаза, выражение: res=(char*)realloc(res,((strlen(src))*sizeof(char*)));
Ты пытаешься выделить память не под 1-байтовый тип char, а под указатель char*, а это 4-байтовый тип.
 
L

Linko

#6
"Не стреляйте в пианиста, он играет как умеет".
Так я стараюсь поэффективнее использовать память и не быть привязанным к размерам массивов.

Первое что бросается в глаза, выражение: res=(char*)realloc(res,((strlen(src))*sizeof(char*)));
Ты пытаешься выделить память не под 1-байтовый тип char, а под указатель char*, а это 4-байтовый тип.
Это ничего не меняет, по крайней мере - в моем случае, я пробовал...
 

grigsoft

Well-known member
15.11.2005
735
0
#7
Виноват, сходу не понял для чего count. Исправился.

Как ты думаешь, ты сможешь разобраться в своем коде через полгода, если ты сейчас даже ошибку найти в нем не можешь? Сколько ты собрался памяти экономить? Вряд-ли у тебя будут строки длиной больше 1М использоваться. Стоит твоя экономия памяти проблем с чтением кода? И кстати, попробуй поменять в строке "мама" 'а' на 'м' и наоборот :)

Код:
char * tagReplacer(char *src, tagStruct * tagS, int count)
{
if (!src || !tagS || !*src)
return NULL;
if (count<=0)
return strdup(src);
int nOrgLen = strlen(src);
int nMaxLen = strlen(tagS[0]->to);
for (int i=1; i<count; i++)
{
int l = strlen(tagS[i]->to);
if (l>nMaxLen)
nMaxLen = l;
}
char* szRet = (char*)malloc(max(nOrgLen, nOrgLen*nMaxLen)+1);
char* szCur = szRet;
while (*src)
{
BOOL bDone = FALSE;
for (i=0; i<nCount; i++)
{
if (!strcmp(str, tagS[i]->from))	// got it!
{
if (*tagS[i]->to)
{
strcpy(szCur, tagS->to);
szCur += strlen(tagS->to);
}
str += strlen(tagS[i]->from);
bDone = TRUE;
break;
}
}
if (!bDone)
{
*szCur = *str;
szCur++;
str++;
}
}
*szCur=0;
return szRet;
}
 
L

Linko

#8
Виноват, сходу не понял для чего count. Исправился.

Как ты думаешь, ты сможешь разобраться в своем коде через полгода, если ты сейчас даже ошибку найти в нем не можешь? Сколько ты собрался памяти экономить? Вряд-ли у тебя будут строки длиной больше 1М использоваться. Стоит твоя экономия памяти проблем с чтением кода? И кстати, попробуй поменять в строке "мама" 'а' на 'м' и наоборот :)

Код:
	char* szRet = (char*)malloc(max(nOrgLen, nOrgLen*nMaxLen)+1);
А ты в чем собирал это и тестировал? У меня к пример нет max, в строке которую я оставил.
P.S.: В коде намеренно сделано только ошибок? :) str у меня тоже нет.
 

grigsoft

Well-known member
15.11.2005
735
0
#9
:) ну прям собирал и тестировал :) Прямо тут писал, уж извините :) Ну с max я думаю проблем не будет, а str - это src должно быть, что-то меня переклинило в середине :) Код просто как пример давал - я на С уже сто лет не писал.
 
L

Linko

#10
Все таки с max есть проблемы :)
Я тут даже не представляю, какую роль оно может играть :)
 

grigsoft

Well-known member
15.11.2005
735
0
#11
эээ, тогда так:
Код:
if (nMaxLen<1)
nMaxLen = 1;
char* szRet = (char*)malloc(nOrgLen*nMaxLen+1)
И кстати, в чем смысл sizeof(char)? Вроде как char>1 только в C#. Или в голом С юникод просто так собирается, без всяких TCHAR, wchar, L и прочих?
 
L

Linko

#12
Вся засада в том - что я это пишу под FreeBSD, используя компилятор g++42
А в чем смысл - я точно не помню, но без этого периодически все начинало у меня глючить, когда то давно, глюки исчезли, а привычка осталась.

Кстати, я так и не постиг - за что отвечает nCount :)
 
L

Linko

#14
Да, я так и понял. :)
Вообщем - буду ковырять то что получилось, а то с первого раза не заработало, уходит в бесконечный цикл :)
 

grigsoft

Well-known member
15.11.2005
735
0
#15
Ну ты меня прямо напугал, пришлось все-таки собрать и проверить :) Должен извинится, наляпал не глядя много, конечно, но в мелочах. Принципиальная ошибка одна всего - надо strncmp вместо strcmp.
Код:
char * tagReplacer(char *src, tagStruct * tagS, int count)
{
if (!src || !tagS || !*src)
return NULL;
if (count<=0)
return strdup(src);
int nOrgLen = strlen(src);
int nMaxLen = strlen(tagS[0].to);
for (int i=1; i<count; i++)
{
int l = strlen(tagS[i].to);
if (l>nMaxLen)
nMaxLen = l;
}
if (nMaxLen<1)
nMaxLen = 1;
char* szRet = (char*)malloc(sizeof(char)*(nOrgLen*nMaxLen+1));
char* szCur = szRet;
while (*src)
{
BOOL bDone = FALSE;
for (i=0; i<count; i++)
{
if (!strncmp(src, tagS[i].from, strlen(tagS[i].from)))	// got it!
{
if (*tagS[i].to)
{
strcpy(szCur, tagS[i].to);
szCur += strlen(tagS[i].to);
}
src += strlen(tagS[i].from);
bDone = TRUE;
break;
}
}
if (!bDone)
{
*szCur = *src;
szCur++;
src++;
}
}
*szCur=0;
return szRet;
}
 
L

Linko

#16
Блин, все отдам - когда узнаю что же все такое - max?
У меня такого в юниксе нет :) И ни какого описания или намеков на это, как оно работает? :)
 

grigsoft

Well-known member
15.11.2005
735
0
#17
Дык это - выбирает максимум :) но это из С++.
Код:
#define max(a, b) ((a)>(b) ? (a) :(b))
 
L

Linko

#18
Я в шоке - оно работает как часы! :)
Спасибо, буду работать над собой :)
 
Статус
Закрыто для дальнейших ответов.