Python随机数据生成

思路

python的特性支持快速开发实用小程序的能力,能让你做事效率大幅度提高。特别是在c++数据测试中,检验一个程序的可靠性需要大量数据进行测试可靠性。虽然c++也有随机函数等方法但是不方便移植更改,用Python编写数据生成器是再合适不过的了。接下来进行举例说明:下面的代码直接在python3终端中运行,生成一个长度在4 ~9之间, 恰好包含一个大写字母, 其他字符为小写字母的特殊串。

>>> from random import* 
>>> from string import* 
>>> L = randint(4, 9) 
>>> s =''.join([choice(ascii_lowercase) for i in range(L)]) 
>>> p = randint(0, len(s)) 
>>> s[:p] + choice(ascii_uppercase) + s[p:] 
' bdsqVgke'

列表解析Clist comprehension) 是一种构造列表的简单方法。range(5) 生成列表[0,1,2,3,4]。这条语句就是 “对于列表[0,1,2,3,4]中的每个数i调用一次 choice(lowercase),把结果拼成一个列表” 。接下来用join函数把列表里的字符串连接起来。 .join(L)的作用是把字符串列表L中的各个字符串拼接起来。 最后随机出小写字符出现的位置p, 然后插入到大写字母串中。s[a:b]代表列表或者字符串的第a个元素到第b-1 个元素。a和b都可以省略,a默认为0, b默认为列表长度。L2 = L[:]的作用是创建一个和L 一样的数组。 由于Python 的所有值都是引用类型的, 因此L2=L只是把L中保存的引用拷贝(浅拷贝)到了L2,这点需要小心。例如下面的代码,求其地址id可以分析出来。

>>> a,b=1,2 
>>> a= [1,3,7] 
>>> b=[1,3,7] 
>>> c,d=a,a[:]
>>> id (a), id (b), id (c), id (d)
(12598008, 12517288, 12598008, 12517208)

计算 30!可以采用如下写法:

>>> from functools import*
>>> reduce(lambda x,y: x*y, range(1,31)) 
265252859812191058636308480000000L

简单实现

类似的东西还有很多。 使用Python后, 能大大缩短编写数据生成器、对拍器、 “猜想验证器” 等小程序的时间,这里我打算把python生成的数据全部转为字符数据存入文本中(转字符数据就不用考虑int位数 浮点数精度等问题)。c++再读数据存入容器进行原本函数的测试。

python生成数据代码

接下来的代码为进行测试写入文件的代码,作为参考:

# !/usr/bin/env python3
# coding: utf-8
from random import *
from string import *

def create_element0(lines, a = 4, b = 7):
    elements = []
    for i in range(lines):
        # ascii_lowercase在string中定义,为所有小写字符的列表
        # choice(seq): 返回列表、元组或字符串seq的随机项str。(可重复)
        L = randint(a, b)
        s =''.join([choice(ascii_lowercase) for i in range(L)])
        p = randint(0, len(s)) 
        element = s[:p] + choice(ascii_uppercase) + s[p:] + '\n'
        elements.append(element)
    return elements

def create_element1(lines):
    elements = []
    for i in range(lines):
        # sample: 不重复的取列表中i个元素,并返回这些元素组成的列表
        # 不可像choice中列表添加for in,因为其返回的是列表
        # 要生成m个不重复i元素列表得在外面加循环
        username = ''.join(sample(ascii_letters + digits, 5))
        password = randint(10000,99999)
        element= str(username) + "," + str(password) + '\n'
        elements.append(element)
    return elements

def create_element2(lines):
    elements = []
    allNum = list(range(-10000, 10000))
    NumLen = len(allNum)    
    #在allNum中抽取Len个不重复数字,最后依照题意排序,旋转。共lines组
    for i in range(lines):  
        s = []
        num = randint(1, 256)
        for j in range(num) :
            index = randint(j, NumLen - 1)
            s.append(allNum[index])
            # 把用过的元素到前面,以防再次选中
            allNum[index], allNum[i] = allNum[i], allNum[index]
        # 模拟target是否存在,有1/36的几率必定不存在
        suiji = randint(0,35)
        if suiji == 35:
            target = 10001
        else :
            target = s[randint(0, num-1)]
        #排序取出的不重复数组并旋转
        s.sort()
        k = randint(0, num-1)
        if k != 0 :
            s = list(reversed(s[0:k])) + list(reversed(s[k:num]))
            s.reverse()
        element = ' '.join([str(s[i]) for i in range(num)]) + '\n'
        elements.append(element)
        elements.append(str(target) + '\n')
        print(f"i = {i},\t k = {k}, \ttarget = {target}")
    return elements

