Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - Ошибки новичков или индийский стиль...

Ответить
Настройки темы
C/C++ - Ошибки новичков или индийский стиль...

Аватара для Dr.Dark

Старожил


Сообщения: 224
Благодарности: 15

Профиль | Отправить PM | Цитировать


Я написал небольшую программку. Хотел бы услышать мнения о том как она смотрится относительно идеологии C++. Т.е. незнаю возможно можно было как то сделать проще или лучше, записать короче и т.д. Зараннее спасиб
Код: Выделить весь код
#include <vcl.h>
#include <stdio.h>
#include <iostream.h>
#include <string.h>
#pragma hdrstop

#pragma argsused

int main(int argc, char* argv[])
{
	FILE *binFile;
	char *cSect, *cKey, *cValue, *sPtr, *kPtr, bSect[512], bKeys[512],
	bValue[512], *cFile, MyPath[256], iniPath[256], MyDrive[2], MyDir[251];

	cout << "Patcher started...\r\n";
	GetModuleFileName(NULL,MyPath,sizeof(MyPath));
	_splitpath(MyPath, MyDrive, MyDir, NULL, NULL);
	sprintf(iniPath,"%s%s%s", MyDrive,MyDir,"map.ini");
	sprintf(MyPath,"%s%s", MyDrive,MyDir);
	cout << "Getting patch map...\r\n";
	if (GetPrivateProfileString(NULL,NULL,FALSE,bSect,sizeof(bSect),iniPath) == 0)
	{
		cout << "Can't see map.ini\r\n" << "\r\n";
		system("pause");
		exit(1);
	}

	sPtr=bSect;
	while(*sPtr!=NULL)//перебираем буфер секций
	{
		cSect=(char*) malloc(strlen(sPtr)+1);
		strcpy(cSect,sPtr);
		sPtr=strchr(sPtr,'\0')+1;
		cFile=(char*) malloc(strlen(MyPath)+strlen(cSect)+1);
		sprintf(cFile,"%s%s",MyPath,cSect);
		binFile=fopen(cFile,"r+b");
		printf("Patching %s:\r\n",cSect);
		if (binFile==NULL)
		{
			printf("\tCan't open file %s\r\n",cSect);
			system("pause");
			exit(2);
		}
		GetPrivateProfileString(cSect,NULL,FALSE,bKeys,sizeof(bKeys),iniPath);
		kPtr=bKeys;
		while(*kPtr!=NULL) //перебираем ключи секции
		{
			cKey=(char*) malloc(strlen(kPtr)+1);
			strcpy(cKey, kPtr);
			kPtr=strchr(kPtr,'\0')+1;
			GetPrivateProfileString(cSect,cKey,FALSE,bValue,sizeof(bValue),iniPath);
			cValue=(char*) malloc(strlen(bValue)+1);
			strcpy(cValue,bValue);
			printf("\t%s=%s\r\n",cKey,cValue);
			fseek(binFile,atoi(cKey),0);
			fwrite(cValue, 1, strlen(cValue), binFile);
		};
		fclose(binFile);
	}
	cout << "Patching done. Have a nice day :)...\r\n";
	return 0;
}

-------
Спасение утопающих-дело рук самих утопающих.


Отправлено: 23:36, 29-08-2010

 

Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить PM | Цитировать


Ну если прям так придираться, то:
1.
Код: Выделить весь код
cSect=(char*) malloc(strlen(sPtr)+1);
strcpy(cSect,sPtr);
sPtr=strchr(sPtr,'\0')+1;
я бы этот кусок как нибудь упростил, т.к тут используются 2 функции (strlen, strchr) которые совершают 2*N итераций, хотя можно было бы использовать только strchr и длину вычислять не с помощью strlen, а вычитанием sPtr от начального адреса.
Что, касается strcpy, то я лучше бы использовал strncpy, т.к. переполнение буфера не кто не отменял (хотя тут мб и не будет такого...).

2.
Код: Выделить весь код
fseek(binFile,atoi(cKey),0);
Уверены, что в cKey всегда будет строка из цифр?

3.
Вызываем malloc, но забываем вызвать free.

-------
К величайшему сожалению "история учит нас тому, что она ничему не учит".

