路径打印(上海交通大学)

借鉴某位佬的代码,注释比较多,里面也有一些我不太懂的部分,欢迎大家一起讨论。
测试用例粘这个:

4
a\b\c
a\d\e
b\cst
d\
0

下面是代码部分:

#include <iostream>
#include<string>
#include<algorithm>   //有sort函数
#include<vector>
using namespace std;

const int maxn=11;
vector<string> vec[maxn];   //vec是一个元素类型为string,大小为11的vector(也就是容器)
int n;          //路径总条数
string s;       //每条路径

int main()
{
    while(cin>>n&&n!=0){      //输入路径总条数
        for(int i=0;i<n;i++)
        {
            cin>>s;    //输入每条路径
            vec[i].clear();     //把上一次的测试用例清除掉
            vec[i].push_back(s);   //把新的测试用例放入
        }sort(vec,vec+n);   //默认从小到大排序
        for(int i=0;i<n;i++)
        {
            s=vec[i][0];   //第一个路径,这里的vector[i][0]为什么不能用vector[i]呢?我不太懂这个
            vec[i].clear();//把带\的字符串清除掉,准备填入新的不带\的字符串
            int j=0,index;
            while(j<s.size()){//截取,将“a\b\c”的字符串分割成{"a","b","c"}这样的字符串数组
                if((index=s.find('\\',j))!=string::npos){ //这里的意思是从字符串s下标为j的位置开始寻找,string::npos是指直到字符串的结尾(最大值为-1,通常和find搭配使用)
                    vec[i].push_back(s.substr(j,index-j));//substr截取函数,从第j位开始截取,截取index-j位,截取下来的是字母
                    j=index+1; //从\的后一个位置继续扫描并截取
                }
                else{
                    vec[i].push_back(s.substr(j,s.size()-j));//字符串的最后一个也要保存进去
                    break;
                }
            }
        }
        for(int i=0;i<n;i++) //打印
        {
            if(i==0){  //第一个直接输出
                for(int j=0;j<vec[i].size();j++)
                {
                    for(int k=0;k<j;k++)cout<<" ";
                    cout<<vec[i][j]<<endl;
                }
            }
            else{//找到与前一个字符串的第一个不相等的位置
                int j=0;
                while(j<vec[i-1].size()&&j<vec[i].size()&&vec[i][j]==vec[i-1][j])//找到与前一个字符串的第一个不相等的位置
                    j++;
                if(j==0)  //如果第一个字母就不相同,直接输出
                {
                    for(int k=0;k<vec[i].size();k++){
                        for(int l=0;l<k;l++)cout<<" "; //输出的是第几个字母前面就空几格
                        cout<<vec[i][k]<<endl;
                    }

                }else{   //找到的第一个不同的位置j,从j开始输出
                    for(int k=j;k<vec[i].size();k++){
                        for(int l=0;l<k;l++)cout<<" ";
                        cout<<vec[i][k]<<endl;
                    }
                }
            }
        }
        cout<<endl;
    }

}


下面只是一些我自己的一些知识补充,可不看

1.

vector.clear()函数并不会把所有元素清零。
vector有两个参数,一个是size,表示当前vector容器内存储的元素个数,一个是capacity,表示当前vector在内存中申请的这片区域所能容纳的元素个数。
通常capacity会比size大,如果往vector中push_back数据,这样就不用重新申请内存和拷贝元素到新内存区域了,便于节省时间。
所以vector.clear()的真正作用是:把size设置成0,capactiy不变。

2.

sort()基本使用方法:
 sort()函数可以对给定区间所有元素进行排序。它有三个参数sort(begin, end, cmp),其中begin为指向待sort()的数组的第一个元素的指针,end为指向待sort()的数组的最后一个元素的下一个位置的指针,cmp参数为排序准则,cmp参数可以不写,如果不写的话,默认从小到大进行排序。如果我们想从大到小排序可以将cmp参数写为greater()就是对int数组进行排序,当然<>中我们也可以写double、long、float等等。
 例如:sort(num,num+10,greater());
 sort中的cmp也可以自己定义,通俗来讲就是比较方式,如果我们需要按照其他的排序准则,那么就需要我们自己定义一个bool类型的函数来传入。
 例如:

