Показать сообщение отдельно
Старый 13.04.2007, 13:54     # 5
Bishop
Member
 
Аватар для Bishop
 
Регистрация: 18.08.2004
Пол: Male
Сообщения: 235

Bishop Имеются все основания чтобы гордиться собойBishop Имеются все основания чтобы гордиться собойBishop Имеются все основания чтобы гордиться собойBishop Имеются все основания чтобы гордиться собойBishop Имеются все основания чтобы гордиться собойBishop Имеются все основания чтобы гордиться собойBishop Имеются все основания чтобы гордиться собойBishop Имеются все основания чтобы гордиться собойBishop Имеются все основания чтобы гордиться собойBishop Имеются все основания чтобы гордиться собой
Как я понял, нужна такая процедура:
Код:
#include <stdio.h>
#include <tchar.h>
#include <windows.h>

BOOL GetString(TCHAR* fileName, TCHAR* section, TCHAR* key, // [in]
	   TCHAR* value, // [out]
	   DWORD sizeOfValue, TCHAR* commonSection = NULL) // [in]
{
	//TCHAR common_section[] = _T("Common");
	BOOL need_free = !commonSection;
	if (need_free)
		commonSection = _tcsdup(_T("Common"));
	TCHAR seps[] = _T("$()"), *token, *next_token;
	TCHAR inner_buffer[MAX_PATH]; 

	// получим исходную строку
	int ret_val = GetPrivateProfileString(section, key, NULL, value, sizeOfValue, fileName);

	TCHAR* start_mark = NULL; // начало замещаемой конструкции
	while (start_mark = _tcschr(value, _T('$')))
	{
		_tcscpy_s(inner_buffer, MAX_PATH, value);
		value[0] = _T('\0');
		start_mark += inner_buffer - value + 2;
		token = _tcstok_s(inner_buffer, seps, &next_token);
		while (token != NULL)
		{
			size_t cur_len = _tcsnlen(value, sizeOfValue);
			if (token == start_mark)
			{
				// если [секция]имя, разбиваем их нулем [секция0имя
				// и секцию читаем с первого символа
				TCHAR* custom_section = NULL;
				if (custom_section = _tcschr(token, _T(']')))
					*custom_section = _T('\0');
				ret_val = GetPrivateProfileString(
					custom_section?token+1:commonSection,
					custom_section?++custom_section:token,
					NULL, value + cur_len, sizeOfValue - cur_len, fileName);
				if (ret_val == 0)
					break; // нет какого-то ключа/секции
				// следующая замещаемая конструкция
				start_mark = _tcschr(next_token, _T('$')) + 2;
			}
			else
				_tcscpy_s(value + cur_len, sizeOfValue - cur_len, token);
			token = _tcstok_s(NULL, seps, &next_token);
		}
		if (ret_val == 0)
			break;
	}

	if (need_free)
		free(commonSection);

	return ret_val;
}

int _tmain(int argc, _TCHAR* argv[])
{
	TCHAR ini_file[] = _T("e:\\Visual Studio Projects\\INIParser\\test.ini");
	TCHAR buffer[MAX_PATH];
	TCHAR common_section[] = _T("Common");
	TCHAR section[] = _T("Final");
	TCHAR key[] = _T("megaFile");

	_putts(
		GetString(ini_file, section, key, buffer, sizeof(buffer)/sizeof(TCHAR))?
		buffer:_T("Error"));

	return 0;
}
Но в этом случае пути не должны содержать скобок. Что неправильно. Ведь никогда не знаешь, когда твоя программа окажется в каталоге Program Files (x86). Предлагаю в макросах заменить их на что-нибудь недопустимое, например ':'. Или '%'.
Приведенный код обрабатывает любое число подстановок в строке, например:
Код:
[Final]
part = public\release
megaFile = $(ResultDir)\$([Final]part)\release.txt
Про скобки в путях можно почитать в статьях:
_http://blog.not-a-kernel-guy.com/2006/08/15/33
_http://blog.not-a-kernel-guy.com/2006/11/29/106
Bishop вне форума