Randomized Parameters Using System()? - c++

I am attempting to try some randomized parameters for minisat while calling the program using system(). I've never done anything like this before and have to admit I am pretty lost.
For example I can do like:
system("minisat -luby -rinc=1.5 <dataset here>")
How can I randomize it to be -luby or -no-luby and randomize the 1.5 value for -rinc?

system is only a normal function that receive a c-style string as the parameter. You can construct the string by yourself.
bool luby = true;
double rinc = 1.5;
system((std::string("minisat -")+(luby?"luby":"no-luby")+" -rinc="+std::to_string(rinc)).c_str());

You need construct the command dynamically with variables.
bool luby = true; // if you want -no-luby, set it to be false
double rinc = 1.5; // set it to be other values
char command[1024];
std::string luby_str = (luby ? "luby" : "no-luby");
std::snprintf(command, sizeof(command), "minisat -%s -rinc=%f", luby_str.c_str(), rinc);
system(command);
Just as #RemyLebeau pointing out, the C++ style should be better.
std::string command;
std::ostringstream os;
os << "minisat -" << luby_str << " -rinc=" << rinc;
system(command.c_str());

Here, you can try using a random string command generator like this, to create a randomized command:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <random>
#include <string>
std::string getCommand()
{
std::string result = "minisat ";
srand(time(0));
int lubyflag = rand() % 2; //Not the best way to generate random nums
//better to use something from <random>
if (lubyflag == 1)
{
result += "-luby ";
} else
{
result += "-no-luby ";
}
double lower_bound = 0; //Now were using <random>
double upper_bound = 2; //Or whatever range
std::uniform_real_distribution<double> unif(lower_bound,upper_bound);
std::default_random_engine re;
double rinc_double = unif(re);
result += "-rinc=" + rinc_double;
return result;
}
int main()
{
std::string command = getCommand();
system(command.c_str());
}
If you want all control, do this:
bool flaga = false;
double valueb = 1.5;
system(std::string("ministat " + ((flaga) ? "-luby " : "-no-luby ") +
"rinc= " + std::to_string(valueb)).c_str());

Related

Rounding converting from string to double/float

I am trying to extract a number from a string and convert it into a double or float so I can do some numerical operations on it. I am able to isolate the variable I need so the string consists only of the number, but when I try to convert it to a float or double it rounds the value, ie from 160430.6 to 160431.
//Helper Function to Extract Value of Interest
//Based on column of final digit of numbers being same across various FLOPS output files
double findValue(string &line, int &refN){
setprecision(100);
string output;
//go to end column and work backwards to get value string
while(line[refN] != ' '){
output = line[refN] + output;
refN = refN - 1;
}
const char* outputx = output.c_str();
double out = atof(outputx);
//removing the const char* line and replacing atof with stod(output) runs into the same issue
return out;
}
int main()
{
string name;
cin >> name;
ifstream file(name);
//opens file
if(!file.is_open()){"error while opening the file";
}else{
//Temporary Reference Definitions
string ref = "TOGW";
int refN = 25;
string line = findLine(file,ref);
double MTOGW = findValue(line, refN);
cout << MTOGW;
}
return 0;
}
I initially tried using stof() to convert, but that rounded. I have also tried using stod() and stold(), and last tried converting to a const char* and using atof(). I have messed with the setprecision() value, but also have not been able to solve it that way.
I cannot use Boost
You were almost there. The rounding was occurring on output, so that's where you need to use setprecision. That and always use double instead of float to ensure you have enough precision in your variables.
#include <vector>
#include <ranges>
#include <iomanip>
#include <iostream>
#include <string>
using std::string;
double findValue(string &line, int &refN){
//setprecision(100);
string output;
//go to end column and work backwards to get value string
while(line[refN] != ' '){
output = line[refN] + output;
refN = refN - 1;
}
const char* outputx = output.c_str();
double out = strtod(outputx, NULL);
return out;
}
int main()
{
string s = " 160430.6";
int n = s.size() - 1;
std::cout << std::setprecision(10) << findValue(s, n) << '\n';
}
See it in action on the Godbolt compiler.

