写了一个简单的切分字符串的函数,竟然有错(vs2008下测试)

超级管理员9527 2009-07-09 05:48:26
为了调用方便,写了个切分字符串的函数,代码如下。
可运行的时候竟然有错,哪里的错误呢?待续。。。


template<typename charT, typename stringT>
int __cdecl SplitStringToN(const charT* lpszSrc, const charT c, bool bIgnorEmpty, stringT*, ...)
{
if (lpszSrc == NULL || *lpszSrc == 0)
return 0;

int nItem = 0;

va_list argList;
va_start(argList, bIgnorEmpty);

const charT* p1 = lpszSrc;
const charT* p2 = p1;
stringT*pString = NULL;

while (true)
{
//取得下一个参数的地址,以保存结果
if (pString == NULL || !bIgnorEmpty)
{
pString = va_arg(argList, stringT*);
}
if (pString == NULL)
{
break;
}

//获取下一个子串,并保存、计数
while (*p2 != 0 && *p2 != c) ++p2;
if (p1 != p2)
{
memcpy(lock_buffer(*pString, p2 - p1), p1, (p2 - p1) * sizeof(charT));
unlock_buffer(*pString);
pString = NULL;
}
if (pString == NULL || !bIgnorEmpty)
{
++nItem;
}

//判断是退出还是调整并继续
if (*p2 == 0)
{
break;
}
else
{
p1 = ++p2;
}
}

va_end(argList);

return nItem;
}
...全文
68 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
多谢各位的代码,对于代码不做评论
我的目的是想找到Debug和Release结果不同的原因

在vs2008下,va_arg在获得可选参数地址的时候,Debug版本和Release版本不同。
Debug版本获得的是第四个参数的地址,Release版本获得的是第五个参数的地址。
原因可能是我多了一个类型说明stringT*
写它的原因是调用的时候,根据它推到,不必写尖括号

CStringW str1, str2;
SplitStringToN(L"a=b", L'=', true, &str1, &str2, NULL);
而不是
SplitStringToN<wchar_t, CStringW>(L"a=b", L'=', true, &str1, &str2, NULL);

看来不想让我偷懒啊:(
iblold 2009-07-09
  • 打赏
  • 举报
回复
给个俺的实现,没有用string


int FindChars(const char* p, const char* f, bool br)
{
char* s = strstr((char*)p, f);
if (s)
{
if(br)
{
return strlen(p) - (s - p);
}
else
{
return s - p;
}
}
return -1;
}


char** spilwhit(char* str, char* strsp, DWORD* buf, int buflen, int& ct)
{
if(!str || !buf) return NULL;
int splen = strlen(strsp), k = 0;
char *s = str, *p = str;
ct = 0;
char** pr = (char**)buf;
while(*s)
{
if (FindChars(s, strsp, 0) == 0)
{
pr[ct] = p;
*s=0;
s+=splen;
p=s;
++ct;
if (ct==buflen) return pr;
}
++s;
}
pr[ct]=p;
++ct;
return pr;
}

用法:
char str[] = {"abc,def,ghi,123"};
DWORD buf[20], ct = 0;
char** p = spilwhit(str, ",", buf, 10, &ct);
for(int i=0; i<ct; ++i)
{
p[i]....
}

  • 打赏
  • 举报
回复
多谢各位捧场,我的代码没问题,只是release和debug的结果不一样
就是为了使用方便,不用CStringA CStringW string wstring的转来转去

功能稍强的还有一个代码

template<typename charT>
class StringSplitorT
{
public:
typedef std::basic_string<charT> stringT;

public:

StringSplitorT()
{
m_bIgnoreNull = true;
m_bJustOneOfSep = true;
}

// Split
//
size_t SplitString(const charT* str, const charT* sep, bool bJustOneOfSep, bool bIgnoreNull);

// Get Item
//
size_t GetCount()
{
return m_substr.size();
}
const charT* GetItem(size_t index)
{
if (index >= 0 && index < m_substr.size())
return m_substr[index].c_str();
else
return NULL;
}
const charT* operator[](size_t index)
{
return GetItem(index);
}

private:
void Split();

private:
stringT m_string;
stringT m_sep;
std::vector<stringT> m_substr;
bool m_bJustOneOfSep;
bool m_bIgnoreNull;
};

template<typename charT>
size_t StringSplitorT<charT>::SplitString(const charT* str, const charT* sep, bool bJustOneOfSep, bool bIgnoreNull)
{
m_string.clear();
m_substr.clear();
m_sep.clear();

m_bIgnoreNull = bIgnoreNull;
m_bJustOneOfSep = bJustOneOfSep;

if (str) m_string = str;
if (sep) m_sep = sep;

Split();

return m_substr.size();
}

template<typename charT>
size_t find_one_of(std::basic_string<charT>& str, std::basic_string<charT>& sep, size_t nStart)
{
size_t pos = std::basic_string<charT>::npos;

for (size_t i = nStart; i < str.size(); ++i)
{
if (sep.find(str[i]) != pos)//pos is -1(std::basic_string<charT>::npos)
return i;
}

return pos;
}

template<typename charT>
void StringSplitorT<charT>::Split()
{
if (m_string.empty() || m_sep.empty())
return;

stringT::size_type i = 0, j = 0;
size_t nSep = m_sep.size();
stringT strSubstr;

while(i <= m_string.size())
{
if (m_bJustOneOfSep)
j = find_one_of(m_string, m_sep, i);
else
j = m_string.find(m_sep, i);

if (j == stringT::npos)
{
j = m_string.size();
}

strSubstr = m_string.substr(i, j-i);

if (!strSubstr.empty() || !m_bIgnoreNull)
{
m_substr.push_back(strSubstr);
}

if (m_bJustOneOfSep)
i = j + 1;
else
i = j + nSep;
}
}

typedef StringSplitorT<char> StringSplitorA;
typedef StringSplitorT<wchar_t> StringSplitorW;

#if defined(UNICODE) || defined(_UNICODE)
typedef StringSplitorW StringSplitor;
#else
typedef StringSplitorA StringSplitor;
#endif
rendao0563 2009-07-09
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 Fleeboy 的回复:]
5L这个看起来不错
[/Quote]

