I am looking for a C/C++ macro that can transform a random SVN revision like "$Revision: 9 $" or "$Revision: 9999999 $" into an integer or a string.
I know that simple functions exists to achieve this, but I want this to be made at compile time.
My wish is to write things like:unsigned int rev = SVN_TO_INT("$Revision$");
I agree that you can't work with strings at compile time through macros or templates. So.... don't use strings.
This is an ugly hack, but I think it meets all your requirements. I don't recommend it.
#define $Revision struct REV_STR { unsigned foo
#define $ * 64; };
$Revision: 4521 $
enum { REV = sizeof(REV_STR) / 8 };
#undef $Revision
#undef $
#include <iostream>
int main()
{
std::cout << REV << std::endl;
return 0;
}
// $ g++ -Wall -Wextra revision.cpp && ./a.exe
// revision.cpp:4: warning: width of `REV_STR::foo' exceeds its type
// 4521
I'm relatively sure that this isn't possible with a macro.
It may be possible with template metaprogramming, but I've never gone near it.
It would also be possible with a pre-build script that replaces SVN_TO_INT with your desired text.
I don't understand why you want this, though, since it would be just as easy to hardcode the version number since you know it at compile time.
You can't do the kind of string manipulation you want at compile time with the C preprocessor (macros) or with templates (C++). You'll need to use an external utility or script that you can invoke from the build process.
Some utilities/scripts/code that might help you:
SvnRev: http://www.compuphase.com/svnrev.htm
http://blog.guymahieu.com/2008/06/09/getting-the-svn-head-revision-number-from-a-windows-batch-file/
http://www.codeproject.com/KB/architecture/svn_visual_studio.aspx
My solution is
#define $Revision (false?1
#define $ +0)
int codeRevision() { return $Revision: $; }
#undef $Revision
#undef $
You can't fully work with strings at preprocessing or compile time - but why not use something something like:
int svn_version()
{
static const int v = extract_svn_version(REVISION);
return v;
}
I agree that it is not doable with macros, however, I found a trick using compiler optimizations.
The result is that the expression JL_SvnRevToInt("$Revision: 12345 $") is reduced to a single unsigned integer: 12345
inline unsigned int JL_SvnRevToInt(const char *r) {
if ( r == NULL || r[0] == '\0' || r[10] == '\0' || r[11] == '\0' || r[12] == '\0' || r[13] == '\0' )
return 0;
const unsigned int count =
r[11] == ' ' ? 1
: r[12] == ' ' ? 10
: r[13] == ' ' ? 100
: r[14] == ' ' ? 1000
: r[15] == ' ' ? 10000
: r[16] == ' ' ? 100000
: r[17] == ' ' ? 1000000
: r[18] == ' ' ? 10000000
: r[19] == ' ' ? 100000000
: 0;
return
(r[11] == ' ' ? 0 : (r[11]-'0') * (count/10) +
(r[12] == ' ' ? 0 : (r[12]-'0') * (count/100) +
(r[13] == ' ' ? 0 : (r[13]-'0') * (count/1000) +
(r[14] == ' ' ? 0 : (r[14]-'0') * (count/10000) +
(r[15] == ' ' ? 0 : (r[15]-'0') * (count/100000) +
(r[16] == ' ' ? 0 : (r[16]-'0') * (count/1000000) +
(r[17] == ' ' ? 0 : (r[17]-'0') * (count/10000000) +
(r[18] == ' ' ? 0 : (r[18]-'0') * (count/100000000) +
(r[19] == ' ' ? 0 : (r[19]-'0') * (count/1000000000) +
0)))))))));
}
It supports9 digits revision number, NULL and empty and "$Revision$" strings.
If you have a makefile based build system you can make a special rule that creates a file every maketime.
.PHONY: svn_revision.c
svn_revision.c:
echo -n "int svn_revision = " > svn_revision.c
svn info | grep Revision | cut -f2 -d" " >> svn_revision.c
echo ";" >> svn_revision.c
svn_revision.o: svn_revision.c
Related
Look at the query and result generated in sqlplus :
SELECT
plan_line_id,
LPAD (a.plan_operation || ' ' || a.plan_options,
LENGTH (a.plan_operation || ' ' || a.plan_options) + a.plan_depth * 3
) OPERATION,
a.plan_cost COST,
output_rows "ROWS"
FROM gV$SQL_PLAN_MONITOR a
WHERE sql_id = '8gan9d0z7bzhm'
Looks pretty cool doesn't it ;)
And the same result in grid report :
Apex 21 removes all spaces generated by lpad function. The same problem is with classic report and classic grid :( any idea why ?
You'll have to use a character which can be correctly interpreted by your browser - instead of a space, use a non-breaking space, the   character.
Something like this (I'm using the # character in the CTE, which is then replaced by :
WITH
temp
AS
(SELECT plan_line_id,
LPAD (
a.plan_operation || ' ' || a.plan_options,
LENGTH (a.plan_operation || ' ' || a.plan_options)
+ a.plan_depth * 3,
'#') OPERATION, --> here
a.plan_cost COST,
output_rows "ROWS"
FROM a1_test a
WHERE sql_id = '9p4xcx2gd8u49')
SELECT plan_line_id,
REPLACE (operation, '#', ' ') operation, --> here
cost,
"ROWS"
FROM temp
Turn "Operation" column's **Escape special characters" property OFF.
The result is then
Not as pretty as you'd want it to, but it is better than what you currently have.
I'm new to C++. I know a lot of python but I'm extremely new to C++. I was creating an array of chars but I got this error- "Too many Initializers" in VSCode.
Please let me know how to fix it.
Here's the code
1 | class Board {
2 | public:
3 | char pos_list[9];
4 |
5 | void reset_pos() {
6 | pos_list[9] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
7 | };
8 | };
I am getting this error in line 6.
Please help me :(
EDIT: My initial answer was not correct, please find the modified correct way to do what you are looking for:
You will not be able to use {'','',''} in order to assign empty values to all elements in the array in C++, you can only do that while initializing the array when you declare it. Also, it wouldn't be ideal because it would use hardcoding of ' ' across the entire length of the array. The better way to do this is to loop over the array and then set each element to empty like below:
void reset_pos() {
int len = sizeof(pos_list)/sizeof(pos_list[0]);
for(int i=0; i<len; i++){
pos_list[i] = ' ';
}
};
I'm trying to recreate a program in my textbook, with the syntax shown below. However when I add in the line for detecting tabs [if ((c=' ' || c='\t'] (and the inverted version above , and printing only one tab at once, it shifts the entire text a few more'tabs' to the left. If I delete mentions of tabs, it works perfectly with blanks. Hope this helps.
I tried to do this question before from my book, but ended up focusing on answers from this site (https://clc-wiki.net/wiki/K%26R2_solutions:Chapter_1:Exercise_9) For being concise, I won't post the code that worked best, but it's the one at the very bottom of the page if you want to consult it. Afterwards I changed my sight towards a code (a part of it is listed below), which let be able to answer the Q with tabs also which which wasn't originally in the Q.
int main(void)
{
int c, p;
p = 0;
while ((c = getchar()) != EOF)
{
if (c != ' ' || c!= '\t')
{
putchar(c);
p= 0;
}
if ((c == ' ' || c== '\t') && p<1)
{
putchar(c);
p++;
}
} if (c == '\n')
p = 0;
}
______________________________________________________________________________Another example from the site I listed, which I thought syntax was concise and interesting.
while ((c = getchar()) != EOF)
{ if (c == ' ' || c == '\t')
{ while ((c = getchar()) == ' ' || c == '\t')
No error messages come up, but in an instance like ' [tab][tab]hello world
, I expect' [tab]hello world'. But somehow I get '[tab][tab][tab][tab]hello world. It seems to increase the output by 2x including both tabs and blanks.
The problem is on this line here:
if (c != ' ' || c!= '\t')
Let's look at three cases:
c == ' ' is true. This means that c != '\t' is also true, so the if statement executes.
c == '\t' is true. This means that c != ' ' is also true, so the if statement executes.
c is neither of those. This means that c != ' ' is true, so the if statement executes.
In every possible case, the if statement executes.
Proposed solution: Re-write it as
if (c != ' ' && c != '\t')
using '&&' instead of '||'.
Since your first if statement will always evaluate to true putchar will be called the first time and p will be set to 0. Since p is 0 the 2nd if statement will always be true. This will call putchar a 2nd time. You may want to use isspace(). It will check for white-space characters.
N.B: Directly connected to a problem I had a few years ago, but I'd like to resolve the first issue there which wasn't otherwise part of the question, so please don't flag it as a duplicate of my earlier question.
I have a string centring function that centres the given string according to the given width (which is 113 characters):
std::string center(std::string input, int width = 113) {
return std::string((width - input.length()) / 2, ' ') + input;
}
I am using a game SDK in order to create a gameserver modification, and this game SDK supports coloured strings in the game's command console, which are denoted using a dollar sign and a number from 0-9 (i.e, $1) and are not printed in the console itself.
The string centring function above treats these markers as part of the total string, so I want to add the total amount of characters these markers take up to the width so that the string is actually centred.
I have tried modifying the function:
std::string centre(std::string input, int width = 113) {
std::ostringstream pStream;
for(std::string::size_type i = 0; i < input.size(); ++i) {
if (i+1 > input.length()) break;
pStream << input[i] << input[i+1];
CryLogAlways(pStream.str().c_str());
if (pStream.str() == "$1" || pStream.str() == "$2" || pStream.str() == "$3" || pStream.str() == "$4" || pStream.str() == "$5" || pStream.str() == "$6" || pStream.str() == "$7" || pStream.str() == "$8" || pStream.str() == "$9" || pStream.str() == "$0")
width = width+2;
pStream.clear();
}
return std::string((width - input.length()) / 2, ' ') + input;
}
The goal of the above function is to iterate through the string, add the current character and the next to an ostringstream, and evaluate the ostringstream.
This didn't exactly do as I wanted:
<16:58:57> 8I
<16:58:57> 8IIn
<16:58:57> 8IInnc
<16:58:57> 8IInncco
<16:58:57> 8IInnccoom
<16:58:57> 8IInnccoommi
<16:58:57> 8IInnccoommiin
<16:58:57> 8IInnccoommiinng
<16:58:57> 8IInnccoommiinngg
<16:58:57> 8IInnccoommiinngg C
<16:58:57> 8IInnccoommiinngg CCo
<16:58:57> 8IInnccoommiinngg CCoon
<16:58:57> 8IInnccoommiinngg CCoonnn
<16:58:57> 8IInnccoommiinngg CCoonnnne
(snippet from server log)
Here's a brief summary of the issue:
I think I might be missing how iteration works; what am I missing, and how can I make this function work in the way I want it to?
So, what you are really trying to do is count the instances of $N in your string, where N is a decimal digit. To do this, just look in the string for instances of $ using std::string::find, and then check the next character to see if it is a digit.
std::string::size_type pos = 0;
while ((pos = input.find('$', pos)) != std::string::npos) {
if (pos + 1 == input.size()) {
break; // The last character of the string is a '$'
}
if (std::isdigit(input[pos + 1])) {
width += 2;
}
++pos; // Start next search from the next char
}
In order to use std::isdigit, you need to first:
#include <cctype>
I have a condition to validate a number. My requirement is accept only following numbers.
0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5
I tried with this regex but it returns false for decimal numbers.
/^[0|0.5|1|1.5|2|2.5|3|3.5|4|4.5|5]$/
The system that I am working is an existing system and I must use regular expression. No other option available for me.
Can anyone help me?
Your expression is almost correct:
/^(0|0\.5|1|1\.5|2|2\.5|3|3\.5|4|4\.5|5)$/
You need to use round brackets instead of square brackets and escape the dots. Round brackets indicate groups while square brackets define a group of single characters which may be matched. A shorter variant is this:
/^([0-4](\.5)?|5)$/
This will match any digit from 0 to 4, optionally followed by .5, or the single digit 5.
You may try the below regex.
^(?:[0-4](?:\.5)?|5)$
[0-4] will match range of digits from 0 to 4.
(?:\.5)? optional .5
DEMO
Instead of using regexes, you should really see if you can use a function.
This would be your best option, then:
function check(num) {
var floored = Math.floor(num);
return (num === floored || num - 0.5 === floored) && num >= 0 && num <=5;
}
alert(1 + ' ' + check(1) + '\n' +
5 + ' ' + check(5) + '\n' +
6 + ' ' + check(6) + '\n' +
1.5 + ' ' + check(1.5) + '\n' +
4.5 + ' ' + check(4.5) + '\n' +
5.5 + ' ' + check(5.5) + '\n' +
5.51 + ' ' + check(5.51) + '\n' +
-1.5 + ' ' + check(-1.5) + '\n' +
-0.5 + ' ' + check(-0.5))