鱼C论坛

 找回密码
 立即注册
查看: 3258|回复: 19

[已解决]C++分割函数

[复制链接]
发表于 2023-2-16 20:42:41 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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

int main(void) {
        cout << SPLIT("haha/fafa/dada/rara", '/', 2) << endl;
        return 0;
}
fafa
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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[s].insert(s, (const char *)x[i]);
                                                 ^~~~~~~~~~~~~~~~~~
 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[i] <= 'z' || 'A' <= x[i] <= '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[i] <= 'z' || 'A' <= x[i] <= 'Z')) {
                            ~~~~~~~~~~~ ^  ~~~
4 warnings generated.
然后我总觉得自己不是在读 C++ 代码而是一种别的语言,感觉很陌生,看不懂思路
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-2-16 21:29:44 | 显示全部楼层
写一写注释,说一说这个代码的实现思路
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-16 21:41:55 | 显示全部楼层
dolly_yos2 发表于 2023-2-16 21:03
编译器首先很不满意

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

为什么我的Dev-c++只有一个Warning
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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[j] << " ";
                }
                cout << endl;
                */
                
                if(x.c_str()[i] == fenge) {      //如果遇到要分割的字符,则在返回的列表中增加一个空字符串 
                        if(i == 0 || char(x[i-1]) != fenge)
                                ans.push_back(string());
                }
                else {                           //如果不是要分割的字符 
                        if(('a' <= x[i] && x[i] <= 'z') || ('A' <= x[i] && x[i] <= 'Z')) { // 如果是字母 
                                int s = ans.size()-1;                        //添加到返回的列表中的最后一个字符串中 
                                ans[s].insert(s, (const char *)x.c_str()[i]);
                                // cout << "ans[s]:" << ans[s] << endl;
                        }
                }
        }
        
        return ans;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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[j] << " ";
                }
                cout << endl;
                */
                
                if(x.c_str()[i] == fenge) {      //如果遇到要分割的字符,则在返回的列表中增加一个空字符串 
                        if(i == 0 || char(x[i-1]) != fenge)
                                ans.push_back(string());
                }
                else {                           //如果不是要分割的字符 
                        if(('a' <= x[i] && x[i] <= 'z') || ('A' <= x[i] && x[i] <= 'Z')) { // 如果是字母 
                                int s = ans.size()-1;                        //添加到返回的列表中的最后一个字符串中 
                                ans[s].insert(s, (const char *)x.c_str()[i]);
                                // cout << "ans[s]:" << ans[s] << endl;
                        }
                }
        }
        
        return ans;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-2-16 21:54:07 | 显示全部楼层

这个 insert 就极为别扭,里面的类型转换确定没问题吗?
看看 std::string::push_back 能不能用
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-2-16 21:56:11 | 显示全部楼层

我也看不懂你在做什么
说一说这个代码的实现思路
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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[j] << " ";
                }
                cout << endl;
                */
                
                if(x.c_str()[i] == fenge) {      //如果遇到要分割的字符,则在返回的列表中增加一个空字符串 
                        if(i == 0 || char(x[i-1]) != fenge)
                                ans.push_back(string());
                }
                else {                           //如果不是要分割的字符 
                        if(('a' <= x[i] && x[i] <= 'z') || ('A' <= x[i] && x[i] <= 'Z')) { // 如果是字母 
                                int s = ans.size()-1;                        //添加到返回的列表中的最后一个字符串中 
                                ans[s].push_back(x.c_str()[i]);
                                // cout << "ans[s]:" << ans[s] << endl;
                        }
                }
        }
        
        return ans;
}
现在运行完的结果还是
--------------------------------
Process exited after 3.907 seconds with return value 3221225477
请按任意键继续. . .
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-16 22:00:43 | 显示全部楼层
人造人 发表于 2023-2-16 21:56
我也看不懂你在做什么
说一说这个代码的实现思路

遍历字符串中的每一个字符
判断当前字符是不是分隔符
    如果是,添加一个新的字符串,但是如果自己的上一个字符也是分隔符的话,就不添加新字符串
    如果不是,
        如果是一个字母的话,就在列表中的最后一个字符串的最后加入这个字符。
        如果不是字母,就不进行操作。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

                ans[s].insert(s, (const char *)x.c_str()[i]); // 这是什么?
            }
        }
    }
    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;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-16 22:09:13 | 显示全部楼层

将字符加入最后一个字符串中
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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()[i] == fenge) {
        if(x[i] == fenge) {
            //if(i == 0 || char(x[i - 1]) != fenge) ans.push_back(std::string());   // x[i - 1] 的类型是什么?
            if(i == 0 || x[i - 1] != fenge) ans.push_back(std::string());
        } else {
            if(('a' <= x[i] && x[i] <= 'z') || ('A' <= x[i] && x[i] <= 'Z')) { // 如果是字母
                //int s = ans.size() - 1; // 添加到返回的列表中的最后一个字符串中
                size_t s = ans.size() - 1; // 添加到返回的列表中的最后一个字符串中
                //ans[s].insert(s, (const char *)x.c_str()[i]); // 这是什么?
                ans[s].push_back(x[i]);     // 是吧?
            }
        }
    }
    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$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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$

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
tommyyu + 5 + 5 + 3 感谢楼主无私奉献!

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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[i - 1];
}

int main(void) {
        cout << SPLIT("haha/fafa/dada/rara", '/', 2) << endl;
        return 0;
}
fafa
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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()[i] == fenge) {
        if(x[i] == fenge) {
            //if(i == 0 || char(x[i - 1]) != fenge) ans.push_back(std::string());   // x[i - 1] 的类型是什么?
            if(i == 0 || x[i - 1] != fenge) ans.push_back(std::string());
        } else {
            if(('a' <= x[i] && x[i] <= 'z') || ('A' <= x[i] && x[i] <= 'Z')) { // 如果是字母
                //int s = ans.size() - 1; // 添加到返回的列表中的最后一个字符串中
                size_t s = ans.size() - 1; // 添加到返回的列表中的最后一个字符串中
                //ans[s].insert(s, (const char *)x.c_str()[i]); // 这是什么?
                ans[s].push_back(x[i]);     // 是吧?
            }
        }
    }
    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;
}

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
tommyyu + 5 + 5 + 3 感谢楼主无私奉献!

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-2-16 23:21:39 | 显示全部楼层
没看懂。。。。。
vector<string> ans;    //这是一个容器嵌套,ans内的每个值都是一个string

if(i == 0 || char(x[i]) == fenge) {   //这里是想写  i == 0 || (char)(x[i]) == fenge 么? 可能更好的写法是 i== 0 || x.at(i) == fenge
                        ans.push_back(string());     //放进去一个空串?
                        if(ans.size() > 1 && ans[ans.size()-2] == 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[ans.size() - 1].append(1, x.at(i));
                }
        }

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
tommyyu + 5 + 5 + 3 感谢楼主无私奉献!

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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[i])
    {
        if(fenge==x[i])
        {
            if(i&&fenge!=x[i-1])
            {
                ans.push_back(x.substr(j,i-j));

            }
            j=i+1;
        }
        i+=1;
    }
    if(fenge!=x[i-1])
    {
        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[i])
    {
        if(fenge==x[i])
        {
            if(i&&fenge!=x[i-1])
            {
                ans.push_back(s);
                s="";

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

    }
    return ans;
}

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
tommyyu + 5 + 5 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

看不懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-17 21:21:12 | 显示全部楼层

看来还是要尽量使用c++的内置函数
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-17 19:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表