Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C/C++;使用空格作为分隔符_C++_C_String - Fatal编程技术网

C++ 在C/C++;使用空格作为分隔符

C++ 在C/C++;使用空格作为分隔符,c++,c,string,C++,C,String,很抱歉,我的C/C++不是很好,但即使对我来说,下面的现有代码也像垃圾。它还有一个错误-当str=“07/02/2010”被“\0”终止时失败。我认为与其修复bug,不如重写它。在Python中,它只是'kas\nhjkfh kjsdjkasf'.split()。我知道这是C-ish代码,但拆分字符串不会那么复杂!坚持相同的签名,并且不使用额外的库,我如何改进它-使其简短而甜美?我可以看出这段代码有异味,例如,因为最后的else子句 失败的行: _tcsncpy_s( s.GetBuff

很抱歉,我的C/C++不是很好,但即使对我来说,下面的现有代码也像垃圾。它还有一个错误-当str=“07/02/2010”被“\0”终止时失败。我认为与其修复bug,不如重写它。在Python中,它只是
'kas\nhjkfh kjsdjkasf'.split()
。我知道这是C-ish代码,但拆分字符串不会那么复杂!坚持相同的签名,并且不使用额外的库,我如何改进它-使其简短而甜美?我可以看出这段代码有异味,例如,因为最后的else子句

失败的行:

_tcsncpy_s(
    s.GetBuffer((int) (nIndex-nLast)),
    nIndex-nLast,
    psz+nLast,
    (size_t) (nIndex-nLast)
);
字符串“07/02/2010”以“\0”结尾,它将尝试将11个字符写入一个只有10个字符长的缓冲区

全功能:

#define 

// This will return the text string as a string array
// This function is called from SetControlText to parse the
// text string into an array of CStrings that the control
// Gadgets will attempt to interpret

BOOL CLVGridDateTimeCtrl::ParseTextWithCurrentFormat(const CString& str, const CGXStyle* pOldStyle, CStringArray& strArray )
{
    // Unused:
    pOldStyle;

    // we assume that the significant segments are seperated by space

    // Please change m_strDelim to add other delimiters

    CString s;

    LPCTSTR psz = (LPCTSTR) str;

    BOOL bLastCharSpace = FALSE;
    DWORD size = str.GetLength()+1;

    // (newline will start a new row, tab delimiter will
    // move to the next column).
    // parse buffer (DBCS aware)
    for (DWORD nIndex = 0, nLast = 0; nIndex < size; nIndex += _tclen(psz+nIndex))
    {
        // check for a delimiter
        if (psz[nIndex] == _T('\0') || _tcschr(_T("\r\n"), psz[nIndex]) || _tcschr(_T(" "), psz[nIndex])
            ||!_tcscspn(&psz[nIndex], (LPCTSTR)m_strDelim))
        {
            s.ReleaseBuffer();
            s.Empty();
            // abort parsing the string if next char
            // is an end-of-string
            if (psz[nIndex] == _T('\0'))
            {
                if (psz[nIndex] == _T('\r') && psz[nIndex+1] == _T('\n'))
                    nIndex++;

                _tcsncpy_s(s.GetBuffer((int) (nIndex-nLast)),
                    nIndex-nLast,
                            psz+nLast,
                            (size_t) (nIndex-nLast));
                CString temStr = s;
                strArray.Add(temStr);
                temStr.Empty();
                break;
            }

            else if (_tcscspn(&psz[nIndex], (LPCTSTR)m_strDelim) == 0 && !bLastCharSpace)
            {
                if (psz[nIndex] == _T('\r') && psz[nIndex+1] == _T('\n'))
                    nIndex++;

                _tcsncpy_s(s.GetBuffer((int) (nIndex-nLast)),
                    nIndex-nLast,
                            psz+nLast,
                            (size_t) (nIndex-nLast));
                CString temStr = s;
                strArray.Add(temStr);
                temStr.Empty();
                bLastCharSpace = TRUE;
                // abort parsing the string if next char
                // is an end-of-string
                if (psz[nIndex+1] == _T('\0'))
                    break;

            }
            // Now, that the value has been copied to the cell,
            // let's check if we should jump to a new row.
            else if (_tcschr(_T(" "), psz[nIndex]) && !bLastCharSpace)
            {
                if (psz[nIndex] == _T('\r') && psz[nIndex+1] == _T('\n'))
                    nIndex++;

                _tcsncpy_s(s.GetBuffer((int) (nIndex-nLast)),
                    nIndex-nLast,
                            psz+nLast,
                            (size_t) (nIndex-nLast));
                CString temStr = s;
                strArray.Add(temStr);
                temStr.Empty();
                bLastCharSpace = TRUE;
                // abort parsing the string if next char
                // is an end-of-string
                if (psz[nIndex+1] == _T('\0'))
                    break;
            }

            nLast = nIndex + _tclen(psz+nIndex);


        }
        else
        {   
            // nLast = nIndex + _tclen(psz+nIndex);
            bLastCharSpace = FALSE;
        }
    }
    if (strArray.GetSize())
        return TRUE;
    else
        return FALSE;
}

最好的方法是使用。该链接对于如何使用它应该是不言自明的,并且您也可以使用多个分隔符。非常方便的C函数。C++中的

< P>,最容易使用的是<代码> STSRIGSTROUND<<代码>:

std::istringstream buffer("kas\nhjkfh kjsdjkasf");

std::vector<std::string> strings;

std::copy(std::istream_iterator<std::string>(buffer),
          std::istream_iterator<std::string>(),
          std::back_inserter(strings));
“bizarro”部分是,如果第一个参数周围没有额外的括号,这将调用“最麻烦的解析”,因此它将声明一个函数,而不是定义一个向量。:-)

