I'm using swig to wrap around this C++ project and after having imported all the header files into my python code, I'm now working on re-creating the main class in python, but I'm having trouble looking for the corresponding data structures and data types.
Following is the main method under main.cpp
int main( int argc, char *argv[] )
{
string exe_name = argv[ 0 ];
string usage = "Usage: " + exe_name + " unigene.fasta [options]\n\
Options:\n\
-g <GC content> \tminimum GC content in percentage (Default 45).\n\
-G <GC content> \tmaximum GC content in percentage (Default 55).\n\
-m <temperature> \tlowest melting temperature in degrees of celsius (Default 0).\n\
-M <temperature> \thighest melting temperature in degrees of celsius (Default 100).\n\
-r <repeat.fasta> \tfasta file containing repeat DNA sequences.\n\
-t <top number> \tnumber of top oligos selected for each unigene (Default 1).\n\n";
string unigene_file;
// options only, each must have an associated value
int min_gc = 45;
int max_gc = 55;
int min_tm = 0;
int max_tm = 100;
int top_num = 1;
string repeat_file;
vector< string > m_argument;
for ( int i = 0; i < argc; i ++ ) {
string new_arg = argv[ i ];
m_argument.push_back( new_arg );
}
parse_argument( m_argument, usage, unigene_file,
min_gc, max_gc, min_tm, max_tm, top_num, repeat_file );
// initialize filtration parameters
float norm_min_gc = (float)min_gc / 100.0;
float norm_max_gc = (float)max_gc / 100.0;
string splice_file; // empty splice file
filt_param m_filtparam( norm_min_gc, norm_max_gc, min_tm, max_tm,
repeat_file, splice_file );
// screen unigenes for unique oligos
seqs m_unigene;
m_unigene.init( unigene_file );
// map from unigene names to oligo sequences
map< string, vector< string > > uniq_oligo;
get_unique_oligo( m_unigene, m_filtparam, top_num, uniq_oligo );
// output oligos
if ( uniq_oligo.empty() ) {
cout << "No valid oligo has been found. " << endl <<
"It could be due to one of the following reasons: " << endl <<
"1. input sequences are not unique, or " << endl <<
"2. they are repetitive DNAs, or " << endl <<
"3. GC% range is too restricted, etc. " << endl;
}
map< string, vector< string > > :: const_iterator m_itr;
for ( m_itr = uniq_oligo.begin(); m_itr != uniq_oligo.end(); m_itr ++ ) {
for ( int o_idx = 0; o_idx < (int)m_itr->second.size(); o_idx ++ ) {
cout << ">unique-oligo-" << o_idx+1 << "-of-unigene-" <<
m_itr->first << endl;
cout << m_itr->second[ o_idx ] << endl;
}
}
//system("PAUSE");
return 1;
}
For instance when I try passing an empty string (repeat_file) into filtparam() as done above, in python, I get the error
in method 'new_filt_param', argument 5 of type 'string const &'
How does one declare a 'string const &' type in python?
Also is there a structure like 'map' in python?
What you're looking for is the dict, which essentially works similar to C++'s map. More information can be found in the documentation.
Different question: Is there any reason you're recreating main() in Python rather than simply wrapping that one with SWIG? While SWIG is able to handle things like std::string in a limited way, I'd try to use a more simple interface using pointers/arrays only, rather than trying to pass any C++ objects or constructs.
Related
I have an structure named "Particle" and I want to create several objects whose names depends on an int.
As I am inside a for loop the name is going to change as follows: part0, part1, part2.
for (int i = 0; i<num_particles; i++)
{
//double sample_x, sample_y, sample_theta;
string name = "part" + std::to_string(i);
Particle name;
name.id = i;
name.x = dist_x(gen);
name.y = dist_y(gen);
name.theta = dist_theta(gen);
cout << "Sample" << " " << name.x << " " << name.y << " " << name.theta << endl;
}
As you can imagine this approach doesn't work, do you have any solution?
I have updated my question, now this is my new approach:
I have created a vector and an int "number of particles":
std::vector<Particle> particles;
And the function code:
void ParticleFilter::init(double x, double y, double theta, double std[]) {
// TODO: Set the number of particles. Initialize all particles to first position (based on estimates of
// x, y, theta and their uncertainties from GPS) and all weights to 1.
// Add random Gaussian noise to each particle.
// NOTE: Consult particle_filter.h for more information about this method (and others in this file).
default_random_engine gen;
normal_distribution<double> dist_x(x, std[0]);
normal_distribution<double> dist_y(y, std[1]);
normal_distribution<double> dist_theta(theta, std[2]);
//for (int i = 0; i<num_particles; i++)
//{
//double sample_x, sample_y, sample_theta;
//string name = "part";
//+ std::to_string(i);
//Particle particles;
particles[num_particles].id =num_particles;
particles[num_particles].x = dist_x(gen);
particles[num_particles].y = dist_y(gen);
particles[num_particles].theta = dist_theta(gen);
num_particles++;
cout << "Sample" << " " << particles[num_particles].x << " " << particles[num_particles].y << " " << particles[num_particles].theta << endl;
//}
}
But it doesn't work yet, it outputs "Segmentation fault".
you can use itoa() function of cstdlib simply in your code.
for (int i = 0; i<10; i++)
{
char a[max];
string pa="part_";
string name = pa + itoa(i,a,i+1) ;
cout << "Sample" << " " << name << endl;
}
}
Sample Output:
Sample part_0
Sample part_1
Sample part_2
Sample part_3
Sample part_4
Sample part_5
Sample part_6
Sample part_7
Sample part_8
Sample part_9
This construct exists in C++, it is called std::vector.
// we want to have a bunch of variables of type Particle
// all named particles[i] for i == 0,1,2....
std::vector<Particle> particles;
// create a new particle variable
particles.emplace_back(x, y, theta);
// print the variable number 42
std::cout << particles[42];
Why do you want to down the messy road of variable naming such as var0, var1, var2 and so on? I'd recommend creating an array or vector.
It's not clear from your code snippet that why you need to create variables with different names. Moreover, your code/usecase doesn't sit right with the concept of variable scoping.
For an assignment I have written two programs.
One for generating a file of random integers, the other for counting integers less than a specified threshold.
You can find the actual assignment texts below the code I've posted.
When compiling g++ generate.cpp -o generate, I get this error:
z1755294#hopper:~/assign2$ g++ generate.cpp -o generate
generate.cpp: In function ‘bool writeRand(int, int, int, const char*)’:
generate.cpp:12:31: error: variable ‘std::ofstream fout’ has initializer but incomplete type
ofstream fout ( fname );
When I compile g++ thresh.cpp -o thresh, I get this error:
z1755294#hopper:~/assign2$ g++ thresh.cpp -o thresh
thresh.cpp: In function ‘int main()’:
thresh.cpp:19:16: error: variable ‘std::ifstream fin’ has initializer but incomplete type
ifstream fin( fname.c_str() );
Can anyone help me fix my code to get it working? Also I need to create a Makefile for my project since I have multiple executables?
Thanks so much...kinda stuck on what to do.
This is my code:
generate.cpp
#include <iostream>
#include <cstdlib> // re. atoi
using std::cout;
using std::endl;
using std::cerr;
using std::ifstream;
using std::ofstream;
bool writeRand ( const int ranSeed, const int maxVal, const int numVals, const char* fname )
{
ofstream fout ( fname );
if ( fout )
{
srand ( ranSeed );
for ( int i=0; i < numVals; ++ i )
fout << rand () % (maxVal+1) << endl;
fout.close ();
return true;
}
//else
return false;
}
int main ( int argc, char* argv [] )
{
if (argc !=5 )
{
cerr << "Usage: " << argv[0] << "ranSeed maxVal numVals outFileName" << endl;
return -1;
}
const int ranSeed = atoi(argv[1]);
const int maxVal = atoi(argv[2]);
const int numVals = atoi(argv[3]);
const char* fname = argv[4];
if ( ranSeed <= 0 || maxVal <= 0 || numVals <= 0 )
{
cerr << "Invalid negative or zero numbers on command line....Try again..." << endl;
return -1;
}
if ( writeRand( ranSeed, maxVal, numVals, fname ) )
cout << "ranSeed = " << ranSeed << ", maxVal = " << maxVal << ", numVals = " << numVals
<< "\nfame " << fname << " was created ok ..." << endl;
else
cout << "There was a problem creating file " << fname << " ..." << endl;
}
thresh.cpp
#include <iostream>
#include <cstdlib> // re. atoi
using std::cout;
using std::endl;
using std::cin;
using std::ifstream;
using std::string;
using std::flush;
int main ()
{
//prompt and take in the desired file name
cout << "Enter name of file (for example randNums.txt): " << flush;
string fname;
getline( cin, fname );
//then can open file
ifstream fin( fname.c_str() );
if( fin )
{
int max, count = 0, below = 0, val = 0;
string line;
while( true )
{
cout << "Enter the threshold value: " << flush;
getline( cin,line );
max = atoi( line.c_str() );
if( max > 0 ) break;
cout << "Try again with value > 0 \n";
}
while( getline( fin, line) )
{
val = atoi( line.c_str() );
++count;
if( val < max ) ++below;
}
fin.close();
cout << below << " of " << count << " values in file '"
<< fname << "' are less than " << max << '\n';
max = val+1; //last value (in file) + 1
count = 0, below = 0;
fin.open( fname.c_str() );
while( getline( fin, line ) )
{
int val = atoi( line.c_str() );
++count;
if( val < max ) ++below;
}
fin.close();
cout << below << " of " << count << " values in file '"
<< fname << "' are less than " << max << '\n';
}
else
cout << "There was an error opening file " << fname << '\n';
cout << "Please 'Enter' to continue/exit..." << flush;
cin.get();
return 0;
}
Assignments
generate
Create a program called "generate" which generates a file of random integers.
This program takes four command line arguments. They are, in order
*A random number seed. This is an integer value explained below.
*A maximum value. The random values should be less than this maximum. This value is an integer.
*The number of values to be generated
*The name of an output file to store the values
If the command line arguments are not given, the program should give a brief message on proper usage and then exit. The integer values on the comand line should all be checked for negative values. If a negative value is given, the program should print an error message and exit.
Random number generation
The rand() function, found in returns a random positive integer every time it is called. The srand(int) function takes an integer called the random number seed which is used to initialize the random number generator. Subsequent calls to rand() produce a random sequence which is uniquely tied to its seed. Typically in a program, srand() is called once, while rand() is called multiple times.
A common technique for producing random numbers of a particular size is to use the remainder of divding rand() by the maximum upper bound.
thresh
Create a program called thresh which should ask the user for a file name and an integer threshold value. The program should then count the number of values in the file less than the threshold and report the results.
For example, 43 of 300 values in mydatafile are less than 17
This program should not use command line arguments. Rather, needed values should be obtained by prompting the user.
When asking for the threshold value, if the user inputs a negative value, the program should print an error and loop on the request until a proper value is obtained.
If the input file does not exist, an error message should be printed and the program should exit.
Hints:
Test your programs with small values that can be checked by hand. For example, create a file of 20 values less than 10. A particularly good test of thresh is to use the last value of the data file as a threshold value. Then use the last value plus one as a threshold value.
**A Makefile is required as part of your submission. If the project has multiple executables, you should have a default makefile rule to build all of the executables. You should have a rule to clear out the project to a pristine state. Your Makefile should use appropriate variables.
As #mrunion pointed out, you should replace
g++ generate.cpp thresh.cpp
with g++ generate.cpp
and g++ thresh.cpp
By the way, if you do these back to back, you'll overwrite your executable. An improvement would be:
g++ generate.cpp -o generate
and
g++ thresh.cpp -o thresh
my program compiles without error and appears to run through all of the steps correctly. It is supposed to make a php call and return data. tcpdump does show the request going out so popen is being executed, but the receiving party never updates.
The only discrepancy I can find, is that the command variable appears to be missing data.
# .trol.o
market max price is 0.00638671 at position 0
php coin.php 155 0.006387
0.00638672
the second line in the output is the command I am sending to popen
cout << command << endl; -> php coin.php 155 0.006387
that number is supposed to be the same as the one under it 0.00638672
The number 6 and the number 2 have been chopped off somehow.
How do I get the correct data into my popen command?
code:
void mngr(){
//vector defs
vector<std::string> buydat;
vector<std::string> markdat;
vector<std::string> pricedat;
vector<std::string> purchaseid;
vector<double> doublePdat;
vector<double> doubleMdat;
doublePdat.reserve(pricedat.size());
doubleMdat.reserve(markdat.size());
char buybuff[BUFSIZ];
char command[70];
char sendbuy[12];
buydat = getmyData();
markdat = getmarketbuyData();
//string match "Buy" and send results to new vector with pricedat.push_back()
for(int b = 2; b < buydat.size(); b+=7){
if ( buydat[b] == "Buy" ) {
pricedat.push_back(buydat[b+1]);
}
}
transform(pricedat.begin(), pricedat.end(), back_inserter(doublePdat), [](string const& val) {return stod(val);});
transform(markdat.begin(), markdat.end(), back_inserter(doubleMdat), [](string const& val) {return stod(val);});
auto biggestMy = std::max_element(std::begin(doublePdat), std::end(doublePdat));
std::cout << "my max price is " << *biggestMy << " at position " << std::distance(std::begin(doublePdat), biggestMy) << std::endl;
auto biggestMark = std::max_element(std::begin(doubleMdat), std::end(doubleMdat));
std::cout << "market max price is " << *biggestMark << " at position " << std::distance(std::begin(doubleMdat), biggestMark) << std::endl;
if (biggestMy > biggestMark){
cout << "Biggest is Mine!" << endl;
}
else if (biggestMy < biggestMark){
//cout << "Biggest is market!";
*biggestMark += 0.00000001;
sprintf(sendbuy,"%f",*biggestMark);
sprintf(command, "php coin.php 155 %s",sendbuy);
FILE *markbuy = popen(command, "r");
if (markbuy == NULL) perror ("Error opening file");
while(fgets(buybuff, sizeof(buybuff), markbuy) != NULL){
size_t h = strlen(buybuff);
//clean '\0' from fgets
if (h && buybuff[h - 1] == '\n') buybuff[h - 1] = '\0';
if (buybuff[0] != '\0') purchaseid.push_back(buybuff);
}
cout << command << endl;
cout << *biggestMark << endl;
}
}
I would try to use long float format instead of float as the type of biggestMark should be evaluated as iterator across doubles. I mean try to change sprintf(sendbuy,"%f",*biggestMark); to sprintf(sendbuy,"%lf",*biggestMark);. Hope this would help.
int a = max_element(highesthuman[0], highesthuman[2]);
if( win > loss)
{
cout << "You won " << (win-loss) << " games more than the computer did! You used " << a << " the most.";
}
}
The above array is given by
int humanrock = 0;
int humanpaper = 0;
int humanscissors = 0;
int highesthuman [3] = {humanrock, humanpaper, humanscissors};
When running my whole program I get an error saying "invalid type argument of unary". I looked this up but was not able to understand "pointers" or what people were referring too.
std::max_element() accepts two iterators as parameters, and returns an iterator. In your case iterators are pointers. So you should change
int a = max_element(highesthuman[0], highesthuman[2]);
to
int a = *max_element(highesthuman, highesthuman + 3);
I'm looking to read a text file using a relative path in C++. The directory structure is as follows: source -> Resources -> Settings -> Video.txt.
The contents of the file (note: these are used for testing, of course):
somes*** = 1
mores*** = 2
evenmores*** = 3
According to my research, this is possible. Still, I find that this has yet to work. For example, when I step through my debugger, my char *line variable which is used to receive line-by-line text file input is always at a constant 8 value. As to my understanding, a char pointer can act as a dynamic array of characters which you may reassign to.
Why can't I read my file? When I try do an if ( !videoSettings ), it returns true, and I get an error message (created by myself).
Code
#ifdef WIN32
const char *filePath = "Resources\\Settings\\Video.txt";
#else
const char *filePath = "Resources/Settings/Video.txt";
#endif
std::ifstream videoSettings( filePath );
if ( !videoSettings )
{
cout << "ERROR: Failed opening file " << filePath << ". Switching to configure mode." << endl;
//return false;
}
int count = 0;
char *line;
while( !videoSettings.eof() )
{
videoSettings >> line;
cout << "LOADING: " << *line << "; ";
count = sizeof( line ) / sizeof( char );
cout << "VALUE: " << line[ count - 1 ];
/*
for ( int i = count; i > count; --i )
{
if ( i == count - 4 )
{
}
}
*/
}
delete line;
Wow ok- you cannot read a string of text into just a char * you need to preallocate the memory first.
2nd the size of a char* pointer is constant - but the size of the data it points to is not
I suggest using the std::string getline call and avoid all the dynamic memory allocation
So this would be
std::ifstream in("file.txt");
std::string line;
while(getline(in, line))
{
std::cout << line << std::endl;
}
Lastly relative paths are the last of your problems in you code example :-)