Leading spaces while trying to print a number in Ada - ada

I wrote a program which accepts an integer as input and prints the integer as output in Ada. When i run the program, it's printing the number but there are several leading white spaces. Does anybody know why it's happening? Here's the code:
with Ada.Text_IO, Ada.Float_Text_IO, Ada.Integer_Text_IO;
use Ada;
procedure Solution is
Int: Integer;
begin
Integer_Text_IO.Get (Int);
Integer_Text_IO.Put (Int);
end Solution;

Leading white spaces are mandated by the standard: "If the resulting sequence of characters to be output has fewer than Width characters, then leading spaces are first output to make up the difference." RM A.10.8(13).
If you want a different behaviour, specify width, like this:
Integer_Text_IO.Put (Int, Width => 1);

The definition for the Put procedure has the width parameter as being on type Field. Its definition is...
subtype Field is Integer range 0 .. implementation-defined;
I'd recommend putting a field width of 0, which I think stands out more than 1.
Alternatively you could just set the default field width...
Ada.Integer_Text_IO.Default_Width = 0;
in the startup section of your program, which will ensure that all output from this package has no leading spaces.

Related

What do these characters inside the parentheses of a paremeter expansion (${(…)}) do?

hi am new to zsh and am trying to create multi-line prompt and came across this line of code:
local pad=${(pl.$pad_len.. .)}
My 1st question is what is the pl inside the parentheses? Is it a command or operator or a flag(s)?
And my 2nd question is what are the dots that follow $pad_len?
Those are Zsh parameter expansion flags.
l.$pad_len. makes the given (in this case, empty) string exactly $pad_len long, either by truncating it from the left or by padding it on the left with spaces.
l.$pad_len.. . does the same as the above, but specifies explicitly to use the space character for padding — which is unnecessary, since the default is to pad with spaces.
The .s here are arbitrary separators used to enclose each argument for the preceding flag. It doesn’t matter which (matching pair of) punctuation characters you use for this, as long they enclose each argument in pairs. So, l:$pad_len:: : and l<$pad_len>< > do the exact same thing.
p makes l support print escape codes in the second argument — which is unnecessary, since we don’t use any here.
So, a shorter way to write this would be
local pad=${(l.$pad_len.)}
If you want to do this operation on a non-empty string, you can either pass the name of a variable
local foo=bar
local pad=${(l.$pad_len.)foo}
or pass a literal string with :-
local pad=${(l.$pad_len.):-bar}

In ruamel how to start a string with '*' with no quotes like any other string