用起来也不错。
Fleeboy 2009-07-09
  • 打赏
  • 举报
回复
5L这个看起来不错
rendao0563 2009-07-09
  • 打赏
  • 举报
回复

sSource = ReplaceString(sSource,"\n",""); 为了去掉\n 你不需要的话可以直接删掉。



std::string ReplaceString(std::string strSrc,std::string strPos,std::string strStr)
{
std::basic_string<char>::iterator IterL;
std::basic_string <char>::size_type indexCh1a = 0;
std::basic_string <char>::size_type off = 0;
std::string result6a = strSrc;
if (strPos.empty())
{
return strSrc;
}
while((indexCh1a = strSrc.find (strPos,off)) != std::string::npos)
{
IterL = strSrc.begin ( ) + indexCh1a;
off = indexCh1a + strStr.size();
result6a = strSrc.replace ( IterL , IterL+strPos.size() , strStr );
}
return result6a;
}

rendao0563 2009-07-09
  • 打赏
  • 举报
回复
你这个太麻烦。看不太懂。给你发个我用的吧。


//////////////////////////////////////////////////////////////////////////
/// 分割字符串
/// 位于字符串末尾的分割符总是被忽略
/// @param sSource 待分割的字符串
/// @param delim 分割字符
/// @param bEnableEmpty 是否允许空字符串,如果该参数设为true,则相连的两个
/// 分隔符之间认为存在一个空串(该参数默认值为false)
/// @return 字符串列表
//////////////////////////////////////////////////////////////////////////
std::vector<std::string> ExtractStrings(std::string sSource, char delim, bool bEnableEmpty)
{
std::string::size_type pos1, pos2;
std::vector<std::string> strParams;
pos2 = 0;
sSource = ReplaceString(sSource,"\n","");
while (pos2 != std::string::npos)
{
if (bEnableEmpty)
{
if (sSource[pos2] == delim)
{
pos2 += 1;
strParams.push_back("");
continue;
}
}

pos1 = sSource.find_first_not_of(delim, pos2);
if (pos1 == std::string::npos)
break;
pos2 = sSource.find_first_of(delim, pos1 + 1);
if (pos2 == std::string::npos)
{
if (pos1 != sSource.size())
strParams.push_back(sSource.substr(pos1));
break;
}
strParams.push_back(sSource.substr(pos1, pos2 - pos1));

pos2 += 1;
}
return strParams;
}
Walf_ghoul 2009-07-09
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 luwenzuo 的回复:]
if (pString == NULL || !bIgnorEmpty)

if (pString == NULL)

处理上有冲突,不是所想要的结果吧
[/Quote]
好眼力。。
大前置 2009-07-09
  • 打赏
  • 举报
回复
if (pString == NULL || !bIgnorEmpty)

if (pString == NULL)

处理上有冲突,不是所想要的结果吧
大前置 2009-07-09
  • 打赏
  • 举报
回复
if (pString == NULL || !bIgnorEmpty)

修改为
if (pString != NULL || !bIgnorEmpty)
  • 打赏
  • 举报
回复
//lock_buffer
inline char* lock_buffer(std::string& r, int n)
{
r.resize(n);
return const_cast<char*>(r.c_str());
}
inline wchar_t* lock_buffer(std::wstring& r, int n)
{
r.resize(n);
return const_cast<wchar_t*>(r.c_str());
}
inline char* lock_buffer(CStringA& r, int n)
{
return r.GetBuffer(n);
}
inline wchar_t* lock_buffer(CStringW& r, int n)
{
return r.GetBuffer(n);
}

//unlock_buffer
inline void unlock_buffer(std::string& r)
{
}
inline void unlock_buffer(std::wstring& r)
{
}
inline void unlock_buffer(CStringA& r)
{
r.ReleaseBuffer();
}
inline void unlock_buffer(CStringW& r)
{
r.ReleaseBuffer();
}

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