Это сообщение посчитали полезным следующие участники:

Отправлено: 01:27, 30-08-2010 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для Dr.Dark

Старожил


Сообщения: 224
Благодарности: 15

Профиль | Отправить PM | Цитировать


Цитата ganselo:
можно было бы использовать только strchr и длину вычислять не с помощью strlen, а вычитанием sPtr от начального адреса. »
Первоначально я так и сделал... для хранения начального адреса была выделена переменная... Но я почему то решил что так будет лучш...
Скажем так... А что если использовать sizeof тоже ищет нуль терминатор как и strlen? Или?!
Код: Выделить весь код
sPtr=sizeof(cSect);
Цитата ganselo:
касается strcpy, то я лучше бы использовал strncpy »
ИМХО тут его не будет потому что память выделяю под длину строки...

Цитата ganselo:
Уверены, что в cKey всегда будет строка из цифр? »
Нет эт так пробный вариант... Там будет строка HEX смещение от начала файла.... Ща набросаю функцию перевод char* в hex и там проверять буду...

Цитата ganselo:
но забываем вызвать free. »
дамс... промухал

-------
Спасение утопающих-дело рук самих утопающих.


Отправлено: 10:23, 30-08-2010 | #3


Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить PM | Цитировать


С помощью операции sizeof можно определить размер памяти которая соответствует идентификатору или типу. Если вы выделяете память char *c = malloc(...), то sizeof(c) вернёт, 1 байт. Так, что sizeof тут не прокатит.

Цитата Dr.Dark:
ИМХО тут его не будет потому что память выделяю под длину строки... »
Лично я завёл для себя правило использовать strncpy вместо strcpy.

P.S
Цитата Dr.Dark:
Хотел бы услышать мнения о том как она смотрится относительно идеологии C++ »
Наверно, Вы имели ввиду идеологии Си.

-------
К величайшему сожалению "история учит нас тому, что она ничему не учит".


Отправлено: 13:19, 30-08-2010 | #4


Аватара для Dr.Dark

Старожил


Сообщения: 224
Благодарности: 15

Профиль | Отправить PM | Цитировать


Я ещё немног подумал над алгоритмом и немного упростил всё...
терь так выглядит
Код: Выделить весь код
#include <vcl.h>
#include <stdio.h>
#include <iostream.h>
#include <string.h>
#include <math.h>
#pragma hdrstop

#pragma argsused
int hstoi(char* hexstr)
{
	int idx, len, result;
	len=strlen(hexstr);
	strrev(hexstr);
	result=0;

	for(idx=0; idx<len; idx++)
	{
		if (isdigit(hexstr[idx]))
		{
			result+=(hexstr[idx]-48)*pow(16,idx);
		} else {
			switch(toupper(hexstr[idx]))
			{
				case 'A': result+=10*pow(16,idx);break;
				case 'B': result+=11*pow(16,idx);break;
				case 'C': result+=12*pow(16,idx);break;
				case 'D': result+=13*pow(16,idx);break;
				case 'E': result+=14*pow(16,idx);break;
				case 'F': result+=15*pow(16,idx);break;
				default:
					cout << "Incorrect offset";
					exit(3);
				break;
			}
		}
	}
	return result;
}

