【发布时间】:2015-06-30 21:03:54
【问题描述】:
我正在努力将一些旧代码引入 C++Builder XE7 环境。当我使用低级 i/o 库编译一个小型独立工具时,我收到此错误:
[ilink32 Error] Error: Unresolved external 'std::char_traits<char>::assign(char *, unsigned int, char)' referenced from <library>|mydate
mydate 类并不复杂,只有一个函数真正使用了 STL 类,即字符串(惊喜!)。如果我注释掉一个函数的内容,错误就会消失。该代码粘贴在下面,但在查看之前,需要注意一些事项:
这段代码是很久以前写的。我在 C++ Builder 6 开发环境中继承了它。几年前,我把它带到了 C++ Builder 2010,在那里它似乎工作得很好。
它这样做的部分原因是该代码也是为非 VCL 环境编译的。一切都在 char * 上标准化,因为它是可移植的。
我的第一个猜测是这是一个宽/窄字符串问题。我认为它应该都是窄字符串,但我无法以编译器喜欢的方式明确地缩小所有内容。
1234563作者正在使用其他 STL 类(地图等),或者他正在使用它来托管一个字符数组,他正在使用指针漫游(通常与下面的示例类似地进行手动标记)。
我没有能力让所有这些代码都达到 21 世纪的 C++ 标准。我确信有更好的方法来做这些事情,但是我没有足够的时间来重写/更新这个产品套件中的数百万行代码。我的目标是了解为什么这段代码现在会导致问题,以及如何通过尽可能少的更改来修复它。
据我所知,该方法甚至没有被应用程序调用。
类名已更改以保护有罪者。
所以,就是这样。您能告诉我为什么会导致上述链接错误吗?
非常感谢!
-凯伦
string myDate::Format(const char* format) const
{
string output;
if (julian == 0)
return output;
while (format[0] != '\0')
{
if (format[0] == 'm')
{
if (format[1] == 'm')
{
if (format[2] == 'm')
{
if (format[3] == 'm')
{
// mmmm Full name of month.
output += CMonthName();
format += 4;
}
else
{
// mmm Three letter abbreviation of month.
output += CMonthAbbr();
format += 3;
}
}
else
{
// mm Two digit month (zero fill).
const char* ptr = CMonth();
if (ptr[1] == '\0')
output += '0';
output += ptr;
format += 2;
}
}
else
{
// m One or two digit month (blank fill).
const char* ptr = CMonth();
if (ptr[1] == '\0')
output += '0';
output += ptr;
format += 1;
}
}
else if (format[0] == 'd')
{
if (format[1] == 'd')
{
if (format[2] == 'd')
{
if (format[3] == 'd')
{
// dddd Full name of day of week.
output += CDayName();
format += 4;
}
else
{
// ddd Three letter abbreviation of day of week.
output += CDayAbbr();
format += 3;
}
}
else
{
// dd Two digit day of month (zero fill).
const char *ptr = CDay();
if (ptr[1] == '\0')
output += '0';
output += ptr;
format += 2;
}
}
else
{
// d One or two digit day of month (blank fill).
const char *ptr = CDay();
if (ptr[1] == '\0')
output += ' ';
output += ptr;
format += 1;
}
}
else if (format[0] == 'y')
{
if (format[1] == 'y')
{
if (format[2] == 'y')
{
if (format[3] == 'y')
{
// yyyy Four digit year.
output += CYear();
format += 4;
}
else
{
// yyy Not valid (use \y\y\y for yyy)
return string();
}
}
else
{
// yy Two digit year (zero fill).
const char *ptr = CYearAbbr();
if (ptr[1] == '\0')
output += '0';
output += ptr;
format += 2;
}
}
else
{
// y Not valid (use \y or y)
return string();
}
}
else if (format[0] == '\\')
{
if (format[1] != '\0')
{
output += format[1];
format += 2;
}
}
else if (format[0] == ';')
{
// ignore rest of format text
break;
}
else
{
output += format[0];
format += 1;
}
}
return output;
}
【问题讨论】:
-
正如您所提到的,这可能是
char与wchar_t的问题。但这会在项目选项中进行配置,因此您可能应该检查并在此处发布您有哪些选项。您可以检查C++ (Shared Options)部分并查看_TCHAR 映射到什么。也许你只需要指定char而不是wchar_t这是新项目的默认值,IIRC。 -
它设置为
wchar_t,这是我们需要与我们在UI中使用的VCL控件交互的东西。据我了解,这应该只影响System::String,而不是string(来自Dinkumware stl)。至少在 CBB2010 中似乎是这样。如果我错了,我将经历巨大的痛苦。 -
您可以尝试将其更改为 char 看看会发生什么。但是,如果您使用 String 类型(仅是别名)并使用
.c_str()访问其字节并假设它是char *那么是的,移动所有内容可能会有些困难。一种可能的选择是不使用System::String,而是使用AnsiString。这样,当通过.c_str()访问时,您将获得一个char *缓冲区,如果您从 UI 分配,则转换会在 UnicodeString 和 AnsiString 之间自动发生。 -
感谢您的建议,罗德里戈,这就是我试图做的,但没有成功。我希望有人可能对为什么这不再起作用提出建议,所以我不会盲目地重写它。感谢您的帮助!
标签: string stl linker c++builder