I'm doing this question with Pascal (Google Kick Start 2020 Round A - Workout) and I ran into a problem that doesn't make any sense at all. Here is a part of my program:
var N,K,i,max,max1 : longint;
M : array [1..100000] of longint;
A : array [1..99999] of longint;
begin
readln(N,K);
for i := 1 to N do
read(M[i]);
for i := 1 to N-1 do A[i] := M[i+1]-M[i];
max := 0;
for i := 1 to N-1 do
if A[i] >= max then
begin
max := A[i];
max1 := i;
end;
writeln('max = ',max); writeln('max1 = ',max1);
readln; readln;
end.
So first I type in all the input data which are:
5 6 and
9
10
20
26
30.
When I run the program, the value of max is 10 and the value of max1 is 2.
But when I change the way max gets its value and totally did nothing with max1, the program becomes like this:
uses crt;
var N,K,i,max,max1 : longint;
M : array [1..100000] of longint;
A : array [1..99999] of longint;
begin
readln(N,K);
for i := 1 to N do
read(M[i]);
for i := 1 to N-1 do A[i] := M[i+1]-M[i];
max := 0;
for i := 1 to N-1 do
if A[i] >= max then
begin
max := i;
max1 := i;
end;
writeln('max = ',max); writeln('max1 = ',max1);
readln; readln;
end.
I run the program, and suddenly both the values of max and max1 are 4. How can this happen? Should I delete Pascal?? By the way if you can't install Pascal for some reasons then go to this link:https://www.onlinegdb.com/, select Pascal language and paste my program. Thanks for helping me!
I use GMLib to work with Google maps and now I have come to a point where I am very confused.
I have the functions GetDistance and GetHeading to calculate the distance and compass direction between 2 markers on my map.
When I call them from my procedure GetHeadingDistance I get the result I expect (distance and direction is correct)- aSearchCallInfo is a class containing info that needs to be updated with the values.
Now I am trying to add a function that lets the user press the right mouse button on the map and the get info about that location.
But in this case I get very wrong results. As far as I can see of the results it uses GMMarker.Items[1].Position as source even when I know that it is GMMarker.Items[0].Position I send as parameter.
When I try to debug the functions by writing values to a textfile during calculation, I can see that it is the correct values it gets to work with at the correct position.
(GMMarker.Items[0].Position is the position of the user of the software)
Any ideas as what I could try to get this solved?
procedure TfrmQthMap.GMMapRightClick(Sender: TObject; LatLng: TLatLng; X, Y: Double);
var
MessageText: string;
LL: TLatLng;
Heading: double;
Distance: double;
Qra: string;
begin
if GMMarker.Count > 0 then
begin
LL := TLatLng.Create;
try
LL.Lat := LatLng.Lat;
LL.Lng := LatLng.Lng;
Heading := GetHeading(GMMarker.Items[0].Position, LL);
Distance := GetDistance(GMMarker.Items[0].Position, LL);
Qra := Maidenhead(LatLng.LngToStr, LatLng.LatToStr);
finally
FreeAndNil(LL);
end;
MessageText := 'Data for det sted du klikkede på: ' + sLineBreak + sLineBreak +
Format('Længdegrad: %s', [LatLng.LngToStr(Precision)]) + sLineBreak +
Format('Breddegrad: %s', [LatLng.LatToStr(Precision)]) + sLineBreak +
Format('Afstand: %6.1f km', [Distance]) + sLineBreak +
Format('Retning: %6.1f °', [Heading]) + sLineBreak +
Format('Lokator: %s', [Qra]);
ShowMessage(MessageText);
end;
end;
procedure TfrmQthMap.GetHeadingDistance(aSearchCallInfo: TCallInfo);
var
Heading: double;
Distance: double;
begin
if GMMarker.Count > 1 then
begin
Heading := GetHeading(GMMarker.Items[0].Position, GMMarker.Items[1].Position);
Distance := GetDistance(GMMarker.Items[0].Position, GMMarker.Items[1].Position);
barFooter.Panels[PanelDist].Text := Format('Afstand: %6.1f km', [Distance]);
barFooter.Panels[PanelDir].Text := Format('Retning: %6.1f°', [Heading]);
aSearchCallInfo.Distance := Format('%6.1f km', [Distance]);
aSearchCallInfo.Heading := Format('%6.1f °', [Heading]);
aSearchCallInfo.SaveToDatabase;
end;
end;
function TfrmQthMap.GetDistance(aOrigin, aDest: TLatLng): double;
var
Distance: double;
begin
Distance := TGeometry.ComputeDistanceBetween(GMMap, aOrigin, aDest);
Distance := Distance / 1000;
Result := Distance;
end;
function TfrmQthMap.GetHeading(aOrigin, aDest: TLatLng): double;
var
Heading: double;
begin
Heading := TGeometry.ComputeHeading(GMMap, aOrigin, aDest);
Heading := 180 + Heading;
Result := Heading;
end;
I need to convert a Json String to a table data structure in Lua. I am using the following code.
local json = require "json"
local t = {
["name1"] = "value1",
["name2"] = { 1, false, true, 23.54, "a \021 string" },
name3 = json.null
}
local encode = json.encode (t)
print (encode) --> {"name1":"value1","name3":null,"name2":[1,false,true,23.54,"a \u0015 string"]}
local decode = json.decode( encode )
But when I run the script, I get the following errors,
no field package.preload['json']
no file '/usr/local/share/lua/5.2/json.lua'
no file '/usr/local/share/lua/5.2/json/init.lua'
no file '/usr/local/lib/lua/5.2/json.lua'
no file '/usr/local/lib/lua/5.2/json/init.lua'
no file './json.lua'
no file '/usr/local/lib/lua/5.2/json.so'
no file '/usr/local/lib/lua/5.2/loadall.so'
no file './json.so'
So how to convert my json string to lua table?
maybe lua-cjsonis your friend:
install e.g. through luarocks:
$sudo luarocks install lua-cjson
then in lua:
local json = require('cjson')
local tab = json.decode(json_string)
json_string = json.encode(tab)
https://gist.github.com/tylerneylon/59f4bcf316be525b30ab
I found pure lua script file to parse json data (just one file).
local json = {}
-- Internal functions.
local function kind_of(obj)
if type(obj) ~= 'table' then return type(obj) end
local i = 1
for _ in pairs(obj) do
if obj[i] ~= nil then i = i + 1 else return 'table' end
end
if i == 1 then return 'table' else return 'array' end
end
local function escape_str(s)
local in_char = {'\\', '"', '/', '\b', '\f', '\n', '\r', '\t'}
local out_char = {'\\', '"', '/', 'b', 'f', 'n', 'r', 't'}
for i, c in ipairs(in_char) do
s = s:gsub(c, '\\' .. out_char[i])
end
return s
end
-- Returns pos, did_find; there are two cases:
-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.
-- 2. Delimiter not found: pos = pos after leading space; did_find = false.
-- This throws an error if err_if_missing is true and the delim is not found.
local function skip_delim(str, pos, delim, err_if_missing)
pos = pos + #str:match('^%s*', pos)
if str:sub(pos, pos) ~= delim then
if err_if_missing then
error('Expected ' .. delim .. ' near position ' .. pos)
end
return pos, false
end
return pos + 1, true
end
-- Expects the given pos to be the first character after the opening quote.
-- Returns val, pos; the returned pos is after the closing quote character.
local function parse_str_val(str, pos, val)
val = val or ''
local early_end_error = 'End of input found while parsing string.'
if pos > #str then error(early_end_error) end
local c = str:sub(pos, pos)
if c == '"' then return val, pos + 1 end
if c ~= '\\' then return parse_str_val(str, pos + 1, val .. c) end
-- We must have a \ character.
local esc_map = {b = '\b', f = '\f', n = '\n', r = '\r', t = '\t'}
local nextc = str:sub(pos + 1, pos + 1)
if not nextc then error(early_end_error) end
return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))
end
-- Returns val, pos; the returned pos is after the number's final character.
local function parse_num_val(str, pos)
local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)
local val = tonumber(num_str)
if not val then error('Error parsing number at position ' .. pos .. '.') end
return val, pos + #num_str
end
-- Public values and functions.
function json.stringify(obj, as_key)
local s = {} -- We'll build the string as an array of strings to be concatenated.
local kind = kind_of(obj) -- This is 'array' if it's an array or type(obj) otherwise.
if kind == 'array' then
if as_key then error('Can\'t encode array as key.') end
s[#s + 1] = '['
for i, val in ipairs(obj) do
if i > 1 then s[#s + 1] = ', ' end
s[#s + 1] = json.stringify(val)
end
s[#s + 1] = ']'
elseif kind == 'table' then
if as_key then error('Can\'t encode table as key.') end
s[#s + 1] = '{'
for k, v in pairs(obj) do
if #s > 1 then s[#s + 1] = ', ' end
s[#s + 1] = json.stringify(k, true)
s[#s + 1] = ':'
s[#s + 1] = json.stringify(v)
end
s[#s + 1] = '}'
elseif kind == 'string' then
return '"' .. escape_str(obj) .. '"'
elseif kind == 'number' then
if as_key then return '"' .. tostring(obj) .. '"' end
return tostring(obj)
elseif kind == 'boolean' then
return tostring(obj)
elseif kind == 'nil' then
return 'null'
else
error('Unjsonifiable type: ' .. kind .. '.')
end
return table.concat(s)
end
json.null = {} -- This is a one-off table to represent the null value.
function json.parse(str, pos, end_delim)
pos = pos or 1
if pos > #str then error('Reached unexpected end of input.') end
local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.
local first = str:sub(pos, pos)
if first == '{' then -- Parse an object.
local obj, key, delim_found = {}, true, true
pos = pos + 1
while true do
key, pos = json.parse(str, pos, '}')
if key == nil then return obj, pos end
if not delim_found then error('Comma missing between object items.') end
pos = skip_delim(str, pos, ':', true) -- true -> error if missing.
obj[key], pos = json.parse(str, pos)
pos, delim_found = skip_delim(str, pos, ',')
end
elseif first == '[' then -- Parse an array.
local arr, val, delim_found = {}, true, true
pos = pos + 1
while true do
val, pos = json.parse(str, pos, ']')
if val == nil then return arr, pos end
if not delim_found then error('Comma missing between array items.') end
arr[#arr + 1] = val
pos, delim_found = skip_delim(str, pos, ',')
end
elseif first == '"' then -- Parse a string.
return parse_str_val(str, pos + 1)
elseif first == '-' or first:match('%d') then -- Parse a number.
return parse_num_val(str, pos)
elseif first == end_delim then -- End of an object or array.
return nil, pos + 1
else -- Parse true, false, or null.
local literals = {['true'] = true, ['false'] = false, ['null'] = json.null}
for lit_str, lit_val in pairs(literals) do
local lit_end = pos + #lit_str - 1
if str:sub(pos, lit_end) == lit_str then return lit_val, lit_end + 1 end
end
local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)
error('Invalid json syntax starting at ' .. pos_info_str)
end
end
return json
You can use json-lua. A pure lua implementation of json. First install json-lua using Luarocks. luarocks install json-lua . Then Use this code :
local json = require "json"
local t = {
["name1"] = "value1",
["name2"] = { 1, false, true, 23.54, "a \021 string" },
name3 = json.null
}
local encode = json:encode (t)
print (encode) --> {"name1":"value1","name3":null,"name2":[1,false,true,23.54,"a \u0015 string"]}
local decode = json:decode( encode )
Tested & Verified on win 7 64 bit with lua 5.1. lua-cjson is fine, but it is not a pure lua rock. So, it's installation will not be easier to you.
this is my first question. Sorry my english.
I have a classes like this:
TSFis_S = class(TPersistent)
private
_SFis_MID : Integer;
public
property SFis_MID : Integer read _SFis_MID write _SFis_MID;
end;
TSFis_D = class(TPersistent)
private
_SFis_MID : Integer;
_SFis_S : TObjectList<TSFis_S>;
public
property SFis_MID : Integer read _SFis_MID write _SFis_MID;
property SFis_S : TObjectList<TSFis_S> read _SFis_S write _SFis_S;
end;
TSFis_M = class(TPersistent)
private
_SFis_MID : Integer;
_SFis_D : TObjectList<TSFis_D>;
public
property SFis_MID : Integer read _SFis_MID write _SFis_MID;
property SFis_D : TObjectList<TSFis_D> read _SFis_D write _SFis_D;
function ToJSON:TJSONValue;
destructor Destroy;
end;
I trying convert TSFis_M Object to JSon and Revert to Object for my datasnap application. I use converts and reverters for my datatypes (TObjectList and TObjectList)
{ TSFis_M }
function JSonToSFis_M(json: TJSONValue): TSFis_M;
var
UnMarshaller: TJSONUnMarshal;
begin
if json is TJSONNull then
exit(nil);
UnMarshaller := TJSONUnMarshal.Create;
try
UnMarshaller.RegisterReverter(TSFis_M, '_FisTar',
procedure(Data: TObject; Field: string; Arg: string)
var
ctx: TRttiContext;
datetime :
TDateTime;
begin
datetime := EncodeDateTime(StrToInt(Copy(Arg, 7, 4)), StrToInt(Copy(Arg, 4, 2)), StrToInt(Copy(Arg, 1, 2)), StrToInt
(Copy(Arg, 12, 2)), StrToInt(Copy(Arg, 15, 2)), StrToInt(Copy(Arg, 18, 2)), 0);
ctx.GetType(Data.ClassType).GetField(Field).SetValue(Data, datetime);
end
);
UnMarshaller.RegisterReverter(TSFis_D, '_SFis_S',
procedure(Data: TObject; Field: String; Args: TListOfObjects)
var
obj: TObject;
SFisS: TObjectList<TSFis_S>;
SFis, SFisNew: TSFis_S;
begin
if TSFis_D(Data)._SFis_S=Nil
then TSFis_D(Data)._SFis_S := TObjectList<TSFis_S>.Create(True);
SFisS := TSFis_D(Data)._SFis_S;
SFisS.Clear;
for obj in Args do
begin
SFis := obj as TSFis_S;
SFisNew := TSFis_S.Create;
SFisS.Add(SFisNew);
SFisNew._SFis_MID := SFis._SFis_MID;
end;
end
);
UnMarshaller.RegisterReverter(TSFis_M, '_SFis_D',
procedure(Data: TObject; Field: String; Args: TListOfObjects)
var
obj: TObject;
SFisD: TObjectList<TSFis_D>;
SFis, SFisNew: TSFis_D;
i: integer;
begin
if TSFis_M(Data)._SFis_D=Nil then
TSFis_M(Data)._SFis_D := TObjectList<TSFis_D>.Create(True);
SFisD := TSFis_M(Data)._SFis_D;
SFisD.Clear;
for obj in Args do
begin
SFis := obj as TSFis_D;
SFisNew := TSFis_D.Create;
SFisD.Add(SFisNew);
SFisNew._SFis_MID := SFis._SFis_MID;
end;
end
);
exit(Unmarshaller.Unmarshal(json) as TSFis_M)
finally
UnMarshaller.Free;
end;
end;
function TSFis_M.ToJSON: TJSONValue;
var
Marshaller: TJSONMarshal;
begin
if Assigned(Self) then
begin
Marshaller := TJSONMarshal.Create(TJSONConverter.Create);
try
Marshaller.RegisterConverter(TSFis_M, '_SFis_D',
function(Data: TObject; Field: String): TListOfObjects
var
FisD: TObjectList<TSFis_D>;
i: integer;
begin
FisD := TSFis_M(Data)._SFis_D;
SetLength(Result, FisD.Count);
if FisD.Count > 0 then
for I := 0 to FisD.Count - 1 do
Result[I] := FisD[i];
end);
Marshaller.RegisterConverter(TSFis_M, '_FisTar',
function(Data: TObject; Field: string): string
var
ctx: TRttiContext; date : TDateTime;
begin
date := ctx.GetType(Data.ClassType).GetField(Field).GetValue(Data).AsType<TDateTime>;
Result := FormatDateTime('dd.mm.yyyy hh:nn:ss', date);
end);
Marshaller.RegisterConverter(TSFis_D, '_SFis_S',
function(Data: TObject; Field: String): TListOfObjects
var
FisD: TObjectList<TSFis_S>;
i: integer;
begin
FisD := TSFis_D(Data)._SFis_S;
SetLength(Result, FisD.Count);
if FisD.Count > 0 then
for I := 0 to FisD.Count - 1 do
Result[I] := FisD[i];
end);
exit(Marshaller.Marshal(Self))
finally
Marshaller.Free;
end;
end
else
exit(TJSONNull.Create);
end;
And finally
for example i put 1 Button and 2 Memo on the form. And i try My created Object convert to Json, Json.ToString to Memo1. And Convert that JSonValue to Object.
procedure TForm1.Button1Click(Sender: TObject);
var
MainFis : TSFis_M;
MainFis2 : TSFis_M;
DFis : TSFis_D;
SFis : TSFis_S;
begin
MainFis := TSFis_M.Create;
MainFis.SFis_D := TObjectList<TSFis_D>.Create(True);
DFis := TSFis_D.Create;
DFis._SFis_MID := 1;
MainFis.SFis_D.Add(DFis);
SFis := TSFis_S.Create;
SFis._SFis_MID := 1;
DFis.SFis_S := TObjectList<TSFis_S>.Create(True);
DFis.SFis_S.Add(SFis);
Memo1.Text := MainFis.ToJSON.ToString;
Edit1.Text := IntToStr(MainFis.SFis_D[0].SFis_S.Count);
MainFis2 := JSonToSFis_M(MainFis.ToJSON);
Edit2.Text := IntToStr(MainFis2.SFis_D[0].SFis_S.Count); // Access violation. Because MainFis2.SFis_D[0].SFis_S = Nil Now (That's the my problem. Why?)
Memo2.Text := MainFis2.ToJSon.ToString;
end;
But when i do this. TSFis_S is disappearing. In first step (ObjectToJSon) no problem.
{"type":"Unit1.TSFis_M","id":1,"fields":
{"_SFis_MID":0,"_SFis_D":
[ {"type":"Unit1.TSFis_D","id":2,"fields":
{"_SFis_MID":1,"_SFis_S":
[ {"type":"Unit1.TSFis_S","id":3,"fields":{"_SFis_MID":1} } ]
}
} ]
}
}
But when i trying revert to Object reverter goes wrong.
I can't found problem. What's my fault.
Thanks
PS: If i didn't explain, sample code here: http://goo.gl/3QnSw
Platform : Lazarus 1.1, FreePascal 2.7.1, Win 7 32-bit.
I have a string value as follows:
FileName[12345][45678][6789].jpg
By default (assume this is default behaviour 0), my program currently pulls out the last set of numbers from the last pair of square brackets to the farthest right of the filename, i.e. 6789. It does so using this code:
if chkbxOverrideUniqueID.Checked then
IDOverrideValue := StrToInt(edtToggleValue.Text);
// User is happy to find the right most unique ID
if not chkbxOverrideUniqueID.Checked then
LastSquareBracket := RPos(']', strFileName);
PreceedingSquareBracket := RPosEx('[', strFileName, LastSquareBracket) + 1;
strFileID := AnsiMidStr(strFileName, PreceedingSquareBracket, LastSquareBracket - PreceedingSquareBracket)
else // User doesn't want to find the rightmost ID.
// and now I am stuck!
However, I have now added an option for the user to specify a non-default behaviour. e.g if they enter '1', that means "look for the first ID in from the farthest right ID". e.g. [45678], because [6789] is default behaviour 0, remember. If they enter 2, I want it to find [12345].
My question : How do I adapt the above code to achieve this, please?
The following code will return just the numeric value between brackets:
uses
StrUtils;
function GetNumber(const Text: string; Index: Integer): string;
var
I: Integer;
OpenPos: Integer;
ClosePos: Integer;
begin
Result := '';
ClosePos := Length(Text) + 1;
for I := 0 to Index do
begin
ClosePos := RPosEx(']', Text, ClosePos - 1);
if ClosePos = 0 then
Exit;
end;
OpenPos := RPosEx('[', Text, ClosePos - 1);
if OpenPos <> 0 then
Result := Copy(Text, OpenPos + 1, ClosePos - OpenPos - 1);
end;
If you'd like that value including those brackets, replace the last line with this:
Result := Copy(Text, OpenPos, ClosePos - OpenPos + 1);