tommyyu 发表于 2023-2-16 20:42:41

C++分割函数

这是我自己写的一个分割 string 类型的函数,现在在编译期不会出现问题,但是运行时会出问题,请问是什么原因,该怎么改{:10_254:}vector<string> split(string x, char fenge = ' ') {
        vector<string> ans;
       
        for(int i=0; i<x.length(); ++i) {
                /*cout << "i:" << i << endl;
                cout << "ans: ";
                for(int j=0; j<ans.size(); ++j) {
                        cout << ans << " ";
                }
                cout << endl;
                */
                if(i == 0 || char(x) == fenge) {
                        ans.push_back(string());
                        if(ans.size() > 1 && ans == string()) {
                                ans.erase(ans.begin() + ans.size()-2);
                        }
                }
                else {
                        if(('a' <= x <= 'z' || 'A' <= x <= 'Z')) {
                                int s = ans.size()-1;
                                ans.insert(s, (const char *)x);
                                // cout << "ans:" << ans << endl;
                        }
                }
        }
       
        return ans;
}

dolly_yos2 发表于 2023-2-16 21:03:05

编译器首先很不满意
warning: cast to 'const char *' from smaller integer type 'std::basic_string<char>::value_type'
      (aka 'char') [-Wint-to-pointer-cast]
                              ans.insert(s, (const char *)x);
                                                 ^~~~~~~~~~~~~~~~~~
