zoukankan      html  css  js  c++  java
  • string find 以及 stringstream的用法--由一道上机题说起

    今天做了一个上机题,题目很简单,正好重温下std::string类的一些接口以及stringstream的简单用法。

    题目:给定一个正整数,看作字符串,判断这个数是否包含两次或者两次以上的子串。

    如“12121”就包含两次“12”,

    再如”12345“就不包含重复的子串。

    一、std::string的find接口介绍

    首先解决一个问题,判定一个串t是否在串s中出现过的次数。这个可以使用std::string提供的find接口。

    这个接口的原型为:

    size_t find(string&str, size_t pos = 0);
    
    size_t find(char*s, size_t pos = 0);
    
    size_t find(char*s, size_t pos, size_type n);
    
    size_t find(char c, size_t pos =0);

    重载的4个接口里,返回类型均为size_t类型。

    如果找到对应的pattern,那么返回pattern在s中的第一个下标位置。

    如果查找失败,那么返回string::npos,这个值定义为常量-1

    static const size_t npos = -1;

    参数中的pattern既可以是string类型,也可以是char*类型,也可以是单个字符,所以常见的查找的对象基本被包含了。

    其中第三个接口被用来查找无“”结果的字符数组/buffer。查找的长度为n。

    string s = "abcdefg12";
    char t[3]={'d','e','f'};
    size_t idx = s.find(t, 0, 3);
    //cout << idx << endl;//3

    如果不指定n,那么就是第二个find声明,即期望patter为""结尾的字符串

    pos指的是从母串s中开始查找的位置下标。

    二、利用find接口查找重复子串

    const int TIMES = 2;
    
    bool check_dup_str(string& s, string& t)
    {
       size_t idx = 0;
      size_t beg = 0;
      idx = s.find(t, beg);
      while(string::npos != idx) {
        ++count;
        beg = idx + t.length();
        idx = s.find(t, beg);
      }
      
      if (count >= TIMES) {
        return true;
      } else {
        return false;
      }
    
    }

    函数check_dup_str用来检测t在s中出现的次数是否大于等于2,如果是返回true,否则返回false。

    这里使用了find的第一个重载的接口,t为对应的pattern, pos为母串中开始查找的位置。每次查找到一个pattern后,计数,同时跳过pattern的长度,在余下的母串中继续查找。

    三、完成题目

      这里直接蛮力解决,找出所有的子串,然后调用check_dup_str进行检查,一旦找到第一个满足的情况就退出。

    int check_dup_str(string& s)
    {
        bool found_flag = false;
        for (int i = 0; !found_flag && i < s.length()-1; i++) {
            for (int j = i+1; j < s.length(); j++) {
                string tmp_str = s.substr(i, j-i+1);
                if (is_t_in_s_2(s, tmp_str)) {
                    found_flag = true;
                    break;
                }
            }
        } // for
        
        if (found_flag) {
            return 1;
        } else {
            return 0;
        }
    }

    蛮力枚举子串就不多说,这里提下,退出两层循环的常用方法:“内部break+外部布尔变量”

    这里找到第一个满足的子串就退出函数。或者在内部for中直接return出来。

    如果需要在两层for之后继续其他逻辑,不想直接return,那么就内部先break出来,由于break只能退出一层,为了同时退出外层循环,可以break之前设置一个flag,这里是found_flag,使得退出内部for之后,found_flag为true,同时在外层循环中设置对这个flag的依赖。

    当外层for需要继续迭代的时候,由于依赖了内部设置的flag,因此会直接退出外层for循环,这样就实现了二层循环的退出。

    这应该是大一时候学习的方法吧,汗,早就忘记了,今天也是急中生智想出来:(。

    四、main函数

    int _tmain(int argc, _TCHAR* argv[])
    {
        int input;
        cin >> input;
        string str;
        stringstream ss;
        ss << input;
        ss >> str;
        cout << check_dup_str(str) << endl;
        return 0;
    }

    这里提到一下stringstream的用法,其实在C的<stdio。h>中包含了一些int/char/char*之间的转换,而stringstream则是采用对象封装的形式实现了这些基本常用类型之间的转换。老式转换中<stdio.h>,需要小心处理申请的缓冲区大小。如itoa, atoi等。

    而stringstream内部封装了buffer,可以根据具体的转换类型自行管理缓冲区,因此带来了方便。

    本题中将int转型为string类型。当然也可以string到int,类比同样可以char*到int等。(char*到string,string(char*), 再到int)

  • 相关阅读:
    EzHttp 流传输调用代码示例
    使用EzHttp框架 开发基于HTTP协议的CS轻应用
    [转]Installing Memcached on Windows
    SQLiteServer+SQLiteClient 用于.Net项目的SQLite服务端程序和客户端类库
    ERROR: Pillow-5.2.0-cp35-cp35m-win_amd64.whl is not a supported wheel on this platform.
    Linux下的tar压缩解压缩命令详解
    scp 基于 SSH 的安全远程服务器文件拷贝
    大批量删除列表中元素的方法,自己用本办法做的
    Python 列表 pop() 方法
    可遍历的数据对象enumerate() 方法的使用
  • 原文地址:https://www.cnblogs.com/crafet/p/3661567.html
Copyright © 2011-2022 走看看