gpt4 book ai didi

c++ - C++17中不定参数函数的错误

转载 作者:行者123 更新时间:2023-11-28 04:11:20 25 4
gpt4 key购买 nike

我写了一个字符串类,想在MFC的CString类中写一个类似Format()函数的函数。但是当我使用它时,它总是导致一些“随机”错误并且根本不起作用。

我使用 sprintf() 实现此功能,但是当我输入从 va_arg() 获得的参数时,它告诉我该参数无效。通过使用 std::string().c_str() ,这个错误消失了,但我得到了这个错误:

"At 0x00B326A0(Inside UString.exe)Csusing error: 0xC0000005: Access conflict occurs at read location 0x77000073" or it will turn to my throw() line.

这里是所有“格式化”函数及其支持的函数代码:

    std::string UString::SUBSTR(std::string src, int start, int stop)
{
if (start > stop)
{
return "null";
}
if ((stop - start) > src.length())
{
return "overload";
}
char* tmp = new char[src.length()];
for (int i = start; i <= stop; i++)
{
tmp[i - start] = src[i];
}
std::string ret = std::string(tmp);
delete[] tmp;
return ret;
}
std::wstring UString::STW(const std::string & str)
{
std::wstring ret;
try {
std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;
ret = wcv.from_bytes(str);
}
catch (const std::exception & e) {
std::cerr << e.what() << std::endl;
}
return ret;
}
bool UString::Matchopt(std::string s)
{
const std::string opt[10] = { "d","o","x","X","c","s","f","ld","lld","lf" };
for (int i = 0; i < 10; i++)
{
if (s == opt[i])
return true;
}
return false;
}
bool UString::IsLegalFormatStringEnd(char c)
{
std::string sg = "doxXsfc";
for (int i = 0; i < sg.length(); i++)
{
if (c == sg[i])
return true;
}
return false;
}
bool UString::IsLegalFormatString(std::string fms)
{
UString ustr = fms;
return ustr.legalstring(std::string("%-0123456789.cdoflsxX"));
}
std::string UString::GetSubFormatString(std::string full,int pos)
{
for (int i = pos; i < full.length(); i++)
{
if (IsLegalFormatStringEnd(full[i]))
{
printf("format string:%s,result:%d\n", SUBSTR(full, pos, i).c_str(), IsLegalFormatString(SUBSTR(full, pos, i)));
if (IsLegalFormatString(SUBSTR(full, pos, i)))
{
return SUBSTR(full, pos, i);
}
else
{
throw("UString: Unlegal Format String");
return "";
}
}
}
throw("UString: Unlegal Format String");
return "";
}
std::string UString::GetCoreString(std::string sfs)
{
UString utmp = sfs;
if (utmp.length() == 0)
{
throw("UString: Cannot get sub string from a empty source string");
}
else if (utmp.length() == 1)
{
if (Matchopt(utmp.std_str()))
{
return utmp.std_str();
}
else
{
throw("UString: Unlegal Format String");
}
}
else if (utmp.length() == 2)
{
if (Matchopt(utmp.substr(1, 1)))
{
return utmp.substr(1, 1);
}
else if (Matchopt(utmp.substr(0, 1)))
{
return utmp.substr(0, 1);
}
else
{
throw("UString: Unlegal Format String");
}
}
else if (Matchopt(utmp.substr(utmp.length() - 1, utmp.length() - 1)))
{
return utmp.substr(utmp.length() - 1, utmp.length() - 1);
}
else if (Matchopt(utmp.substr(utmp.length() - 2, utmp.length() - 1)))
{
return utmp.substr(utmp.length() - 2, utmp.length() - 1);
}
else if (Matchopt(utmp.substr(utmp.length() - 3, utmp.length() - 1)))
{
return utmp.substr(utmp.length() - 3, utmp.length() - 1);
}
else
{
throw("UString: Unlegal Format String");
return "";
}
}
void UString::format(std::string cmd, ...)
{
va_list vl;
int cnt = 0;
for (int i = 0; i < cmd.length(); i++)
{
if (i != (cmd.length() - 1))
{
if ((cmd[i] == '%') && (cmd[i + 1] != '%'))
{
cnt++;
}
}
}
if (cnt == 0)
{
str = std::string(cmd);
return;
}
else
{
va_start(vl, cnt);
std::string* cmdgroup = new std::string[cnt + 1];
int* pos = new int[cnt];
char* tmp = nullptr;
int posi = 0, posold = 0;
for (int i = 0; i < cmd.length(); i++)
{
if (i != (cmd.length() - 1))
{
if ((cmd[i] == '%') && (cmd[i + 1] != '%'))
{
pos[posi] = i;
posi++;
}
}
}
for (int i = 0; i < cnt; i++)
{
std::string full = GetSubFormatString(cmd, pos[i]);
std::string opt = GetCoreString(full);
char* buffer = NULL;
if (opt == "d" || opt == "o" || opt == "x" || opt == "X")
{
int tmpi = va_arg(vl, int);
sprintf(buffer, full.c_str(), tmpi);
}
else if (opt == "c")
{
char tmpc = va_arg(vl, char);
sprintf(buffer, full.c_str(), tmpc);
}
else if (opt == "s")
{
const char* tmpcp = va_arg(vl, char*);
std::string tmps = std::string(tmpcp);
sprintf(buffer, full.c_str(), tmps.c_str());
}
else if (opt == "f")
{
float tmpf = va_arg(vl, float);
sprintf(buffer, full.c_str(), tmpf);
}
else if (opt == "ld")
{
long tmpl = va_arg(vl, long);
sprintf(buffer, full.c_str(), tmpl);
}
else if (opt == "lld")
{
long long tmpll = va_arg(vl, long long);
sprintf(buffer, full.c_str(), tmpll);
}
else if (opt == "lf")
{
double tmpd = va_arg(vl, double);
sprintf(buffer, full.c_str(), tmpd);
}
delete[] buffer;
cmdgroup[i + 1] = std::string(buffer);
}
if (cmd[0] != '%')
{
cmdgroup[0] = SUBSTR(cmd, 0, pos[0] - 1);
}
else
cmdgroup[0] = "";
va_end(vl);
str = "";
for (int i = 0; i < cnt + 1; i++)
{
str = str + cmdgroup[i];
}
delete[] pos;
delete[] tmp;
delete[] cmdgroup;
}
return;
}
bool UString::legalstring(std::string sstr)
{
return legalstring(STW(sstr));
}
bool UString::legalstring(std::wstring wstr)
{
std::wstring ws = STW(str);
for (int i = 0; i < length(); i++)
{
for (int j = 0; j < wstr.length(); j++)
{
if (ws[i] == wstr[j])
break;
else if (j == (wstr.length() - 1))
return false;
}
}
return true;
}

它应该像这样工作:

UString ustr;
ustr.format("test:%d",5);
std::cout<<ustr<<std::endl;

输出应该是:test:5

最佳答案

有一种更快的方法来实现您的Format() 成员函数,使用神秘的vsnprintf() 函数!试试这个:

#include <stdio.h>
#include <stdarg.h>
#include <iostream>

class UString {
public:
char buffer[4096]; // Just to keep the code simple!
UString() : buffer {""} {}
inline void Format(const char* fmt, ...) {
va_list argList; va_start(argList, fmt);
vsnprintf(buffer, 4095, fmt, argList);
va_end(argList);
}
operator char* () { return buffer; }
};

int main()
{
UString test;
printf("Initial: >>>%s<<<\n", test.operator char *());
int i = 12; double d = 3.1415926536; const char* s = "Hello, World!";
test.Format("%s i = %d, d = %lf", s, i, d);
printf("Tested: >>>%s<<<\n", test.operator char *());
// Your test ...
UString ustr;
ustr.Format("test:%d", 5);
std::cout << ustr << std::endl;
return 1;
}

编辑:更正为更“标准”的 vsnprintf()

关于c++ - C++17中不定参数函数的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57722252/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com