是否有任何内置函数可用两个在C / C ++中的两个分隔符字符串之间获取字符串?

时间:2013-11-28 09:07:00

标签: c++

是否有任何内置函数可用于在C ++中的两个分隔符字符串之间获取字符串?

输入字符串

(23567)=(58765)+(67888)+(65678)

预期产出

23567
58765
67888
65678

include <iostream>
#include <stdexcept>
#include <string>
#include <sstream>
#include <vector>

std::vector<std::string> tokenize(const std::string& input)
{
  std::vector<std::string> result;
  std::istringstream stream(input);
  std::string thingie; // please choose a better name, my inspiration is absent today
  while(std::getline(stream, thingie, '('))
  {
    if(std::getline(stream, thingie, ')'))
      result.push_back(thingie);
    else
      throw std::runtime_error("expected \')\' to match \'(\'.");
  }
  return result;
}

void rtc()
{
  ifstream myfile(test.txt);
  if(myfile.is_open())
  while (!myfile.eof())
{
  getline(myfile,line);
auto tokens = tokenize(line);
  for(auto&& item : tokens)
    std::cout << item << '\n';
}
Error C4430 missing type specifier int assumed note:c++ does not support default int
ErrorC2440initializing cannot convertfrom std::vector<_ty>to int
Error C2059syntac error empty declaration
Error C2143syntax error missing;before&&
Error C2059syntax error:')'

6 个答案:

答案 0 :(得分:1)

使用std::getline

#include <iostream>
#include <stdexcept>
#include <string>
#include <sstream>
#include <vector>

std::vector<std::string> tokenize(const std::string& input)
{
  std::vector<std::string> result;
  std::istringstream stream(input);
  std::string thingie; // please choose a better name, my inspiration is absent today
  while(std::getline(stream, thingie, '('))
  {
    if(std::getline(stream, thingie, ')'))
      result.push_back(thingie);
    else
      throw std::runtime_error("expected \')\' to match \'(\'.");
  }
  return result;
}

int main()
{
  std::string test = "(23567)=(58765)+(67888)+(65678)";
  auto tokens = tokenize(test);
  for(auto&& item : tokens)
    std::cout << item << '\n';
}

Live example here


对于那些不完全相信这个解决方案的强大稳健性的人,我将其专门用于括号之间的double输入,并使用boost::lexical_cast来验证输入:

#include <iostream>
#include <stdexcept>
#include <string>
#include <sstream>
#include <vector>

#include <boost/lexical_cast.hpp>

std::vector<double> tokenize(const std::string& input)
{
  std::vector<double> result;
  std::istringstream stream(input);
  std::string thingie; // please choose a better name, my inspiration is absent today
  while(std::getline(stream, thingie, '('))
  {
    if(std::getline(stream, thingie, ')'))
    {
      try
      {
        result.push_back(boost::lexical_cast<double>(thingie));
      }
      catch(...)
      {
        throw std::runtime_error("This wasn't just a number, was it?");
      }
    }
    else
      throw std::runtime_error("expected \')\' to match \'(\'.");
  }
  return result;
}

int main()
{
  std::string test = "(23567)=(58765)+(67888)+(65678)";
  auto tokens = tokenize(test);
  for(auto&& item : tokens)
    std::cout << item << '\n';
  test = "(2h567)=(58765)+(67888)+(65678)";
  tokens = tokenize(test);
}

Live example here。现在去了解strtok实际上有多糟糕,或者当前的<regex>实现有多糟糕/不可移植。此外,对于那些怀疑boost::lexical_cast表现明智的人,please see the results for yourself

答案 1 :(得分:0)

strpbrk可用于查找每个令牌的开头 或strcspn可用于计算字符直到下一个标记 然后strspn可用于查找每个令牌的长度。

const char tokenChars[] = "0123456789";
char token = input;  // say input is "(23567)=(58765)+(67888)+(65678)"

while( 0 != (token = strpbrk( token, tokenChars )) )   // find token
{
    size_t tokenLen = strspn( token, token_chars );           // find length of token

    // print out tokenLen characters of token here!

    token+= tokenLen;                                  // go to end of token
}

http://www.cplusplus.com/reference/cstring/strspn/

http://www.cplusplus.com/reference/cstring/strcspn/

http://www.cplusplus.com/reference/cstring/strpbrk/

答案 2 :(得分:0)

如果你想使用指针,这就是答案:

char test[32] = "(23567)=(58765)+(67888)+(65678)";
char *output = NULL;
char *pos = (char *)test;
int length = 0;
while (*pos != '\0') {
    if(*pos == '(' || *pos == ')' || *pos == '+' || *pos == '=') {
        *pos = '\0';
        if (length > 0) {
            output = new char[length + 1];
            strncpy_s(output, length + 1, pos - length, length + 1);
            length = 0;
            cout << output << endl;
            delete [] output;
            output = NULL;
        }
    } else {
        length++;
    }
    pos++;
}

答案 3 :(得分:-1)

const char input[] = "(2av67q)=(ble ble)+(67888)+(qpa)";
int s = 0;

for(int i = 0; input[i]; i++)
{
    if ( input[i] == ')' )
    {
        cout << endl;
        s = 0;
    }
    else if ( input[i] == '(' )
    {
        s = 1;
        continue;
    }
    else
    {
        if ( s == 1 )
        {
            cout << input[i];
        }
    }
}

结果:

2av67q
ble ble
67888
qpa

答案 4 :(得分:-1)

虽然有些评论员可能讨厌它但我喜欢这个:

for (p = std::strtok(input, "+"); p != NULL; p = std::strtok(NULL, "+"))
{
// do more stuff
} 

这不会起作用 - 分隔符需要扩展 - 它展示了易用性。

答案 5 :(得分:-1)

以下是使用正则表达式的解决方案:

std::vector<std::string> get_numbers(std::string const& s)
{
    static std::regex regex(R"(^\((\d+)\)=\((\d+)\)(?:\+\((\d+)\))+$)",
                            std::regex_constants::ECMAScript
                            | std::regex_constants::optimize);

    std::vector<std::string> results;
    std::sregex_iterator matches(s.cbegin(), s.cend(), regex);
    for (auto first = matches->cbegin(), last = matches->cend();
         last != first;
         ++first)
    {
        results.push_back(first->str());
    }

    return results;
}