编辑2:就问题的编辑而言,直接回答几乎是不可能的——这取决于太多既不标准也不解释的类型(例如CGXStyle、CLVDateTime)。一、 首先,我根本无法了解它的任何细节。乍一看,这看起来是一个相当糟糕的设计,让用户输入或多或少模棱两可的内容,然后试图清理混乱。最好使用一个只允许明确输入的控件,您可以直接读取一些包含日期和时间的字段

Edit3:执行拆分的代码也将逗号视为分隔符,可以这样执行:

#include <iostream>
#include <locale>
#include <algorithm>
#include <vector>
#include <sstream>

class my_ctype : public std::ctype<char> {
public:
    mask const *get_table() { 
        // this copies the "classic" table used by <ctype.h>:
        static std::vector<std::ctype<char>::mask> 
            table(classic_table(), classic_table()+table_size);

        // Anything we want to separate tokens, we mark its spot in the table as 'space'.
        table[','] = (mask)space;

        // and return a pointer to the table:
        return &table[0];
    }
    my_ctype(size_t refs=0) : std::ctype<char>(get_table(), false, refs) { }
};

int main() { 
    // put our data in a strea:
    std::istringstream buffer("first kas\nhjkfh kjsdjk,asf\tlast");

    // Create a ctype object and tell the stream to use it for parsing tokens:
    my_ctype parser;
    buffer.imbue(std::locale(std::locale(), &parser));

    // separate the stream into tokens:
    std::vector<std::string> strings(
        (std::istream_iterator<std::string>(buffer)),
        std::istream_iterator<std::string>());

    // copy the tokes to cout so we can see what we got:
    std::copy(strings.begin(), strings.end(), 
        std::ostream_iterator<std::string>(std::cout, "\n"));
    return 0;
}
#包括
#包括
#包括
#包括
#包括
类my_ctype:public std::ctype{
公众:
掩码常量*get_table(){
//这复制了以下人员使用的“经典”表格:
静态std::vector
表格(经典表格(),经典表格()+表格大小);
//任何我们想要分离代币的东西,我们都会在表中将其位置标记为“空格”。
表[',']=(掩码)空间;
//并返回指向该表的指针:
返回&表[0];
}
my_ctype(size_t refs=0):std::ctype(get_table(),false,refs){
};
int main(){
//将我们的数据放入strea:
std::istringstream缓冲区(“第一个kas\nhjkfh kjsdjk,asf\tlast”);
//创建ctype对象并告诉流使用它来解析令牌:
我的ctype解析器;
imbue(std::locale(std::locale(),&parser));
//将流分离为令牌:
std::向量字符串(
(std::istream_迭代器(缓冲区)),
std::istreamu迭代器();
//将tokes复制到cout,这样我们就可以看到我们得到了什么:
std::copy(strings.begin()、strings.end(),
std::ostream_迭代器(std::cout,“\n”);
返回0;
}

在C/C++中解析字符串很少是一件简单的事情。您发布的方法似乎包含了相当多的“历史”。例如,您声明要在空白处拆分字符串。但该方法本身似乎使用成员变量m_strDelim作为分割决策的一部分。简单地替换该方法可能会导致其他意外问题


使用现有的标记化类可以大大简化事情。

对这个问题进行排序的一种非常简单的方法是使用Qt库。如果您使用的是KDE,那么它们已经安装好了。
QString
类有一个成员函数拆分,其工作原理与python版本类似。比如说

QString("This is a string").split(" ", QString::SkipEmptyParts)
返回
QString
s的
QStringList

["This", "is", "a", "string"]
(用pythonic语法)。请注意,第二个参数是必需的,否则如果单词被多个空格分隔,将返回每个单独的参数

一般在Qt库的帮助下,Python的简单性,如简单的字符串解析和列表迭代,都可以很容易地处理,并且具有C++的强大性。

< P>,您的问题有以下解决方案:

#include <string>
#include <deque>
#include "strtk.hpp"
int main()
{ 
   std::string data("kas\nhjkfh kjsdjkasf");
   std::deque<std::string> str_list;
   strtk::parse(data, ", \r\n", str_list);
   return 0;
}
#包括
#包括
#包括“strtk.hpp”
int main()
{ 
std::字符串数据(“kas\nhjkfh kjsdjkasf”);
std::deque str_列表;
strtk::parse(数据,“,\r\n”,str\u列表);
返回0;
}
您可以使用更多示例。即:

std::string myString;
std::向量拆分字符串;
boost::algorithm::split(splitStrings、myString、boost::是(“\r\n”)中的任意一个);

一个比我的另一个答案更好的方法:正则表达式功能。一个小教程,让你开始。这个答案是C++,使用正则表达式(这也许是最好的/最简单的方法来分割一个字符串),我最近自己使用过,所以我知道它是个不错的工具。

1,但是我确信某人会有一个疯狂的C++解决方案,包括BIZARRO语法来取消你的投票。这是一个很好的解决方案。如果你想使用C++,那就没有什么了。“疯狂”地利用语言的优势进行编码。如果
strtok
是正确的答案,你通常会问错误的问题。关于strtok有一个值得注意的小细节:它不是线程安全的。我不知道这是否真的适用于OP的问题,但仍然值得注意。
strtok()通常没有错
修改其输入-在大多数情况下,您希望使用
strtok()进行解析
你不再关心未解析的字符串了。字符串文字投诉也是假的;编译时常量字符串的运行时解析绝对是一个特例。酷,我们使用VS2010来编译它,所以
Boost
有点夸张,但我确信有很多库可用。等等,Jerry,我在哪里指定fy要标记的字符列表?请参阅上面Beh Tou Cheh的答案
["This", "is", "a", "string"]
#include <string>
#include <deque>
#include "strtk.hpp"
int main()
{ 
   std::string data("kas\nhjkfh kjsdjkasf");
   std::deque<std::string> str_list;
   strtk::parse(data, ", \r\n", str_list);
   return 0;
}
std::string myString;
std::vector<std::string> splitStrings;
boost::algorithm::split(splitStrings, myString, boost::is_any_of(" \r\n"));