My function does not always work because of the second argument

My trouble is that my function not always work, and i don't know why.
Here's my code:
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <string>
using namespace std;
void fill_zeros(std::string& fill_zeros_str, int fill_zeros_num){
if (fill_zeros_str.length()<fill_zeros_num){
int i = 0;
for (i=0;i<=((int)fill_zeros_num)-((int)fill_zeros_str.length());i++){
fill_zeros_str = "0"+fill_zeros_str;
}
}
}
int main(){
string testString = to_string(2);
fill_zeros(testString,7);
cout << testString << "\n";
return 0;
}
The second argument of fill_zeros (fill_zeros_num) does not work all the time, and I don't know why.
Because in
for (i=0;i<=((int)fill_zeros_num)-((int)fill_zeros_str.length());i++)
the length of fill_zeros_str changes as you add zeros(decrease by one), and you are also adding one to i(so, the start is adding by one, and the end is decreasing by one). So the best way is to define a length at the beginning of the function to store the string length.
Your loop is modifying the std::string on each iteration, which affects its length(). The loop is re-evaluating the length() on each iteration.
You need to calculate the number of zeros wanted and save that value to a local variable first, and then use that variable in your loop. Also, your loop needs to use < instead of <=.
Try this:
void fill_zeros(std::string& str, size_t min_length){
if (str.length() < min_length){
size_t fill_zeros_num = min_length - str.length();
for (size_t i = 0; i < fill_zeros_num; ++i){
str = "0" + str;
// or: str.insert(0, "0");
// or: str.insert(0, '0');
// or: str.insert(str.begin(), '0');
}
}
}
Live Demo
However, there is a much simpler way to implement fill_zeros() that doesn't involve using a manual loop at all:
void fill_zeros(std::string& str, size_t min_length){
if (str.length() < min_length){
str = std::string(min_length - str.length(), '0') + str;
// or: str.insert(0, std::string(min_length - str.length(), '0'));
// or: str.insert(str.begin(), std::string(min_length - str.length(), '0'));
// or: str.insert(0, min_length - str.length(), '0');
// or: str.insert(str.begin(), min_length - str.length(), '0');
}
}
Live Demo
Alternatively:
#include <sstream>
#include <iomanip>
void fill_zeros(std::string& str, size_t min_length){
if (str.length() < min_length){
std::ostringstream oss;
oss << std::setw(min_length) << std::setfill('0') << str;
str = oss.str();
}
}
Live Demo
In which case, you could simply get rid of fill_zeros() altogether and apply the I/O manipulators directly to std::cout in main() instead:
#include <iostream>
#include <iomanip>
int main(){
std::cout << std::setw(7) << std::setfill('0') << 2 << "\n";
return 0;
}
Live Demo

Find sum of numbers in a string without loops in c++

I've found plenty of resources online how how to calculate the sum of numbers in an alphanumeric string, and I've got a working c++ code below.
#include <iostream>
using namespace std;
int findSum(string str)
{
string temp = "";
int sum = 0;
for (char ch: str)
{
if (isdigit(ch))
temp += ch;
else
{
sum += atoi(temp.c_str());
temp = "";
}
}
return sum + atoi(temp.c_str());
}
int main()
{
string str = "t35t5tr1ng";
cout << findSum(str);
return 0;
}
For the example above, "t35t5tr1ng" returns "41".
Now I'm trying to do the same thing, without using any loops.
On the top of my head, I'm thinking arrays, but even then I'm not sure how to parse the values in the array without a for loop of some kind.
Any suggestions or help would be appreciated!
You can use standard algorithms instead of writing loops. Even if it's just a for-loop under the hood, but it can make user code easier to understandby stating the intent.
int findSum(string str)
{
// replace all the non-digits with spaces
std::replace_if(str.begin(), str.end(),
[](unsigned char c) {
return !std::isdigit(c);
}, ' ');
// sum up space separated numbers
std::istringstream iss{str};
return std::accumulate(
std::istream_iterator<int>{iss},
std::istream_iterator<int>{}, 0);
}
Here's a demo.
Here is another solution using std::accumulate:
#include <numeric>
#include <iostream>
#include <string>
#include <cctype>
int findSum(std::string str)
{
int curVal = 0;
return std::accumulate(str.begin(), str.end(), 0, [&](int total, char ch)
{
// build up the number if it's a digit
if (std::isdigit(static_cast<int>(ch)))
curVal = 10 * curVal + (ch - '0');
else
{
// add the number and reset the built up number to 0
total += curVal;
curVal = 0;
}
return total;
});
}
int main()
{
std::string str = "t35t5tr1ng";
std::cout << findSum(str);
return 0;
}