int main(int argc, char* argv[])
{
	FILE *binFile;
	char *sPtr, *kPtr, *cFile, bSect[512], bKeys[512], bValue[512],  MyPath[256],
	iniPath[256], MyDrive[2], MyDir[251];

	cout << "Patcher started...\r\n";
	GetModuleFileName(NULL,MyPath,sizeof(MyPath));
	_splitpath(MyPath, MyDrive, MyDir, NULL, NULL);
	sprintf(iniPath,"%s%s%s", MyDrive,MyDir,"map.ini");
	sprintf(MyPath,"%s%s", MyDrive,MyDir);
	cout << "Getting patch map...\r\n";
	if (GetPrivateProfileString(NULL,NULL,FALSE,bSect,sizeof(bSect),iniPath) == 0)
	{
		cout << "Can't see map.ini\r\n" << "\r\n";
		system("pause");
		exit(1);
	}

	sPtr=bSect;
	while(*sPtr!=NULL)//перебираем буфер секций
	{
		cFile=(char*) malloc(strlen(MyPath)+strlen(sPtr)+1);
		sprintf(cFile,"%s%s",MyPath,sPtr);
		binFile=fopen(cFile,"r+b");
		printf("Patching %s:\r\n",sPtr);
		if (binFile==NULL)
		{
			printf("\tCan't open file %s\r\n",sPtr);
			system("pause");
			exit(2);
		}
		GetPrivateProfileString(sPtr,NULL,FALSE,bKeys,sizeof(bKeys),iniPath);
		kPtr=bKeys;
		while(*kPtr!=NULL) //перебираем ключи секции
		{
			GetPrivateProfileString(sPtr,kPtr,FALSE,bValue,sizeof(bValue),iniPath);
			printf("\t%s=%s\r\n",kPtr,bValue);
			fseek(binFile,hstoi(kPtr),0);
			fwrite(bValue, 1, strlen(bValue), binFile);
			kPtr=strchr(kPtr,'\0')+1;
		};
		fclose(binFile);
		free(cFile);
		sPtr=strchr(sPtr,'\0')+1;
	}
	cout << "Patching done. Have a nice day :)\r\n";
	return 0;
}

-------
Спасение утопающих-дело рук самих утопающих.

Это сообщение посчитали полезным следующие участники:

Отправлено: 22:11, 30-08-2010 | #5


ИО Капитана Очевидности


Contributor


Сообщения: 5387
Благодарности: 1105

Профиль | Отправить PM | Цитировать


Цитата Dr.Dark:
Хотел бы услышать мнения о том как она смотрится относительно идеологии C++. »
Идеология С++ предполагает использование классов строковых контейнеров
Ну и конечно же,*если всё-таки хочется выделять память "руками", но нельзя забывать её освобождать

замечания к функции int hstoi(char* hexstr)
1. Поскольку hexstr не изменяется, нужно использовать указатель на константу (иначе функция не сможет принимать константы в качестве аргументов)
2. В*цикле много раз выполняется операция pow(16,idx). Это жуткий "индуизм" , проще каждый раз в цикле выполнять операцию умножения.
for(int idx=0, powdx=1; idx<len; idx++, powdx *= 16)
А поскольку у нас значение кратное степеням двойки, то ещё быстрее будет логический сдвиг единицы в числе.
3. Мегабаг. Если в функцию будет направлена длинная строка, то произойдёт целочисленное переполнение значения powdx (равно как и результата исходного вычисления). Нужно добавить проверку значения len

-------
Самое совершенное оружие, которым забиты арсеналы богатых и процветающих наций, может легко уничтожить необразованного, больного, бедного и голодного. Но оно не может уничтожить невежество, болезнь, нищету и голод. (Фидель Кастро)

Почему всех осужденных за измену Родине при Сталине реабилитировали при Горбачёве по отсутствию состава преступления? Потому что при Горбачёве измену Родине перестали считать преступлением.

Это сообщение посчитали полезным следующие участники:

Отправлено: 04:46, 31-08-2010 | #6


Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить PM | Цитировать


Цитата El Scorpio:
2. В*цикле много раз выполняется операция pow(16,idx). Это жуткий "индуизм" , проще каждый раз в цикле выполнять операцию умножения. »
Полностью согласен, т.к функция pow чтобы возвести в степень использует ряды. Плюс ко всему функция pow считает приближённо (ну это если используете float, double).

-------
К величайшему сожалению "история учит нас тому, что она ничему не учит".


Отправлено: 17:21, 31-08-2010 | #7



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - Ошибки новичков или индийский стиль...

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Доступ - "не удается войти в систему из-за следующей ошибки указанный домен не существует или kalion-kill Microsoft Windows 2000/XP 23 22-11-2010 17:19
Ноутбук для новичков OSZone News Новости информационных технологий 0 20-02-2010 02:30
Литература по администрированию для новичков onefromheart Microsoft Windows NT/2000/2003 11 24-10-2008 08:17
Экстремально простая установка Ubuntu для новичков liberatum Новости и флейм из мира *nix 1 16-10-2008 23:06




 
Переход