yaml = ruamel.yaml.YAML()
yaml.indent(mapping=4)
test_yaml_file = open("test.yaml")
test_file = yaml.load(test_yaml_file)
# test = LiteralScalarString('*clvm')
test = "*testing"
test_file['test_perf'] = test
with open("test.yaml", 'w') as changed_file:
yaml.dump(test_file, changed_file)
In this the expected output was
test_perf: *testing
but the output has been
test_perf: '*testing'
how to achieve this using ruamel?
Your scalar starts with a *, which is used in YAML to indicate an alias node. To prevent *testing to be interpreted as an alias during loading (even though the corresponding anchor (&testing) is not specified in the document), the scalar must be quoted or represented as a literal or folded block scalar.
So there is no way to prevent the quotes from happening apart from choosing to represent the scalar as literal or folded block scalar (where you don't get the quotes, but do get the | resp. >)
You should not worry about these quotes, because after loading you'll again have the string *testing and not something that all of a sudden has extra (unwanted) quotes).
There are other characters that have special meaning in YAML (&, !, etc.) and when indicated at the beginning of a scalar cause the scalar to be quoted. What the dump routine actually does is dump the string and read it back and if that results in a different value, the dumper knows that quoting is needed. This also works with strings like 2022-01-28, which when read back result in a date, such strings get quoted automatically when dumped as well (same for strings that look like floats, integers, true/false values).

SQLite3 regexp performance

How performant is the SQLite3 REGEXP operator?
For simplicity, assume a simple table with a single column pattern and an index
CREATE TABLE `foobar` (`pattern` TEXT);
CREATE UNIQUE INDEX `foobar_index` ON `foobar`(`pattern`);
and a query like
SELECT * FROM `foobar` WHERE `pattern` REGEXP 'foo.*'
I have been trying to compare and understand the output from EXPLAIN and it seems to be similar to using LIKE except it will be using regexp for matching. However, I am not fully sure how to read the output from EXPLAIN and I'm not getting a grasp of how performant it will be.
I understand it will be slow compared to a indexed WHERE `pattern` = 'foo' query but is it slower/similar to LIKE?
sqlite does not optimize WHERE ... REGEXP ... to use indexes. x REGEXP y is simply a function call; it's equivalent to regexp(x,y). Also note that not all installations of sqlite have a regexp function defined so using it (or the REGEXP operator) is not very portable. LIKE/GLOB on the other hand can take advantage of indexes for prefix queries provided that some additional conditions are met:
The right-hand side of the LIKE or GLOB must be either a string literal or a parameter bound to a string literal that does not begin with a wildcard character.
It must not be possible to make the LIKE or GLOB operator true by having a numeric value (instead of a string or blob) on the left-hand side. This means that either:
the left-hand side of the LIKE or GLOB operator is the name of an indexed column with TEXT affinity, or
the right-hand side pattern argument does not begin with a minus sign ("-") or a digit.
This constraint arises from the fact that numbers do not sort in lexicographical order. For example: 9<10 but '9'>'10'.
The built-in functions used to implement LIKE and GLOB must not have been overloaded using the sqlite3_create_function() API.
For the GLOB operator, the column must be indexed using the built-in BINARY collating sequence.
For the LIKE operator, if case_sensitive_like mode is enabled then the column must indexed using BINARY collating sequence, or if case_sensitive_like mode is disabled then the column must indexed using built-in NOCASE collating sequence.
If the ESCAPE option is used, the ESCAPE character must be ASCII, or a single-byte character in UTF-8.

SQLite X'...' notation with column data

I am trying to write a custom report in Spiceworks, which uses SQLite queries. This report will fetch me hard drive serial numbers that are unfortunately stored in a few different ways depending on what version of Windows and WMI were on the machine.
Three common examples (which are enough to get to the actual question) are as follows:
Actual serial number: 5VG95AZF
Hexadecimal string with leading spaces: 2020202057202d44585730354341543934383433
Hexadecimal string with leading zeroes: 3030303030303030313131343330423137454342
The two hex strings are further complicated in that even after they are converted to ASCII representation, each pair of numbers are actually backwards. Here is an example:
3030303030303030313131343330423137454342 evaluates to 00000000111430B17ECB
However, the actual serial number on that hard drive is 1141031BE7BC, without leading zeroes and with the bytes swapped around. According to other questions and answers I have read on this site, this has to do with the "endianness" of the data.
My temporary query so far looks something like this (shortened to only the pertinent section):
SELECT pd.model as HDModel,
CASE
WHEN pd.serial like "30303030%" THEN
cast(('X''' || pd.serial || '''') as TEXT)
WHEN pd.serial like "202020%" THEN
LTRIM(X'2020202057202d44585730354341543934383433')
ELSE
pd.serial
END as HDSerial
The result of that query is something like this:
HDModel HDSerial
----------------- -------------------------------------------
Normal Serial 5VG95AZF
202020% test case W -DXW05CAT94843
303030% test case X'3030303030303030313131343330423137454342'
This shows that the X'....' notation style does convert into the correct (but backwards) result of W -DXW05CAT94843 when given a fully literal number (the 202020% line). However, I need to find a way to do the same thing to the actual data in the column, pd.serial, and I can't find a way.
My initial thought was that if I could build a string representation of the X'...' notation, then perhaps cast() would evaluate it. But as you can see, that just ends up spitting out X'3030303030303030313131343330423137454342' instead of the expected 00000000111430B17ECB. This means the concatenation is working correctly, but I can't find a way to evaluate it as hex the same was as in the manual test case.
I have been googling all morning to see if there is just some syntax I am missing, but the closest I have come is this concatenation using the || operator.
EDIT: Ultimately I just want to be able to have a simple case statement in my query like this:
SELECT pd.model as HDModel,
CASE
WHEN pd.serial like "30303030%" THEN
LTRIM(X'pd.serial')
WHEN pd.serial like "202020%" THEN
LTRIM(X'pd.serial')
ELSE
pd.serial
END as HDSerial
But because pd.serial gets wrapped in single quotes, it is taken as a literal string instead of taken as the data contained in that column. My hope was/is that there is just a character or operator I need to specify, like X'$pd.serial' or something.
END EDIT
If I can get past this first hurdle, my next task will be to try and remove the leading zeroes (the way LTRIM eats the leading spaces) and reverse the bytes, but to be honest, I would be content even if that part isn't possible because it wouldn't be hard to post-process this report in Excel to do that.
If anyone can point me in the right direction I would greatly appreciate it! It would obviously be much easier if I was using PHP or something else to do this processing, but because I am trying to have it be an embedded report in Spiceworks, I have to do this all in a single SQLite query.
X'...' is the binary representation in sqlite. If the values are string, you can just use them as such.
This should be a start:
sqlite> select X'3030303030303030313131343330423137454342';
00000000111430B17ECB
sqlite> select ltrim(X'3030303030303030313131343330423137454342','0');
111430B17ECB
I hope this puts you on the right path.

Simple Vim Programming (vimrc file)

I'm trying to learn how to configure my .vimrc file with my own functions.
I'd like to write a function that traverses every line in a file and counts the total number of characters, but ignores all whitespace. This is for a programming exercise and as a stepping stone to more complex programs (I know there are other ways to get this example value using Vim or external programs).
Here's what I have so far:
function countchars()
let line = 0
let count = 0
while line < line("$")
" update count here, don't count whitespace
let line = getline(".")
return count
endfun
What functional code could I replace that commented line with?
If I understand the question correctly, you're looking to count the number of non-whitespace characters in a line. A fairly simple way to do this is to remove the whitespace and look at the length of the resulting line. Therefore, something like this:
function! Countchars()
let l = 1
let char_count = 0
while l <= line("$")
let char_count += len(substitute(getline(l), '\s', '', 'g'))
let l += 1
endwhile
return char_count
endfunction
The key part of the answer to the question is the use of substitute. The command is:
substitute(expr,pattern,repl,flags)
expr in this case is getline(l) where l is the number of the line being iterated over. getline() returns the content of the line, so this is what is being parsed. The pattern is the regular expression \s which matches any single whitespace character. It is replaced with '', i.e. an empty string. The flag g makes it repeat the substitute as many times as whitespace is found on the line.
Once the substitution is complete, len() gives the number of non-whitespace characters and this is added to the current value of char_count with +=.
A few things that I've changed from your sample:
The function name starts with a capital letter (this is a requirement for user defined functions: see :help user-functions)
I've renamed count to char_count as you can't have a variable with the same name as a function and count() is a built-in function
Likewise for line: I renamed this to l
The first line in a file is line 1, not line 0, so I initialised l to 1
The while loop counted up to but not including the last line, I assume you wanted all the lines in the file (this is probably related to the line numbering starting at 1): I changed your code to use <= instead of <
Blocks aren't based on indentation in vim, so the while needs an endwhile
In your function, you have let line = getline('.')
I added a ! on the function definition as it makes incremental development much easier (everytime you re-source the file, it will override the function with the new version rather than spitting out an error message about it already existing).
Incrementing through the file works slightly differently...
In your function, you had let line = getline('.'). Ignoring the variable name, there are still some problems with this implementation. I think what you meant was let l = line('.'), which gives the line number of the current line. getline('.') gives the contents of the current line, so the comparison on the while line would be comparing the content of the current line with the number of the last line and this would fail. The other problem is that you're not actually moving through the file, so the current line would be whichever line you were on when you called the function and would never change, resulting in an infinite loop. I've replaced this with a simple += 1 to step through the file.
There are ways in which the current line would be a useful way to do this, for example if you were writing a function with that took a range of lines, but I think I've written enough for now and the above will hopefully get you going for now. There are plenty of people on stackoverflow to help with any issues anyway!
Have a look at:
:help usr_41.txt
:help function-list
:help user-functions
:help substitute()
along with the :help followed by the various things I used in the function (getline(), line(), let+= etc).
Hope that was helpful.
This approach uses lists:
function! Countchars()
let n = 0
for line in getline(1,line('$'))
let n += len(split(line,'\zs\s*'))
endfor
return n
endfunction
I suppose you have already found the solution.
Just for info:
I use this to count characters without spaces in Vim:
%s/\S/&/gn

Resources