C++ std::sort function gets not finished?

im currently setting up the highscore-part for a game and I have a very weird problem because of the weird behaviour of the std::sort function.
Im doing the whole thing in RAD Studio 10.2 (Embarcadero IDE) in C++.
So he is my code:
std::string Line;
int count = 0;
int i = 0;
ifstream File("Highscore.txt");
if(File.is_open())
{
while(getline(File, Line))
{
count += 1;
}
File.close();
}
ifstream ReadFile("Highscore.txt");
if(ReadFile.is_open())
{
string *scores = NULL;
scores = new string[count];
while(getline(ReadFile, Line))
{
scores[i] = Line;
i += 1;
}
ReadFile.close();
std::sort(scores, (scores+count));
UnicodeString Uscores1 = scores[0].c_str();
UnicodeString Uscores2 = scores[1].c_str();
UnicodeString Uscores3 = scores[2].c_str();
UnicodeString Uscores4 = scores[3].c_str();
UnicodeString Uscores5 = scores[4].c_str();
LScore1->Caption = Uscores1;
LScore2->Caption = Uscores2;
LScore3->Caption = Uscores3;
LScore4->Caption = Uscores4;
LScore5->Caption = Uscores5;
}
I get no errors from the compiler/linker and everything work should fine.
The string array gets filled correctly and so on.
But its not sorting.
To show the problem to you I made a screenshot - on the left you can see the txtfile with the scores; on the right you can see the output after the sorting algorithm:
My question now is why this is happening?
Thanks for you help
Welcome to C++. Since you want to list numbers by rank, read them as int not string. Forget about operator new. You will not need it for years, if ever. Use standard containers like std::vector, which take care of the memory allocation and de-allocation transparently.
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
int main() {
using namespace std;
vector<int> scores;
{
ifstream inp("Highscore.txt");
int next;
while (inp >> next) {
scores.push_back(next);
}
}
sort(scores.begin(), scores.end());
for (auto s : scores) {
cout << s << '\n';
}
return 0;
}
How about something like:
int i = 0;
int * scoresInteger = NULL;
scoresInteger = new int[count];
for(i = 0; i < count; i++)
{
scoresInteger[i] = std::stoi(scores[i]);
}
std::sort(scoresInteger, scoresInteger + count);
If you need to, you can convert the integers back into strings using targetStrings[i] = std::to_string(scoresInteger[i]).
string * targetScores = NULL;
targetScores = new std::string[count];
for(i = 0; i < count; i++)
{
targetScores[i] = std::to_string(scoresInteger[i]);
}
delete [] scoresInteger;
scoresInteger = NULL;
Don't forget to delete [] targetScores later.
My question now is why this is happening?
Because your scores are compared as strings and not as ints. Because of that "3" is greater that "25"
std::cout << std::boolalpha << (std::string("3") > std::string("25")) << std::endl; // true
Luckily you can pass a custom comparator (or lambda) to the std::sort to make it behave just as you want:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
const int count = 5;
std::string scores[count] = { "35","25","3","4","5" };
// TWEAKED SORT
std::sort(scores, scores + count, [](std::string const &s1, std::string const &s2)
{
return std::stoi(s2) < std::stoi(s1);
});
// TEST
for (auto const &s : scores)
{
std::cout << s << std::endl;
}
}
The compared strings in the above example are converted to ints and then compared, resulting in the desired sorting order.
35
25
5
4
3
Please note that I do not agree with the rest of your code and I think you should rethink the implementation, as it would be much easier, safer and more efficient to use std::vector<std::string> for your task.

