I'm very much a newbie to Ada and I'm trying to teach myself, with the assistance of one of John Barnes' books.
While dabbling with strings, I wrote a very basic program to read user input from the keyboard and then output it again to the console. However, when the output is produced, it appears to contain additional characters that have not been explicitly typed. Looking at it, my gut reaction is that it's unicode/Konsole-related but I definitely cannot discount whether or not it's something that I have done wrong in my code.
I have attached a screenshot of the program and its output. Any ideas would be greatly appreciated.
Thanks!
Image showing code and output
The difference is that strings are NOT null terminated; they are exactly as long as they say they are : in this case, 100 characters.
And not all the characters in your example are what you typed.
Quick fix : only output the Len characters you typed...
Put_Line ("Your String: '" & UserString(1 .. Len) & "' (Chars: " & natural'image(Len) & ")");
(I have used the standard portable natural'image(Len) rather than the compiler-specific Len'img form)
This leaves some remaining problems :
if you type more than 100 characters, the result will be safe but unsatisfactory.
you need to specify the slice boundaries (1..Len) everywhere you need the string.
Better fix : create a string of exactly the length you typed. Easiest way is calling the function form of Get_Line, and initialising an unconstrained String from the function's return value. The unconstrained String has no defined length when it is declared, it gets its length from the initialisation. For this to work, we can start a new block...
Put_Line("Enter a string: ");
declare
UserString : constant String := Get_Line;
-- the string is now the correct length, however much you typed.
begin
Put_Line ("Your String: '" & UserString & "' (Chars: " &
natural'image(UserString'Length) & ")");
-- other processing on UserString here
end;
-- UserString is now out of scope, automatically freed
Notice that there is no more need for the Len variable. The string's length is an attribute of the string, not a separate quantity that may be incorrectly managed; one less thing to go wrong.
And the declare block is a safe and powerful technique for allocating runtime sized storage without needing heap allocation routines, pointers, deallocation etc. Several less things to go wrong.
It is usually a good idea (thanks Simon!) to make UserString a Constant. Not essential (otherwise you can edit it in place, but not change its length) but assuming you don't intend to edit it - one less thing to go wrong.
There are other techniques involving Bounded_String or Unbounded_String but they aren't really necessary here.
Related
Delphi Seattle (S10). Win32 project.
Yesterday I got wrong result in my old routine.
I found this line:
sPre := Copy(aSQLText, p - 1, 1);
aSQLText was 'CREATE', and p = 1.
The sPre got "C" result.
Hmmm... Then I wrote to watch window:
Copy('ABC', 0, 1)
and the result was "A"...
Ouch... What???
The copy handles the overflow in the end well.
But not at the beginning? Or what?
I hope that I haven't got any codes which points to before the string.
Do you also got this result in your Delphi?
Why?
As I know the strings internally stored as 4 byte length + string; and they
based in 1 (not 0 as any arrays). Is this a bug?
The call to copy in your code is resolved to the internal function _UStrCopy from System.pas. Right in the beginning of its implementation it checks the Index and Count parameters and corrects them when necessary. This includes forcing the Index to point to the first character if it is too low.
I agree that this should be documented, though.
The documentation for Copy doesn't specify what will happen in this instance, so I wouldn't call it a Bug per se.
I can see arguments for both solutions (empty string or as it does, assume 1 as starting position).
Point is, as it is not defined in the documentation what happens in this instance, it is unwise for a program to assume anything one way or another, as it may be implementation dependent and might even change over the course of different versions. If your code can risk having p=1 (or even p=0) and you want the empty string in that case, you should explicitly write code to that effect instead of relying on your (wrong, in this case) expectation on what the compiler might do:
if p<=1 then sPre:='' else sPre := Copy(aSQLText, p - 1, 1);
In TI-BASIC, the + operation is overloaded for string concatenation (in this, if nothing else, TI-BASIC joins the rest of the world).
However, any attempt to concatenate involving an empty string raises a Dimension Mismatch error:
"Fizz"+"Buzz"
FizzBuzz
"Fizz"+""
Error
""+"Buzz"
Error
""+""
Error
Why does this occur, and is there an elegant workaround? I've been using a starting space and truncating the string when necessary (doesn't always work well) or using a loop to add characters one at a time (slow).
The best way depends on what you are doing.
If you have a string (in this case, Str1) that you need to concatenate with another (Str2), and you don't know if it is empty, then this is a good general-case solution:
Str2
If length(Str1
Str1+Str2
If you need to loop and add a stuff to the string each time, then this is your best solution:
Before the loop:
" →Str1
In the loop:
Str1+<stuff_that_isn't_an_empty_string>→Str1
After the loop:
sub(Str1,2,length(Str1)-1→Str1
There are other situations, too, and if you have a specific situation, then you should post a simplified version of the relevant code.
Hope this helps!
It is very unfortunate that TI-Basic doesn't support empty strings. If you are starting with an empty string and adding chars, you have to do something like this:
"?
For(I,1,3
Prompt Str1
Ans+Str1
End
sub(Ans,2,length(Ans)-1
Another useful trick is that if you have a string that you are eventually going to evaluate using expr(, you can do "("+Str1+")"→Str1 and then freely do search and replace on the string. This is a necessary workaround since you can't search and replace any text involving the first or last character in a string.
I have got following code:
Put_Line(Source_String (Source_String'First + Start-1..Source_String'First + Stop-2));
It works correctly, but I want to use it as a bounded string.
String1: String(1..50);
If I use
String1:= Source_String (Source_String'First + Start-1..Source_String'First + Stop-2)
But this block of code doesn't work. I can't use substring as a String. Compile doesn't output any errors, but also doesn't work
P.S. When I use Put_Line only, my program works correctly
There seems to be a misconception here : String1: String(1..50); doesn't declare a bounded string but a fixed string. Realising that, it's easy to see why the assignment usually "doesn't work" ... the slice of Source_String must be exactly 50 characters long or the assignment will give a constraint error.
One solution is to use a Bounded String, but that may not be necessary here, so I'm going to suggest a simpler approach.
Think about the program, and structure it so that the runtime values of Source_String, Start and Stop are all known before the declaration of String1. One tool you can use is the "declare block" - this allows declarations to be kept local to their point of use, which is good programming practice... Later on, when you're refactoring, these make great candidates for abstracting out into procedures.
Now you can move the assignment into the declaration, as an initialiser, and the string takes its length from the initialisation. The fact that its length is unknown until runtime doesn't matter, you can find the length from its attributes.
You can move quite a lot into the declarations, and if you don't intend to modify the contents another good practice is to make the declarations constant. So the code might look like:
Start := ...
declare
Source_String : constant String := Read_Line(File);
Stop : constant Natural := Second_Space(Source_String);
String1 : constant String := Source_String (Source_String'First + Start-1
.. Source_String'First + Stop-2);
begin
-- process String1
end; -- String1 goes out of scope here.
I have the following code:
var wqry:TAdoQuery;
...
FillChar(wSpaces,cSpacesAfter,' ');
try
wqry := TADOQuery.Create(nil);//here the error
wqry.Connection:=...
cSpacesAfter is a constant and has the value 1035. wSpaces is a local string variable. The problem is that I receive the following error when TAdoQuery is created
even it is in french, I believe you got the idea.....
If I comment the FillChar code, everything works ok. I have the usual compiler directives, nothing special. I'm using Delphi 7.
Can someone tell me what is wrong with that code?
The troublesome code is most likely this one
FillChar(wSpaces,cSpacesAfter,' ');
I'm assuming that wSpaces is of string type. A string variable is in fact nothing more than a pointer to the data structure that holds the string. You don't need to use pointer syntax because the compiler takes care of that for you.
So what this code does is overwrite the variable holding that pointer with 4 space characters and then write 1031 more spaces over the top of whatever follows the variable. In short you will completely corrupt your memory. That would explain why the FillChar works but the very next line of code dies a painful and dramatic death.
If your string indeed had space for 1035 characters your could instead write:
FillChar(wSpaces[1], cSpacesAfter, ' ');
However, if may be more idiomatic to write:
wSpaces := StringOfChar(' ', cSpacesAfter);
FillChar procedure fills out a section of storage Buffer with the same byte or character FillValue FillCount times.
It is principally used to initialise arrays of numbers. It can be used to initialise records and strings, but care should be used to avoid overwriting length fields. StringOfChar is best for filling out strings to the same character.
Are you sure wSpaces has the size enough to fit all of cSpacesAfter you write to it?
I have seen a lot of C/C++ based solutions to this problem where we have to write a program that upon execution prints its own source.
some solutions --
http://www.cprogramming.com/challenges/solutions/self_print.html
Quine Page solution in many languages
There are many more solutions on the net, each different from the other. I wonder how do we approach to such a problem, what goes inside the mind of the one who solves it. Lend me some insights into this problem... While solutions in interpreted languages like perl, php, ruby, etc might be easy... i would like to know how does one go about designing it in compiled languages...
Aside from cheating¹ there is no difference between compiled and interpreted languages.
The generic approach to quines is quite easy. First, whatever the program looks like, at some point it has to print something:
print ...
However, what should it print? Itself. So it needs to print the "print" command:
print "print ..."
What should it print next? Well, in the mean time the program grew, so it needs to print the string starting with "print", too:
print "print \"print ...\""
Now the program grew again, so there's again more to print:
print "print \"print \\\"...\\\"\""
And so on.
With every added code there's more code to print.
This approach is getting nowhere,
but it reveals an interesting pattern:
The string "print \"" is repeated over and over again.
It would be nice to put the repeating part
into a variable:
a = "print \""
print a
However, the program just changed,
so we need to adjust a:
a = "a = ...\nprint a"
print a
When we now try to fill in the "...",
we run into the same problems as before.
Ultimately, we want to write something like this:
a = "a = " + (quoted contents of a) + "\nprint a"
print a
But that is not possible,
because even if we had such a function quoted() for quoting,
there's still the problem that we define a in terms of itself:
a = "a = " + quoted(a) + "\nprint a"
print a
So the only thing we can do is putting a place holder into a:
a = "a = #\nprint a"
print a
And that's the whole trick!
Anything else is now clear.
Simply replace the place holder
with the quoted contents of a:
a = "a = #\nprint a"
print a.replace("#", quoted(a))
Since we have changed the code,
we need to adjust the string:
a = "a = #\nprint a.replace(\"#\", quoted(a))"
print a.replace("#", quoted(a))
And that's it!
All quines in all languages work that way
(except the cheating ones).
Well, you should ensure that you replace only
the first occurence of the place holder.
And if you use a second place holder,
you can avoid needing to quote the string.
But those are minor issues
and easy to solve.
If fact, the realization of quoted() and replace()
are the only details in which the various quines really differ.
¹ by making the program read its source file
There are a couple of different strategies to writing quines. The obvious one is to just write code that opens the code and prints it out. But the more interesting ones involve language features that allow for self-embedding, like the %s-style printf feature in many languages. You have to figure out how to embed something so that it ends up resolving to the request to be embedded. I suspect, like palindromes, a lot of trial and error is involved.
The usual approach (when you can't cheat*) is to write something that encodes its source in a string constant, then prints out that constant twice: Once as a string literal, and once as code. That gets around the "every time I write a line of code, I have to write another to print it out!" problem.
'Cheating' includes:
- Using an interpreted language and simply loading the source and printing it
- 0-byte long files, which are valid in some languages, such as C.
For fun, I came up with one in Scheme, which I was pretty proud of for about 5 minutes until I discovered has been discovered before. Anyways, there's a slight modification to the "rules" of the game to better count for the duality of data and code in Lisp: instead of printing out the source of the program, it's an S-expression that returns itself:
((lambda (x) (list x `',x)) '(lambda (x) (list x `',x)))
The one on Wikipedia has the same concept, but with a slightly different (more verbose) mechanism for quoting. I like mine better though.
One idea to think about encoding and how to give something a double meaning so that it can be used to output something in a couple of forms. There is also the cavaet that this type of problem comes with restrictions to make it harder as without any rules other than the program output itself, the empty program is a solution.
How about actually reading and printing your source code? Its not difficult at all!! Heres one in php:
<?php
{
header("Content-Type: text/plain");
$f=fopen("5.php","r");
while(!feof($f))
{
echo fgetc($f);
}
fclose($f);
}
?>
In python, you can write:
s='c=chr(39);print"s="+c+s+c+";"+s';c=chr(39);print"s="+c+s+c+";"+s
inspired from this self printing pseudo-code:
Print the following line twice, the second time with quotes.
"Print the following line twice, the second time with quotes."
I've done a AS3 example for those interested in this
var program = "var program = #; function main(){trace(program.replace('#',
String.fromCharCode(34) + program + String.fromCharCode(34)))} main()";
function main(){
trace(program.replace('#', String.fromCharCode(34) + program + String.fromCharCode(34)))
}
main()
In bash it is really easy
touch test; chmod oug+x test; ./test
Empty file, Empty output
In ruby:
puts File.read(_ _ FILE _ _)