warning: comparison of integers of different signs: 'int' and 'std::basic_string<char>::size_type'
      (aka 'unsigned long long') [-Wsign-compare]
      for(int i=0; i<x.length(); ++i) {
                     ~^~~~~~~~~~~
warning: result of comparison of constant 90 with expression of type 'bool' is always true
      [-Wtautological-constant-out-of-range-compare]
                        if(('a' <= x <= 'z' || 'A' <= x <= 'Z')) {
                                                ~~~~~~~~~~~ ^~~~
warning: result of comparison of constant 122 with expression of type 'bool' is always true
      [-Wtautological-constant-out-of-range-compare]
                        if(('a' <= x <= 'z' || 'A' <= x <= 'Z')) {
                            ~~~~~~~~~~~ ^~~~
4 warnings generated.
然后我总觉得自己不是在读 C++ 代码而是一种别的语言,感觉很陌生,看不懂思路

人造人 发表于 2023-2-16 21:29:44

写一写注释,说一说这个代码的实现思路

tommyyu 发表于 2023-2-16 21:41:55

dolly_yos2 发表于 2023-2-16 21:03
编译器首先很不满意

然后我总觉得自己不是在读 C++ 代码而是一种别的语言,感觉很陌生,看不懂思路

为什么我的Dev-c++只有一个Warning{:10_282:}

tommyyu 发表于 2023-2-16 21:44:15

本帖最后由 tommyyu 于 2023-2-16 21:46 编辑

人造人 发表于 2023-2-16 21:29
写一写注释,说一说这个代码的实现思路

vector<string> split(string x, char fenge = ' ') {
        vector<string> ans;
       
        for(int i=0; i<(int)x.length(); ++i) {
                /*cout << "i:" << i << endl;
                cout << "ans: ";
                for(int j=0; j<ans.size(); ++j) {
                        cout << ans << " ";
                }
                cout << endl;
                */
               
                if(x.c_str() == fenge) {      //如果遇到要分割的字符,则在返回的列表中增加一个空字符串
                        if(i == 0 || char(x) != fenge)
                                ans.push_back(string());
                }
                else {                           //如果不是要分割的字符
                        if(('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z')) { // 如果是字母
                                int s = ans.size()-1;                        //添加到返回的列表中的最后一个字符串中
                                ans.insert(s, (const char *)x.c_str());
                                // cout << "ans:" << ans << endl;
                        }
                }
        }
       
        return ans;
}

tommyyu 发表于 2023-2-16 21:45:56

dolly_yos2 发表于 2023-2-16 21:03
编译器首先很不满意

然后我总觉得自己不是在读 C++ 代码而是一种别的语言,感觉很陌生,看不懂思路

又改了一下vector<string> split(string x, char fenge = ' ') {
        vector<string> ans;
       
        for(int i=0; i<(int)x.length(); ++i) {
                /*cout << "i:" << i << endl;
                cout << "ans: ";
                for(int j=0; j<ans.size(); ++j) {
                        cout << ans << " ";
                }
                cout << endl;
                */
               
                if(x.c_str() == fenge) {      //如果遇到要分割的字符,则在返回的列表中增加一个空字符串
                        if(i == 0 || char(x) != fenge)
                                ans.push_back(string());
                }
                else {                           //如果不是要分割的字符
                        if(('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z')) { // 如果是字母
                                int s = ans.size()-1;                        //添加到返回的列表中的最后一个字符串中
                                ans.insert(s, (const char *)x.c_str());
                                // cout << "ans:" << ans << endl;
                        }
                }
        }
       
        return ans;
}

dolly_yos2 发表于 2023-2-16 21:54:07

tommyyu 发表于 2023-2-16 21:45
又改了一下

这个 insert 就极为别扭,里面的类型转换确定没问题吗?
看看 std::string::push_back 能不能用

人造人 发表于 2023-2-16 21:56:11

tommyyu 发表于 2023-2-16 21:44


我也看不懂你在做什么
说一说这个代码的实现思路

tommyyu 发表于 2023-2-16 21:57:39

dolly_yos2 发表于 2023-2-16 21:54
这个 insert 就极为别扭,里面的类型转换确定没问题吗?
看看 std::string::push_back 能不能用

vector<string> split(string x, char fenge = ' ') {
        vector<string> ans;
       
        for(int i=0; i<(int)x.length(); ++i) {
                /*cout << "i:" << i << endl;
                cout << "ans: ";
                for(int j=0; j<ans.size(); ++j) {
                        cout << ans << " ";
                }
                cout << endl;
                */
               
                if(x.c_str() == fenge) {      //如果遇到要分割的字符,则在返回的列表中增加一个空字符串
                        if(i == 0 || char(x) != fenge)
                                ans.push_back(string());
                }
                else {                           //如果不是要分割的字符
                        if(('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z')) { // 如果是字母
                                int s = ans.size()-1;                        //添加到返回的列表中的最后一个字符串中
                                ans.push_back(x.c_str());
                                // cout << "ans:" << ans << endl;
                        }
                }
        }
       
        return ans;
}
现在运行完的结果还是
--------------------------------
Process exited after 3.907 seconds with return value 3221225477
请按任意键继续. . .

tommyyu 发表于 2023-2-16 22:00:43

人造人 发表于 2023-2-16 21:56
我也看不懂你在做什么
说一说这个代码的实现思路

遍历字符串中的每一个字符
判断当前字符是不是分隔符
    如果是,添加一个新的字符串,但是如果自己的上一个字符也是分隔符的话,就不添加新字符串
    如果不是,
      如果是一个字母的话,就在列表中的最后一个字符串的最后加入这个字符。
      如果不是字母,就不进行操作。

人造人 发表于 2023-2-16 22:01:24

tommyyu 发表于 2023-2-16 22:00
遍历字符串中的每一个字符
判断当前字符是不是分隔符
    如果是,添加一个新的字符串,但是如果自己 ...

#include <iostream>
#include <string>
#include <vector>

std::vector<std::string> split(const std::string &x, char fenge = ' ') {
    std::vector<std::string> ans;
    //for(int i = 0; i < (int)x.length(); ++i) {
    for(size_t i = 0; i < x.length(); ++i) {
      if(x.c_str() == fenge) {   // 如果遇到要分割的字符,则在返回的列表中增加一个空字符串
            if(i == 0 || char(x) != fenge) ans.push_back(std::string());
      } else {    // 如果不是要分割的字符
            if(('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z')) { // 如果是字母
                int s = ans.size() - 1; // 添加到返回的列表中的最后一个字符串中

                ans.insert(s, (const char *)x.c_str()); // 这是什么?
            }
      }
    }
    return ans;
}

std::ostream &operator<<(std::ostream &os, const std::vector<std::string> &v) {
    bool flag = false;
    for(const auto &i: v) {
      if(flag)
            os << std::endl;
      flag = true;
      os << i;
    }
    return os;
}

int main() {
    {
      std::vector<std::string> v = split("12345", '.');
      std::cout << v << std::endl;
    }
    std::cout << "**************************" << std::endl;
    std::cout << split(".12345", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split("12.345", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split("12345.", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split(".1.23.45.", '.') << std::endl;
    return 0;
}

tommyyu 发表于 2023-2-16 22:09:13

人造人 发表于 2023-2-16 22:01


将字符加入最后一个字符串中

人造人 发表于 2023-2-16 22:24:18

tommyyu 发表于 2023-2-16 22:09
将字符加入最后一个字符串中

你这个思路太复杂了

sh-5.1$ cat main.cpp
#include <iostream>
#include <string>
#include <vector>

std::vector<std::string> split(const std::string &x, char fenge = ' ') {
    //std::vector<std::string> ans;
    std::vector<std::string> ans(1);    // 如果没有分隔符呢?
    for(size_t i = 0; i < x.length(); ++i) {
      //if(x.c_str() == fenge) {
      if(x == fenge) {
            //if(i == 0 || char(x) != fenge) ans.push_back(std::string());   // x 的类型是什么?
            if(i == 0 || x != fenge) ans.push_back(std::string());
      } else {
            if(('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z')) { // 如果是字母
                //int s = ans.size() - 1; // 添加到返回的列表中的最后一个字符串中
                size_t s = ans.size() - 1; // 添加到返回的列表中的最后一个字符串中
                //ans.insert(s, (const char *)x.c_str()); // 这是什么?
                ans.push_back(x);   // 是吧?
            }
      }
    }
    return ans;
}

std::ostream &operator<<(std::ostream &os, const std::vector<std::string> &v) {
    bool flag = false;
    for(const auto &i: v) {
      if(flag)
            os << std::endl;
      flag = true;
      os << i;
    }
    return os;
}

int main() {
    std::cout << "**************************" << std::endl;
    std::cout << split("abcdefg", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split(".abcdefg", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split("abcdefg.", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split(".abcdefg.", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split("ab.cde.fg", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split("..ab..cde..fg..", '.') << std::endl;
    return 0;
}
sh-5.1$ ./main
**************************
abcdefg
**************************

abcdefg
**************************
abcdefg

**************************

abcdefg

**************************
ab
cde
fg
**************************

ab
cde
fg

sh-5.1$

人造人 发表于 2023-2-16 22:29:22

我感觉还是我这个思路清晰
你那个太多的if else组合,要做到没有遗漏,没有重复,这并不容易
像你的那个if else就没有考虑到没有分隔符的情况
太多的if else就很容易出问题,因为那么多的条件组合起来,你很难考虑到所有情况,很容易遗漏一些情况,就像没有分隔符的情况,你就没有考虑到
所以还是尽量避免太多的if else组合

sh-5.1$ cat main.cpp
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

std::vector<std::string> split(const std::string &str, char sep) {
    std::vector<std::string> result;
    std::string::const_iterator b = str.begin();
    while(1) {
      std::string::const_iterator e = std::find(b, str.end(), sep);
      result.push_back(std::string(b, e));
      if(e == str.end()) break;
      b = e + 1;
    }
    return result;
}

std::ostream &operator<<(std::ostream &os, const std::vector<std::string> &v) {
    bool flag = false;
    for(const auto &i: v) {
      if(flag) os << std::endl;
      flag = true;
      os << i;
    }
    return os;
}

int main() {
    {
      std::vector<std::string> v = split("12345", '.');
      std::cout << v << std::endl;
    }
    std::cout << "**************************" << std::endl;
    std::cout << split(".12345", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split("12.345", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split("12345.", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split(".1.23.45.", '.') << std::endl;
    return 0;
}
sh-5.1$ ./main
12345
**************************

12345
**************************
12
345
**************************
12345

**************************

1
23
45

sh-5.1$

傻眼貓咪 发表于 2023-2-16 22:32:05

#include <iostream>
#include <sstream>
#include <vector>
using namespace std;

string SPLIT(string str, char c, int i = 1) {
        vector <string> results;
        istringstream temp(str);
        string token;
        while (getline(temp, token, c)) { results.push_back(token); }
        return results;
}

int main(void) {
        cout << SPLIT("haha/fafa/dada/rara", '/', 2) << endl;
        return 0;
}fafa

人造人 发表于 2023-2-16 22:37:32

#include <iostream>
#include <string>
#include <vector>

std::vector<std::string> split(const std::string &x, char fenge = ' ') {
    //std::vector<std::string> ans;
    std::vector<std::string> ans(1);    // 不对,不是没有分隔符的情况,是第一个字符不是分隔符的情况
                                        // 都说了,太多的if else组合,很难保证没有遗漏掉一些情况
                                        // 你这个思路太复杂了
                                        // 到目前为止,我依然无法保证没有漏掉一些情况
                                        // 除非我把所有能够想到的可能全部枚举出来,然后一个一个去试,看看是不是符合要求
                                        // 这个工作量可不小,我无法在大脑中直接完成这件事
                                        // 而我的那个代码,我就可以在大脑中直接跑出结果
                                        // 我用大脑跑了一遍程序,没有问题,然后又写代码,让计算机去跑一些边界值,然后也没发现问题
    //std::vector<std::string> ans(1);    // 如果没有分隔符呢?
    for(size_t i = 0; i < x.length(); ++i) {
      //if(x.c_str() == fenge) {
      if(x == fenge) {
            //if(i == 0 || char(x) != fenge) ans.push_back(std::string());   // x 的类型是什么?
            if(i == 0 || x != fenge) ans.push_back(std::string());
      } else {
            if(('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z')) { // 如果是字母
                //int s = ans.size() - 1; // 添加到返回的列表中的最后一个字符串中
                size_t s = ans.size() - 1; // 添加到返回的列表中的最后一个字符串中
                //ans.insert(s, (const char *)x.c_str()); // 这是什么?
                ans.push_back(x);   // 是吧?
            }
      }
    }
    return ans;
}

std::ostream &operator<<(std::ostream &os, const std::vector<std::string> &v) {
    bool flag = false;
    for(const auto &i: v) {
      if(flag)
            os << std::endl;
      flag = true;
      os << i;
    }
    return os;
}

int main() {
    std::cout << "**************************" << std::endl;
    std::cout << split(".abcdefg", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split("abcdefg.", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split(".abcdefg.", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split("ab.cde.fg", '.') << std::endl;
    std::cout << "**************************" << std::endl;
    std::cout << split("..ab..cde..fg..", '.') << std::endl;
    return 0;
}

两手空空儿 发表于 2023-2-16 23:21:39

没看懂。。。。。
vector<string> ans;    //这是一个容器嵌套,ans内的每个值都是一个string

if(i == 0 || char(x) == fenge) {   //这里是想写i == 0 || (char)(x) == fenge 么? 可能更好的写法是 i== 0 || x.at(i) == fenge
                        ans.push_back(string());   //放进去一个空串?
                        if(ans.size() > 1 && ans == string()) {   //这行没看懂
                              ans.erase(ans.begin() + ans.size()-2);
                        }
}


没有测试,楼主自己再完善一下吧
      vector<string> ans;
        ans.push_back("");
        for(int i = 0; i < x.size(); ++i){
                if(x.at(i) == fenge){
                        if(x.at(i + 1) == fenge){ //丢掉连续的
                                continue;
                        }else{
                                ans.push_back("");       
                        }
                       
                }else{
                        ans.append(1, x.at(i));
                }
        }

jhq999 发表于 2023-2-17 16:36:54

本帖最后由 jhq999 于 2023-2-17 16:45 编辑

//纯分割
#include <bits/stdc++.h>
using namespace std;
vector<string> split(string x, char fenge = ' ')
{
    vector<string> ans;
    int i=0,j=0;
    while(x)
    {
      if(fenge==x)
      {
            if(i&&fenge!=x)
            {
                ans.push_back(x.substr(j,i-j));

            }
            j=i+1;
      }
      i+=1;
    }
    if(fenge!=x)
    {
      ans.push_back(x.substr(j,i-j));

    }
    return ans;
}
//只留字母
vector<string> split(string x, char fenge = ' ')
{
    vector<string> ans;
    int i=0,j=0;
    string s="";
    while(x)
    {
      if(fenge==x)
      {
            if(i&&fenge!=x)
            {
                ans.push_back(s);
                s="";

            }
            j=i+1;
      }
      else if(('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z'))
      {
            s+=x.substr(i,1);
      }
      i+=1;
    }
    if(fenge!=x)
    {
      ans.push_back(s);

    }
    return ans;
}

tommyyu 发表于 2023-2-17 21:19:40

人造人 发表于 2023-2-16 22:29
我感觉还是我这个思路清晰
你那个太多的if else组合,要做到没有遗漏,没有重复,这并不容易
像你的那个i ...

{:10_282:}看不懂

tommyyu 发表于 2023-2-17 21:21:12

傻眼貓咪 发表于 2023-2-16 22:32


{:10_257:}看来还是要尽量使用c++的内置函数
页: [1]
查看完整版本: C++分割函数