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'm trying to write tab separated values in a file using the tabwriter package in Go.
records map[string] []string
file, err := os.OpenFile(some_file, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Println(err)
}
w := new(tabwriter.Writer)
w.Init(file, 0, 4, 0, '\t', 0)
for _, v := range records {
fmt.Fprintln(w, v[0],"\t",v[1],"\t",v[2],"\t",v[3])
w.Flush()
}
The problem I'm facing is that the records written to the file have two additional spaces prepended to them. I added the debug flag and this is what I get in the file:
fname1 | mname1 | lname1 | age1
fname2 | mname2 | lname2 | age2
I'm unable to see where I'm going wrong. Any help is appreciated.
As SirDarius suggested encoding/csv is indeed the right choice. All you have to do is to set the Comma to a horizontal tab instead of the default value, which unsurprisingly is comma.
package tabulatorseparatedvalues
import (
"encoding/csv"
"io"
)
func NewWriter(w io.Writer) (writer *csv.Writer) {
writer = csv.NewWriter(w)
writer.Comma = '\t'
return
}
How do I send an attachment in an HTML formatted email?
I managed to send an email using stmp.gmail.com in HTML format, but my email has an attachment. The attachment gets converted to a string, but I need it to be in the original file format.
Code:
with FIdSmtp do
begin
// Configure IdSMTP
end;
FIdMessage.Clear;
FIdMessage.MessageParts.Clear;
FIdMessage.From.Address := 'EmailRemetente';
FIdMessage.From.Name := 'Apelido';
FIdMessage.Subject := 'Assunto';
FIdMessage.Body.Text := 'Mensagem';
FIdMessage.Recipients.EMailAddresses := 'aEmailDestinatario'; //email destino
FIdMessage.BccList.EMailAddresses := StringReplace(Trim(BCCList.Text),#13#10,',',[rfReplaceAll]);
FIdMessage.ccList.EMailAddresses := StringReplace(Trim(CCList.Text),#13#10,',',[rfReplaceAll]);
FIdMessage.ContentType := 'text/html'; // set html format
_Anexo := TStringList.Create;
try
_Anexo.Text := aAnexos;
for i := 0 to _Anexo.Count - 1 do
TIdAttachmentFile.Create(FIdMessage.MessageParts,_Anexo.Strings[i]);
finally
_Anexo.Free
end;
FIdSmtp.Send(FIdMessage);
Can someone help me?
Read my blog on Indy's website, I discussed this subject in some detail:
HTML Messages
New HTML Message Builder class
With that in mind, try this:
FIdMessage.Clear;
FIdMessage.From.Address := 'EmailRemetente';
FIdMessage.From.Name := 'Apelido';
FIdMessage.Subject := 'Assunto';
FIdMessage.Recipients.EMailAddresses := 'aEmailDestinatario';
FIdMessage.BccList.EMailAddresses := StringReplace(Trim(BCCList.Text),sLineBreak,',',[rfReplaceAll]);
FIdMessage.ccList.EMailAddresses := StringReplace(Trim(CCList.Text),sLineBreak,',',[rfReplaceAll]);
FIdMessage.ContentType := 'multipart/mixed';
with TIdText.Create(FIdMessage.MessageParts, nil) do
begin
ContentType := 'text/html';
Body.Text := 'Mensagem';
end;
_Anexo := TStringList.Create;
try
_Anexo.Text := aAnexos;
for i := 0 to _Anexo.Count - 1 do
TIdAttachmentFile.Create(FIdMessage.MessageParts, _Anexo.Strings[i]);
finally
_Anexo.Free
end;
Or this:
FIdMessage.Clear;
with TIdMessageBuilderHtml.Create do
try
Subject := 'Assunto';
Html.Text := 'Mensagem';
_Anexo := TStringList.Create;
try
_Anexo.Text := aAnexos;
for i := 0 to _Anexo.Count - 1 do
Attachments.Add(_Anexo.Strings[i]);
finally
_Anexo.Free
end;
FillMessage(FIdMessage);
finally
Free;
end;
FIdMessage.From.Address := 'EmailRemetente';
FIdMessage.From.Name := 'Apelido';
FIdMessage.Recipients.EMailAddresses := 'aEmailDestinatario';
FIdMessage.BccList.EMailAddresses := StringReplace(Trim(BCCList.Text),sLineBreak,',',[rfReplaceAll]);
FIdMessage.ccList.EMailAddresses := StringReplace(Trim(CCList.Text),sLineBreak,',',[rfReplaceAll]);
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);
I've got a report that's supposed to take a grid control and produce HTML output. One of the columns in the grid can display any of a number of values, or <Any>. When this gets output to HTML, of course, it ends up blank.
I could probably write up some routine to use StringReplace to turn that into <Any> so it would display this particular case correctly, but I figure there's probably one in the RTL somewhere that's already been tested and does it right. Anyone know where I could find it?
I am 99 % sure that such a function does not exist in the RTL (as of Delphi 2009). Of course - however - it is trivial to write such a function.
Update
HTTPUtil.HTMLEscape is what you are looking for:
function HTMLEscape(const Str: string): string;
I don't dare to publish the code here (copyright violation, probably), but the routine is very simple. It encodes "<", ">", "&", and """ to <, >, &, and ". It also replaces characters #92, #160..#255 to decimal codes, e.g. \.
This latter step is unnecessary if the file is UTF-8, and also illogical, because higher special characters, such as ∮ are left as they are, while lower special characters, such as ×, are encoded.
Update 2
In response to the answer by Stijn Sanders, I made a simple performance test.
program Project1;
{$APPTYPE CONSOLE}
uses
Windows, SysUtils;
var
t1, t2, t3, t4: Int64;
i: Integer;
str: string;
const
N = 100000;
function HTMLEncode(const Data: string): string;
var
i: Integer;
begin
result := '';
for i := 1 to length(Data) do
case Data[i] of
'<': result := result + '<';
'>': result := result + '>';
'&': result := result + '&';
'"': result := result + '"';
else
result := result + Data[i];
end;
end;
function HTMLEncode2(Data: string):string;
begin
Result:=
StringReplace(
StringReplace(
StringReplace(
StringReplace(
Data,
'&','&',[rfReplaceAll]),
'<','<',[rfReplaceAll]),
'>','>',[rfReplaceAll]),
'"','"',[rfReplaceAll]);
end;
begin
QueryPerformanceCounter(t1);
for i := 0 to N - 1 do
str := HTMLEncode('Testing. Is 3*4<3+4? Do you like "A & B"');
QueryPerformanceCounter(t2);
QueryPerformanceCounter(t3);
for i := 0 to N - 1 do
str := HTMLEncode2('Testing. Is 3*4<3+4? Do you like "A & B"');
QueryPerformanceCounter(t4);
Writeln(IntToStr(t2-t1));
Writeln(IntToStr(t4-t3));
Readln;
end.
The output is
532031
801969
It seems here is a small contest :) Here is a one more implementation:
function HTMLEncode3(const Data: string): string;
var
iPos, i: Integer;
procedure Encode(const AStr: String);
begin
Move(AStr[1], result[iPos], Length(AStr) * SizeOf(Char));
Inc(iPos, Length(AStr));
end;
begin
SetLength(result, Length(Data) * 6);
iPos := 1;
for i := 1 to length(Data) do
case Data[i] of
'<': Encode('<');
'>': Encode('>');
'&': Encode('&');
'"': Encode('"');
else
result[iPos] := Data[i];
Inc(iPos);
end;
SetLength(result, iPos - 1);
end;
Update 1: Updated initially provided incorrect code.
Update 2: And the times:
HTMLEncode : 2286508597
HTMLEncode2: 3577001647
HTMLEncode3: 361039770
I usually just use this code:
function HTMLEncode(Data:string):string;
begin
Result:=
StringReplace(
StringReplace(
StringReplace(
StringReplace(
StringReplace(
Data,
'&','&',[rfReplaceAll]),
'<','<',[rfReplaceAll]),
'>','>',[rfReplaceAll]),
'"','"',[rfReplaceAll]),
#13#10,'<br />'#13#10,[rfReplaceAll]);
end;
(copyright? it's open source)
Unit HTTPApp has a function called HTMLEncode. It has also other HTML/HTTP related functions.
I dont know in which delphi version it was introduced but, there is the System.NetEncoding unit which has:
TNetEncoding.HTML.Encode
TNetEncoding.HTML.Decode
functions. Read up here. You dont need external libraries anymore for that.
From unit Soap.HTTPUtil or simply HTTPUtil for older delphi versions, you can use
function HTMLEscape(const Str: string): string;
var
i: Integer;
begin
Result := '';
for i := Low(Str) to High(Str) do
begin
case Str[i] of
'<' : Result := Result + '<'; { Do not localize }
'>' : Result := Result + '>'; { Do not localize }
'&' : Result := Result + '&'; { Do not localize }
'"' : Result := Result + '"'; { Do not localize }
{$IFNDEF UNICODE}
#92, Char(160) .. #255 : Result := Result + '&#' + IntToStr(Ord(Str[ i ])) +';'; { Do not localize }
{$ELSE}
// NOTE: Not very efficient
#$0080..#$FFFF : Result := Result + '&#' + IntToStr(Ord(Str[ i ])) +';'; { Do not localize }
{$ENDIF}
else
Result := Result + Str[i];
end;
end;
end;
how about that way of replacing special characters:
function HtmlWeg(sS: String): String;
var
ix,cc: Integer;
sC, sR: String;
begin
result := sS;
ix := pos('\u00',sS);
while ix >0 do
begin
sc := copy(sS,ix+4,2) ;
cc := StrtoIntdef('$' +sC,32);
sR := '' + chr(cc);
sS := Stringreplace(sS, '\u00'+sC,sR,[rfreplaceall]) ;
ix := pos('\u00',sS);
end;
result := sS;
end;
My function combines the for-loop with a minimal reallocation of the string:
function HtmlEncode(const Value: string): string;
var
i: Integer;
begin
Result := Value;
i := 1;
while i <= Length(Result) do
begin
if Result[i] = '<' then
begin
Result[i] := '&';
Insert('lt;', Result, i + 1);
Inc(i, 4);
end
else if Result[i] = '>' then
begin
Result[i] := '&';
Insert('gt;', Result, i + 1);
Inc(i, 4);
end
else if Result[i] = '"' then
begin
Result[i] := '&';
Insert('quot;', Result, i + 1);
Inc(i, 6);
end
else if Result[i] = '&' then
begin
Insert('amp;', Result, i + 1);
Inc(i, 5);
end
else
Inc(i);
end;
end;
in delphi You have the function
THTMLEncoding.HTML.Encode