C++ SDL 2.0 - Importing multiple textures using a loop

I don't know whether or not this is possible but I have used this technique in different languages but am struggling to use it in C++. I have 10 images that I am trying to load into an array using a loop as so:
for (int i = 0; i < 10; i++)
{
Sprite[i] = IMG_LoadTexture(renderer, "Graphics/Player" + i + ".png");
}
This however does not seem to work in C++ so I was wondering what I am doing wrong, or what can I do to get the same result without having to load each image individually like so:
Sprite[0] = IMG_LoadTexture(renderer, "Graphics/Player0.png");
My error is: "Expression must have integral or unscoped enum type"
Thanks for any help =)
You cannot do this:
"This is my number: " + (int)4 + "!";
This is illegal. It will give you an error for trying to operator+ a const char* and a const char[SOME_INT_GOES_HERE] or another error for trying to use operator+ to add an int onto a string. Things just don't work that way.
You'd either have to use C (i.e. snprintf()) or a string stream. Here's my test code for isolating your problem:
#include <iostream>
#include <string>
int main()
{
int a = 1;
std::string str = "blah";
std::string end = "!";
//std::string hello = str + a + end;// GIVES AN ERROR for operator+
std::string hello = "blah" + a + "!";
//const char* c_str = "blah" + a + "end";
//std::cout << c_str << std::endl;
std::cout << hello << std::endl;
return 0;
}
Here's an alternative solution using string streams.
#include <iostream>
#include <string>
#include <sstream>
int main()
{
int i = 0;
std::string str;
std::stringstream ss;
while (i < 10)
{
//Send text to string stream.
ss << "text" << i;
//Set string to the text inside string stream
str = ss.str();
//Print out the string
std::cout << str << std::endl;
//ss.clear() doesn't work. Calling a constructor
//for std::string() and setting ss.str(std::string())
//will set the string stream to an empty string.
ss.str(std::string());
//Remember to increment the variable inside of while{}
++i;
}
}
Alternatively, you can also use std::to_string() if you're using C++11 (which just requires -std=c++11) but std::to_string() is broken on some sets of compilers (i.e. regular MinGW). Either switch to another flavor where it works (i.e. MinGW-w64) or just write your own to_string() function using string streams behind the scenes.
snprintf() may be the fastest way of doing such a thing, but for safer C++ and better style, it is recommended you use a non-C way of doing things.
I had a similar problem and I solwed it this way:
#include <iostream>
using namespace std;
int main() {
string line;
for (int i = 0; i < 10; i++) {
line = "Graphics/Player" + inttostr(i) + ".png"; //I wrote inttostr function because built in inttostr functions messed up my program (see below)
char charger[line.length()]; //creating char array
for (int i = 0; i < sizeof(line); i++) {
charger[i] = line[i]; // copying string to char arry
}
Sprite[i] = IMG_LoadTexture(renderer, charger);
}
}
string inttostr(int integer) { //I know it isn't the best way to convert integer to string, but it works
string charakter;
int swap;
bool negativ = false;
if (integer < 0) {
integer = -integer;
negativ = true;
}
if (integer == 0) {
charakter = "0";
}
while (integer >= 1) {
swap = integer % 10;
integer = integer / 10;
charakter = char(swap + 48) + charakter;
}
if (negativ) {
charakter = "-" + charakter;
}
return charakter;
}