【发布时间】:2017-05-14 08:38:53
【问题描述】:
我用隐式运算符编写了以下记录类型,以在此记录类型和字符串之间进行转换。它代表一个standard weather code,简要描述了当前的天气状况:
type
TDayNight = (dnDay, dnNight);
TCloudCode = (ccClear = 0, ccAlmostClear = 1, ccHalfCloudy = 2, ccBroken = 3,
ccOvercast = 4, ccThinClouds = 5, ccFog = 6);
TPrecipCode = (pcNone = 0, pcSlight = 1, pcShowers = 2, pcPrecip = 3, pcThunder = 4);
TPrecipTypeCode = (ptRain = 0, ptSleet = 1, ptSnow = 2);
TWeatherCode = record
public
DayNight: TDayNight;
Clouds: TCloudCode;
Precip: TPrecipCode;
PrecipType: TPrecipTypeCode;
class operator Implicit(const Value: TWeatherCode): String;
class operator Implicit(const Value: String): TWeatherCode;
function Description: String;
function DayNightStr: String;
end;
implementation
{ TWeatherCode }
class operator TWeatherCode.Implicit(const Value: TWeatherCode): String;
begin
case Value.DayNight of
dnDay: Result:= 'd';
dnNight: Result:= 'n';
end;
Result:= Result + IntToStr(Integer(Value.Clouds));
Result:= Result + IntToStr(Integer(Value.Precip));
Result:= Result + IntToStr(Integer(Value.PrecipType));
end;
class operator TWeatherCode.Implicit(const Value: String): TWeatherCode;
begin
if Length(Value) <> 4 then raise Exception.Create('Value must be 4 characters.');
case Value[1] of
'd','D': Result.DayNight:= TDayNight.dnDay;
'n','N': Result.DayNight:= TDayNight.dnNight;
else raise Exception.Create('First value must be either d, D, n, or N.');
end;
if Value[2] in ['0'..'6'] then
Result.Clouds:= TCloudCode(StrToIntDef(Value[2], 0))
else
raise Exception.Create('Second value must be between 0 and 6.');
if Value[3] in ['0'..'4'] then
Result.Precip:= TPrecipCode(StrToIntDef(Value[3], 0))
else
raise Exception.Create('Third value must be between 0 and 4.');
if Value[4] in ['0'..'2'] then
Result.PrecipType:= TPrecipTypeCode(StrToIntDef(Value[4], 0))
else
raise Exception.Create('Fourth value must be between 0 and 2.');
end;
function TWeatherCode.DayNightStr: String;
begin
case DayNight of
dnDay: Result:= 'Day';
dnNight: Result:= 'Night';
end;
end;
function TWeatherCode.Description: String;
begin
case Clouds of
ccClear: Result:= 'Clear';
ccAlmostClear: Result:= 'Mostly Clear';
ccHalfCloudy: Result:= 'Partly Cloudy';
ccBroken: Result:= 'Cloudy';
ccOvercast: Result:= 'Overcast';
ccThinClouds: Result:= 'Thin High Clouds';
ccFog: Result:= 'Fog';
end;
case PrecipType of
ptRain: begin
case Precip of
pcNone: Result:= Result + '';
pcSlight: Result:= Result + ' with Light Rain';
pcShowers: Result:= Result + ' with Rain Showers';
pcPrecip: Result:= Result + ' with Rain';
pcThunder: Result:= Result + ' with Rain and Thunderstorms';
end;
end;
ptSleet: begin
case Precip of
pcNone: Result:= Result + '';
pcSlight: Result:= Result + ' with Light Sleet';
pcShowers: Result:= Result + ' with Sleet Showers';
pcPrecip: Result:= Result + ' with Sleet';
pcThunder: Result:= Result + ' with Sleet and Thunderstorms';
end;
end;
ptSnow: begin
case Precip of
pcNone: Result:= Result + '';
pcSlight: Result:= Result + ' with Light Snow';
pcShowers: Result:= Result + ' with Snow Showers';
pcPrecip: Result:= Result + ' with Snow';
pcThunder: Result:= Result + ' with Snow and Thunderstorms';
end;
end;
end;
end;
可以转换为这种类型的字符串示例是......
-
d310= 多云和小雨(白天) -
d440= 阴雨和雷暴(白天) -
n100= 基本晴朗(夜间)
此字符串将始终采用此格式,并且始终为 4 个字符:1 个字母和 3 个数字。实际上,您可以将其视为以下选项:
- 0, 1
- 0、1、2、3、4、5、6
- 0、1、2、3、4
- 0、1、2
如果我可以将它变得足够小,我还想做一个选项,将其隐式转换为整数甚至字节。但是,我讨厌必须添加大量 if/then/else 或 case 语句。
我知道可以获取给定的(小)字符集并将它们转换为单个值。但是,我不知道它是如何完成的。例如,我知道这种技术用于DrawTextEx 上的标志和其他类似的WinAPI 调用等地方。我认为这可能与 shr / shl 的使用有关,但我不知道如何使用它们,并且在那种类型的数学上很糟糕。
如何将这 4 个属性组合成一个整数或字节,然后再将它们转换回来?
【问题讨论】:
-
class operator TWeatherCode.Implicit(const Value: String): TWeatherCode;- 这段代码是错误的,Delphi 向你发出警告。Value = 'D111'时的结果是什么?Value = 'xABC'会是什么结果? -
@Arioch'My IDE 在构建时不会产生任何提示或警告。而且我还没有添加这种保护,它仍在进行中:-)
-
它应该 - 你的 CASE 没有针对未列出元素的安全检查......你最好从一开始就做好所有保护 - 以后添加它永远不会起作用,你只是忘记了一些地方.所以基本上你从“这是错误!!!”的骨架开始。检查,然后添加正确的非错误值。这样你可能会忘记一些正确的值 - 你会在检查中找到它,但你不会忘记错误保护
-
....在更改 Delphi 版本后,经过长期测试的始终有效的函数开始对函数 8 的局部变量进行隐蔽的精确打击,从而调用堆栈。那么,你真的想成为为未来不幸的人隐藏那些地雷的人吗?在这里和现在穿着他们的鞋子走路?如果没有别的,请表示同情:-D
-
这不是演员表。这是编码。为什么要编码?您将如何处理编码值?