C++读取文件代码

C++中各种流头文件说明 iostream处理控制台IO; fstream处理命名文件IO; stringstream完成内存string的IO。 类fstream和stringstream都是继承在类iostream的。 输入类都继承自istream,输出类都继承自ostream。 string流:sstream头文件定义了三个类型来支持内存IO, 这些类型可以向string写入数据,从string读取数据,就像string是一个IO流一样。 将所有行数据打印出: 该代码仅为读取数据并载入容器中作为模板使用,若要加入判断正确等功能可以根据实际情况添加

// 导入文本至容器,将每一行的数据以空格为间隔输入一个字符容器,将所有行的数据输入
int main() 
{
    string temp;
	ifstream myfile("./date.txt");
    if( !myfile ) {
        cout << "open file fail!" << endl;
        return -1;
    }

	vector<string> res;
	while (getline(myfile, temp)) {		//默认停止符\n
		stringstream slices(temp);
		string slice;
		while (slices >> slice) {		// 类似cin输入,将每行排除不可显字符 空格等字符输入容器,直到接收回车为止
			res.push_back(slice);
			// stoi(int), stol(long), stof(float), stod(double) 
		}
		// for( auto r : res)
		//	cout << r << endl;
		res.clear();
	}
	myfile.close();
    return 0;
}

实际测试案例

上述测试确定无问题后,开始实际做python数据导入c++中做测试: 其中c++代码为leetcode题目搜索旋转排序数组 python生成数据函数即为上述代码的create_element2用于测试判断c++代码是否正确 接下来是c++的读取文件并进行调用。

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

// 自己写的跟官方的思路差不多,官方答案不用先找到最大临界值再二分 直接进行判断二分 
// 下面为官方答案,注意 边界 等于 问题
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int n = (int)nums.size();
        if (!n) 
            return -1;
        else if (n == 1) 
            return nums[0] == target ? 0 : -1;

        int l = 0, r = n - 1;
        while (l <= r) {
            int mid = (l + r) / 2;
            if (nums[mid] == target) return mid;    // target判断是否为mid
            if (nums[0] <= nums[mid]) {             // 说明0到mid是升序
                if (nums[0] <= target && target < nums[mid])  // target在该升序中
                    r = mid - 1;
                else 
                    l = mid + 1;
            } 
            else {                                  // 说明mid到n-1是升序
                if (nums[mid] < target && target <= nums[n - 1])  // target在该升序中
                    l = mid + 1;
                else 
                    r = mid - 1;
            }
        }
        return -1;
    }
};

// 导入文本至容器测试,将每一行的数据以空格为间隔输入一个字符容器,将所有行的数据输入
int main() 
{
    string temp;
	ifstream myfile("./date.txt");
    if( !myfile ) {
        cout << "open file fail!" << endl;
        return -1;
    }

	vector<vector<int>> ress;
	vector<int> res;
	vector<int> targets;
	while (getline(myfile, temp)) {		//默认停止符\n
		stringstream slices(temp);
		string slice;
		while (slices >> slice) {		// 类似cin输入,将每行排除不可显字符 空格等字符输入容器,直到接收回车为止
			res.push_back(stoi(slice));
			// stoi(int), stol(long), stof(float), stod(double) 
		}
		getline(myfile, temp);
		targets.push_back(stoi(temp));
		// for( auto rio : res)
		// 	cout << rio << endl;
		ress.push_back(res);
		res.clear();
	}
	myfile.close();

	Solution su;
	for (int i = 0; i < ress.size(); i++) {
		int ans = su.search(ress[i], targets[i]);
		cout << targets[i] << ' ' << ans <<endl;
	}
	
    return 0;
}