#include <iostream>
#include<string>
#include<algorithm>   //有sort函数
#include<vector>
using namespace std;

struct Student{
    int number;  //学号
    int score;   //成绩
};

const int MAXN=100;

Student arr[MAXN];

bool Compare(Student x,Student y){
    if(x.score==y.score)          //成绩相等比较学号
        return x.number<y.number;
    else
        return x.score<y.score;  //成绩不等比较成绩 按照升序排列,如果想按照降序排列,则是return x.score>y.score
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&arr[i].number,&arr[i].score);
    }
    sort(arr,arr+n,Compare);  //按照比较函数比较,然后用sort排序(快排)
    for(int i=0;i<n;i++)
    {
        printf("%d %d\n",arr[i].number,arr[i].score);
    }

}

3.

什么是string::npos
C++手册里面给出的定义是这样的,string::npos就是一个公有的静态的常量类型的成员变量。使用前需要包含头文件。

具体定义如下:

static const size_type npos = static_cast<size_type>(-1);
1
这里的size_type就是类型size_t,size_t是一个无符号整形,那么-1也就是其最大值。

那么npos其实就是size_t的最大值,放到string类中也代表着:”until the end of the string”,作为一个返回值,在string类中代表的意思就是没有找到任何匹配字段(find, rfind, find_first_of,find_first_not_of等);

所以不要对npos有什么畏惧,它就是一个值,一个无符号整形的最大值。

什么地方用到了string::npos
std::string::npos 及时一个特殊的常量值,正式有了这个值才能让string和其他stl的迭代器使用不一样,也正是因为有了它才能让string类型的查找相对于其他同类型的stl查找效率更高。

string::npos常被用于find, rfind, find_first_of, find_last_of, find_first_not_of, substr, erase和find_last_not_of`,这些函数返回的类型都是size_t类型,当这些函数返回值和string::npos相等时说明查询到字符串结尾也没有找到查找的字符/字符子串。

string::npos的正确用法
使用stl迭代器习惯了很容易写出这样的代码,但是编译的时候却发现编译出错,这时因为find返回的时size_t类型的值,而不是迭代器。

auto iter = name.find(‘d’);
if (iter != name.end()) {

}
正确的用法如下:

// 查找s2字符串在s1中的位置 
void fun(string s1, string s2)
{
    // 查找s2字符串在s1中的位置 
    auto found = s1.find(s2);
    // 检查位置是否等于string::npos,如果不等说明找到了,如果相等说明没找到
    if (found != string::npos) {
        cout << "first " << s2 << " found at: " << (found)
             << endl;
    } else {
        cout << s2 << " is not in"
             << "the string" << endl;
    }
}

如果你不确定find返回值类型,最好使用auto,而不要使用int等类型承接,这样如果类型大小不一样会导致判断失误,比如你用uint16_t类型接返回值,来和string::npos判断是否相同,两个值都被赋值-1是,得到的值是不同的,一个是0xffff,一个是0xffffffff。

使用string::npos来去除字符串中的元音字母

std::string Disemvowel(const std::string& str) {
    // 定义一个字符串,用来承接剔除元音字母之后的字符串
    std::string vowelless;

    // 定义一个包含所有原因字母的字符串
    std::string vowels = "aeiouAEIOU";

    // 迭代查找,如果不是元音字母,就把它放到vowelless中
    for (char c : str) {
        if (vowels.find(c) == std::string::npos) {
            vowelless +=  c;
        }
    }

    // 将所有非原因字母组成的字符串返回
    return vowelless;
}

因此,可以看出std::string::npos是一个特殊的常量值,用来说明没有查找到的状态,这个值被用于std::string的很多成员函数,当这些成员函数返回std::string::npos时就说明没有找到你期望的值。

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值