"Invalid operand types for operand = "ada - comparison

I am trying to check if two strings are the same and I keep getting an error saying the operands are incorrect. Both sides of the "=" are of the type StateAbbreviation, where is the error?
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;
procedure ElectionPrediction is
MaxCandidates: constant Integer := 100;
subtype StateAbbreviation is String (1..2);
subtype Initials is String (1..2);
type CandidateInfo is record
CandidateInitials: Initials;
CandidateScore: Integer;
end record;
type ScoreArray is array (1..MaxCandidates) of CandidateInfo;
Score: ScoreArray;
CurrentState, HomeState: StateAbbreviation;
CandidateName: Initials;
function CalculatePointsFromState(CurrentState: StateAbbreviation; CandidateState: StateAbbreviation) return Integer is
Total: Integer := 0;
temp: Integer := 0;
type ScoreArray is array (1..MaxCandidates) of CandidateInfo;
type NewEngland is array (1..6) of StateAbbreviation;
type NorthEast is array (1..5) of StateAbbreviation;
type SouthEast is array (1..12) of StateAbbreviation;
type Lakes is array (1..6) of StateAbbreviation;
type Central is array (1..8) of StateAbbreviation;
type West is array (1..8) of StateAbbreviation;
type Pacific is array (1..5) of StateAbbreviation;
begin
NewEngland := ("ME", "NH", "VT", "MA", "CT", "RI");
NorthEast := ("NY", "PA", "NJ", "DE", "MD");
SouthEast := ("VA", "NC", "SC", "GA", "FL", "AL", "MS", "TN", "KY", "WV", "AR", "LA");
Lakes := ("OH", "MI", "IN", "IL", "WI", "MN");
Central := ("IA", "MO", "ND", "SD", "NE", "KS", "OK", "TX");
West := ("MT", "WY", "CO", "NM", "AZ", "UT", "ID", "NV");
Pacific :=("WA", "OR", "CA", "AK", "HI");
if CandidateState = CurrentState then Total := Total + 50;
end if;
for I in NewEngland'range loop
**if CurrentState = NewEngland(NewEngland'First + I) then temp := temp + 1; end if;
if CandidateState = NewEngland(NewEngland'First + I) then temp := temp + 1; end if;**
end loop;
if temp = 2 then return Total + 20;
end if;
return 0;
end CalculatePointsFromState;
end ElectionPrediction;

Earlier errors in your code give messages like
39. NorthEast := ("NY", "PA", "NJ", "DE", "MD");
|
>>> invalid use of subtype mark in expression or call
because you have defined
29. type NorthEast is array (1..5) of StateAbbreviation;
NorthEast is a (sub)type, not a variable! and this serious error has confused the compiler to the point where the later error messages don’t make as much sense as they could.
What you might consider is creating a type for an array of StateAbbreviations of any length
type StatesArray is array (Positive range <>) of StateAbbreviation;
and then creating the regional data as specific (constant: you wouldn’t want your program to overwrite them by mistake) arrays of this type
NewEngland : constant StatesArray := ("ME", "NH", "VT", "MA", "CT", "RI”);
NorthEast : constant StatesArray := ("NY", "PA", "NJ", "DE", "MD");
...
after which the rest of the code will compile OK.

Related

Global or Local variable different builder behavior

I'm still doing practical with llvm-c Api,
I have a doubt about this code:
I got the original code from source.
In Delphi is:
procedure test;
(*int A[1024];
int main(){
int B[1024];
A[50] = A[49] + 5;
B[0] = B[1] + 10;
return 0;
}
*)
var
context : TLLVMContextRef ;
module : TLLVMModuleRef;
builder : TLLVMBuilderRef;
typeA,
typeB,
mainFnReturnType : TLLVMTypeRef;
arrayA,
arrayB,
mainFn,
Zero64,
temp,
temp2,
returnVal,
ptr_A_49,
ptr_B_1,
elem_A_49 ,
elem_B_1,
ptr_A_50,
ptr_B_0 : TLLVMValueRef;
entryBlock,
endBasicBlock : TLLVMBasicBlockRef;
indices : array[0..1] of TLLVMValueRef;
begin
context := LLVMGetGlobalContext;
module := LLVMModuleCreateWithNameInContext('meu_modulo.bc', context);
builder := LLVMCreateBuilderInContext(context);
//
// Declara o tipo do retorno da função main.
mainFnReturnType := LLVMInt64TypeInContext(context);
// Cria a função main.
mainFn := LLVMAddFunction(module, 'main', LLVMFunctionType(mainFnReturnType, nil, 0, False));
// Declara o bloco de entrada.
entryBlock := LLVMAppendBasicBlockInContext(context, mainFn, 'entry');
// Declara o bloco de saída.
endBasicBlock := LLVMAppendBasicBlock(mainFn, 'end');
// Adiciona o bloco de entrada.
LLVMPositionBuilderAtEnd(builder, entryBlock);
// Cria um valor zero para colocar no retorno.
Zero64 := LLVMConstInt(LLVMInt64Type(), 0, false);
// Cria o valor de retorno e inicializa com zero.
returnVal := LLVMBuildAlloca(builder, LLVMInt64Type, 'retorno');
LLVMBuildStore(builder, Zero64, returnVal);
//
// Array global de 1024 elementos.
typeA := LLVMArrayType(LLVMInt64Type, 1024);
arrayA := LLVMBuildArrayAlloca(builder, typeA, LLVMConstInt(LLVMInt64Type, 0, false), 'A'); //LLVMAddGlobal (module, typeA, 'A');
LLVMSetAlignment(arrayA, 16);
// Array local de 1024 elementos.
typeB := LLVMArrayType(LLVMInt64Type(), 1024);
arrayB := LLVMBuildArrayAlloca(builder, typeB, LLVMConstInt(LLVMInt64Type, 0, false), 'B');
LLVMSetAlignment(arrayB, 16);
// A[50] = A[49] + 5;
// Na documentação diz para usar dois indices, o primeiro em zero: http://releases.llvm.org/2.3/docs/GetElementPtr.html#extra_index
// The first index, i64 0 is required to step over the global variable %MyStruct. Since the first argument to the GEP instruction must always be a value of pointer type, the first index steps through that pointer. A value of 0 means 0 elements offset from that pointer.
indices[0] := LLVMConstInt(LLVMInt32Type, 0, false);
indices[1] := LLVMConstInt(LLVMInt32Type, 49, false);
ptr_A_49 := LLVMBuildInBoundsGEP(builder, arrayA, #indices[0], 2, 'ptr_A_49"');
TFile.WriteAllText('Func.II',LLVMDumpValueToStr(mainFn));
elem_A_49 := LLVMBuildLoad(builder, ptr_A_49, 'elem_of_A');
temp := LLVMBuildAdd(builder, elem_A_49, LLVMConstInt(LLVMInt64Type(), 5, false), 'temp');
indices[0] := LLVMConstInt(LLVMInt32Type(), 0, false);
indices[1] := LLVMConstInt(LLVMInt32Type(), 50, false);
ptr_A_50 := LLVMBuildInBoundsGEP(builder, arrayA, #indices[0], 2, 'ptr_A_50');
LLVMBuildStore(builder, temp, ptr_A_50);
//
// B[0] = B[1] + 10;
indices[0] := LLVMConstInt(LLVMInt32Type, 0, false);
indices[1] := LLVMConstInt(LLVMInt32Type, 1, false);
ptr_B_1 := LLVMBuildInBoundsGEP(builder, arrayB, #indices[0], 2, 'ptr_B_1');
elem_B_1:= LLVMBuildLoad(builder, ptr_B_1, 'elem_of_B');
temp2 := LLVMBuildAdd(builder, elem_B_1, LLVMConstInt(LLVMInt64Type(), 10, false), 'temp2');
indices[0] := LLVMConstInt(LLVMInt32Type, 0, false);
indices[1] := LLVMConstInt(LLVMInt32Type, 0, false);
ptr_B_0 := LLVMBuildInBoundsGEP(builder, arrayB, #indices[0], 2, 'ptr_B_0');
LLVMBuildStore(builder, temp2, ptr_B_0);
//
// Cria um salto para o bloco de saída.
LLVMBuildBr(builder, endBasicBlock);
// Adiciona o bloco de saída.
LLVMPositionBuilderAtEnd(builder, endBasicBlock);
// Cria o return.
LLVMBuildRet(builder, LLVMBuildLoad(builder, returnVal, ''));
// Imprime o código do módulo.
//LLVMDumpModule(module);
TFile.WriteAllText('Func.II',LLVMDumpValueToStr(mainFn));
// Escreve para um arquivo no formato bitcode.
if (LLVMWriteBitcodeToFile(module, 'meu_modulo.bc').ResultCode <> 0) then
raise Exception.Create('error writing bitcode to file, skipping');
end;
the problem is here, if arrayA is a global variable:
// Array global de 1024 elementos.
typeA: = LLVMArrayType (LLVMInt64Type, 1024);
arrayA: = LLVMAddGlobal (module, typeA, 'A');
LLVMSetAlignment (arrayA, 16);
....
....
ptr_A_49: = LLVMBuildInBoundsGEP (builder, arrayA, #indices [0], 2, 'ptr_A_49 "');
TFile.WriteAllText ( 'Func.II', LLVMDumpValueToStr (mainFn));
the gep instruction is not transferred to the code, in fact the output is
define i64 #main () {
entry:
% retorno = allocates i64
i64 0 store, i64 *% return
% B = allocates [1024 x i64], i64 0, align 16
end:; No predecessors!
}
if ArrayA is a local variable:
// Array global de 1024 elementos.
typeA: = LLVMArrayType (LLVMInt64Type, 1024);
arrayA: = LLVMBuildArrayAlloca (builder, typeA, LLVMConstInt (LLVMInt64Type, 0, false), 'A'); // LLVMAddGlobal (module, typeA, 'A');
LLVMSetAlignment (arrayA, 16);
.....
....
ptr_A_49: = LLVMBuildInBoundsGEP (builder, arrayA, #indices [0], 2, 'ptr_A_49 "');
TFile.WriteAllText ( 'Func.II', LLVMDumpValueToStr (mainFn));
the gep instruction is transferred to the code, in fact the output is:
define i64 #main () {
entry:
% retorno = allocates i64
i64 0 store, i64 *% return
% A = allocates [1024 x i64], i64 0, align 16
% B = allocates [1024 x i64], i64 0, align 16
% "ptr_A_49 22" = getelementptr inbounds [1024 x i64], [1024 x i64] *% A, i32 0, i32 49
end:; No predecessors!
}
why?
Reply from llvm-dev mainling list
With 'A' being a global variable, the GEP becomes a ConstantExpr
(GetElementPtrConstantExpr instead of GetElementPtrInst) since all of
its arguments are constant. ConstantExpr are "free-floating", i.e. not
int a BasicBlock's instruction list and therefore only appear in the
printout when used.
Michael
Other user
LLVM has roughly[1] two kinds of Value: Constants and Instructions.
Constants are things like literal constants, (addresses of) global
variables, and various expressions based just on those things; they're
designed to be values that can be directly calculated by the compiler
and/or linker without any CPU instructions actually being executed[2].
Instructions on the other hand sit inside Functions as real entities,
they produce %whatever Values and, unless optimized away, will be
turned into real CPU instructions in the end.
So, you were asking for "GEP something, 0, 49". If that "something" is
a Constant (e.g. a GlobalVariable) then that GEP only depends on
Constants so it can be a ConstantExpr too, written
"getelementptr([1024 x i64], [1024 x i64]* #var, i32 0, i32 49)". That
Constant is then not inserted into a block (it's not an instruction so
it can't be). Instead it's written directly in any instruction that
uses it, so if you actually use the GEP you might see something like:
%val = load i64, i64* getelementptr([1024 x i64], [1024 x i64]*
#var, i32 0, i32 49)
Until you use it, it's not actually in the function anywhere though.
You just have a handle when needed.
On the other hand if the "something" is a local variable, then the GEP
needs to be an actual instruction inside a function and the API you're
using will insert it automatically.
In the Constant case, you can manually create an instruction anyway,
at least in C++. I'm afraid I haven't used the C API and couldn't see
an obvious way there, but you probably don't want to since
optimization would quickly undo it and turn it back into a Constant.
Cheers.
Tim.
[1] There's also Arguments, representing function parameters. They
behave like Instructions for these purposes.
[2] But you can build pathological Constants that no linker really
could calculate like 4 * #global. That tends to result in a compiler
error.

Exporting to text in xojo

I want to export data from a listbox,
Listbox1.AddRow "001", "Orange", "1.00","Arief"
Listbox1.AddRow "001", "Apple", "1.00","Arief"
Listbox1.AddRow "001", "Banana", "1.00","Arief"
Listbox1.AddRow "004", "Orange", "1.00","Arief"
Listbox1.AddRow "005", "Apple", "1.00","Brandon"
Listbox1.AddRow "006", "Banana", "1.00","Brenda"
dim f as folderitem
dim tisx as TextOutputStream
f = new folderitem("item.txt")
tisx = f.CreateTextFile
dim Last_first_word as String
dim maxRow as Integer = Listbox1.listcount-1
for row as integer = 0 to maxRow
if Listbox1.Cell(row,0)<> Last_first_word then
tisx.WriteLine ""
tisx.writeline listBox1.cell(row,0)
tisx.WriteLine listBox1.cell(row,1)+" "+listBox1.cell(row,2)
Last_first_word=Listbox1.Cell(row,0)
else
tisx.WriteLine listBox1.cell(row,1)+" "+listBox1.cell(row,2)
end if
next
tisx.Close
I want to categorized all the items which is has the same code,and put the name at the last.
How to make the result like ,
001
Orange 1.00
Apple 1.00
Banana 1.00
Arief
004
Orange 1.00
Arief
005
Apple 1.00
Brandon
006
Banana 1.00
Brenda
Thanks
Regards,
Arief
You'll need to also save the name so you can display it before you move onto a new group of data. Only a minor tweak to your code was needed:
Listbox1.DeleteAllRows
ListBox1.AddRow("001", "Orange", "1.00", "Arief")
ListBox1.AddRow("001", "Apple", "1.00", "Arief")
ListBox1.AddRow("001", "Banana", "1.00", "Arief")
ListBox1.AddRow("004", "Orange", "1.00", "Arief")
ListBox1.AddRow("005", "Apple", "1.00", "Brandon")
ListBox1.AddRow("006", "Banana", "1.00", "Brenda")
Dim f As FolderItem
Dim tisx As TextOutputStream
f = SpecialFolder.Desktop.Child("item.txt")
tisx = f.CreateTextFile
Dim Last_first_word As String
Dim lastName As String
Dim maxRow As Integer = Listbox1.ListCount - 1
For row As Integer = 0 To maxRow
If Listbox1.Cell(row, 0) <> Last_first_word Then
If lastName <> "" Then tisx.WriteLine(lastName)
tisx.WriteLine("")
tisx.WriteLine(ListBox1.Cell(row, 0))
tisx.WriteLine(ListBox1.Cell(row, 1) + " " + ListBox1.Cell(row, 2))
Last_first_word = ListBox1.Cell(row, 0)
lastName = ListBox1.Cell(row, 3)
Else
tisx.WriteLine(ListBox1.Cell(row, 1) + " " + ListBox1.Cell(row, 2))
End If
Next
If lastName <> "" Then tisx.WriteLine(lastName)
tisx.Close
The data has to be sorted by that group number in order for this to work.

Delphi - Declare Matrix const

Editing my Question.
I'll be specific.
How can I declare the code below as const instead of var?
(I couldn't get Cube example)
var
Matrix : array of array of string;
SetLength(Matrix, 8, 8);
Matrix[0,0]:='A0';Matrix[0,1]:='A1';Matrix[0,2]:='A2';Matrix[0,3]:='A3';Matrix[0,4]:='A4';Matrix[0,5]:='A5';Matrix[0,6]:='A6';Matrix[0,7]:='A7';
Matrix[1,0]:='B0';Matrix[1,1]:='B1';Matrix[1,2]:='B2';Matrix[1,3]:='B3';Matrix[1,4]:='B4';Matrix[1,5]:='B5';Matrix[1,6]:='B6';Matrix[1,7]:='B7';
Matrix[2,0]:='C0';Matrix[2,1]:='C1';Matrix[2,2]:='C2';Matrix[2,3]:='C3';Matrix[2,4]:='C4';Matrix[2,5]:='C5';Matrix[2,6]:='C6';Matrix[2,7]:='C7';
Matrix[3,0]:='D0';Matrix[3,1]:='D1';Matrix[3,2]:='D2';Matrix[3,3]:='D3';Matrix[3,4]:='D4';Matrix[3,5]:='D5';Matrix[3,6]:='D6';Matrix[3,7]:='D7';
Matrix[4,0]:='E0';Matrix[4,1]:='E1';Matrix[4,2]:='E2';Matrix[4,3]:='E3';Matrix[4,4]:='E4';Matrix[4,5]:='E5';Matrix[4,6]:='E6';Matrix[4,7]:='E7';
Matrix[5,0]:='F0';Matrix[5,1]:='F1';Matrix[5,2]:='F2';Matrix[5,3]:='F3';Matrix[5,4]:='F4';Matrix[5,5]:='F5';Matrix[5,6]:='F6';Matrix[5,7]:='F7';
Matrix[6,0]:='G0';Matrix[6,1]:='G1';Matrix[6,2]:='G2';Matrix[6,3]:='G3';Matrix[6,4]:='G4';Matrix[6,5]:='G5';Matrix[6,6]:='G6';Matrix[6,7]:='G7';
Matrix[7,0]:='H0';Matrix[7,1]:='H1';Matrix[7,2]:='H2';Matrix[7,3]:='H3';Matrix[7,4]:='H4';Matrix[7,5]:='H5';Matrix[7,6]:='H6';Matrix[7,7]:='H7';
The specific problem in your code is that the array you are declaring is dynamic. That is, the bounds are not fixed and can be changed at run-time.
In older versions of Delphi (XE6 and earlier) is it simply not possible to declare dynamic array constants. In XE7 and later it is possible but the syntax is different than for fixed array constants.
In all versions, if you declare a constant array with specified (and therefore fixed) bounds you can then specify the contents of the constant array thus:
const
Matrix : array[0..7, 0..7] of String =
(
('A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7'),
('B0', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'),
('C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7'),
('D0', 'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7'),
('E0', 'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7'),
('F0', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7'),
('G0', 'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7'),
('H0', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7')
);
If your array needs to be dynamic in a version of Delphi earlier than XE6 then you cannot initialise such an array with a declaration like this.
If you are using Delphi XE7 or later, then you can use the alternate syntax for declaring a dynamic array constant. This is very similar to the syntax for a fixed array constant but uses square braces [] instead of regular parentheses ():
const
Matrix : array of array of String =
[
['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7'],
['B0', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'],
['C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7'],
['D0', 'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7'],
['E0', 'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7'],
['F0', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7'],
['G0', 'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7'],
['H0', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7']
];
Hybrid Solution for Older Delphi Versions
If you are using an older version of Delphi then even with a dynamic array, if you have some initial state (bounds and content) that you would like to initialise it with then you could use a fixed array constant to define that initial state and then initialise your dynamic array at run-time from that constant, something like:
const
MX_DIM = 8;
MX_DEFAULT : array[0..MX_DIM - 1, 0..MX_DIM - 1] of String =
(
('A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7'),
('B0', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7'),
('C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7'),
('D0', 'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7'),
('E0', 'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7'),
('F0', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7'),
('G0', 'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7'),
('H0', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7')
);
// Then in your code:
var
x, y: Integer;
Matrix: array of array of String;
begin
// Initialise 'Matrix' from MX_DEFAULT:
SetLength(Matrix, MX_DIM, MX_DIM);
for x := 0 to Pred(MX_DIM) do
for y := 0 to Pred(MX_DIM) do
Matrix[x, y] := MX_DEFAULT[x, y];
end;
The documentation shows how to declare constant arrays
Array Constants
To declare an array constant, enclose the values of the elements of
the array, separated by commas, in parentheses at the end of the
declaration. These values must be represented by constant expressions.
For example:
const Digits: array[0..9] of Char =
('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
declares a typed constant called Digits that holds an array of
characters.
To define a multidimensional array constant, enclose the values of
each dimension in a separate set of parentheses, separated by commas.
For example:
type
TCube = array[0..1, 0..1, 0..1] of Integer;
const
Maze: TCube = (((0, 1), (2, 3)), ((4, 5), (6,7)));
creates an array called Maze where:
Maze[0,0,0] = 0
Maze[0,0,1] = 1
Maze[0,1,0] = 2
Maze[0,1,1] = 3
Maze[1,0,0] = 4
Maze[1,0,1] = 5
Maze[1,1,0] = 6
Maze[1,1,1] = 7
These examples are for one dimensional and three dimensional arrays. For a two dimensional array it would be:
const
Coords: array [0..2, 0..2] of string = (
('A0', 'A1', 'A2'),
('B0', 'B1', 'B2'),
('C0', 'C1', 'C2'),
);

How to split a string using an integer array?

I am trying to split a string using an integer array as mask.
The task is simple but I am not accustomed to ADA (which is a constraint).
Here is my code. It works exept that I have an one character offset when testing against a file. Can someone help me remove this offset. it is drinving me nuts.
generic_functions.adb :
package body Generic_Functions is
-- | Sums up the elements of an array of Integers
function Sum_Arr_Int(Arr_To_Sum: Int_Array) return Integer is
Sum: Integer;
begin
Sum := 0;
for I in Arr_To_Sum'Range loop
Sum := Sum + Arr_To_Sum(I);
end loop;
return Sum;
end Sum_Arr_Int;
-- | Split up a String into a array of Unbounded_String following pattern from an Int_Array
function Take_Enregistrements(Decoup_Tab: Int_Array; Str_To_Read: String) return Str_Array is
Previous, Next : Integer;
Arr_To_Return : Str_Array(Decoup_Tab'Range);
begin
if Sum_Arr_Int(Decoup_Tab) > Str_To_Read'Length then
raise Constraint_Error;
else
Previous := Decoup_Tab'First;
Next := Decoup_Tab(Decoup_Tab'First);
for I in Decoup_Tab'Range loop
if I /= Decoup_Tab'First then
Previous := Next + 1;
Next := (Previous - 1) + Decoup_Tab(I);
end if;
Arr_To_Return(I) := To_Unbounded_String(Str_To_Read(Previous..Next));
end loop;
return Arr_To_Return;
end if;
end Take_Enregistrements;
end Generic_Functions;
generic_functions.ads :
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
package Generic_Functions is
-- | Types
type Int_Array is array(Positive range <>) of Integer;
type Str_Array is array(Positive range <>) of Unbounded_String;
-- | end of Types
-- | Functions
function Sum_Arr_Int(Arr_To_Sum: Int_Array) return Integer;
function Take_Enregistrements(Decoup_Tab: Int_Array; Str_To_Read: String) return Str_Array;
-- | end of Functions
end Generic_Functions;
generic_functions_tests.adb :
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Generic_Functions; use Generic_Functions;
procedure Generic_Functions_Tests is
-- | Variables
Decoup_Test : constant Int_Array(1..8) := (11, 19, 60, 24, 255, 10, 50, 255);
Test_Str_Arr : Str_Array(Decoup_Test'Range);
Test_Str_Arr2 : Str_Array(Decoup_Test'Range);
Test_Str_Arr3 : Str_Array(Decoup_Test'Range);
--Test_Int : Integer;
Test_Handle : File_Type;
-- | end of Variables
begin
Open(Test_Handle, In_File, "EXPORTFINAL.DAT");
Test_Str_Arr := Take_Enregistrements(Decoup_Test, Get_Line(Test_Handle));
Test_Str_Arr2 := Take_Enregistrements(Decoup_Test, Get_Line(Test_Handle));
Test_Str_Arr3 := Take_Enregistrements(Decoup_Test, Get_Line(Test_Handle));
for I in Test_Str_Arr'Range loop
Put_Line(To_String(Test_Str_Arr(I)));
end loop;
for I in Test_Str_Arr2'Range loop
Put_Line(To_String(Test_Str_Arr2(I)));
end loop;
for I in Test_Str_Arr3'Range loop
Put_Line(To_String(Test_Str_Arr3(I)));
end loop;
-- for I in Test_Str_Arr'Range loop
-- Test_Int := To_String(Test_Str_Arr(I))'Length;
-- Put_Line(Integer'Image(Test_Int));
-- end loop;
-- for I in Test_Str_Arr2'Range loop
-- Test_Int := To_String(Test_Str_Arr2(I))'Length;
-- Put_Line(Integer'Image(Test_Int));
-- end loop;
-- for I in Test_Str_Arr3'Range loop
-- Test_Int := To_String(Test_Str_Arr3(I))'Length;
-- Put_Line(Integer'Image(Test_Int));
-- end loop;
Close(Test_Handle);
end Generic_Functions_Tests;
and finaly the file:
000000000012012-01-01 10:00:00 IBM IBM COMPAGNIE IBM FRANCE 17 AVENUE DE l'EUROPE 92275 BOIS-COLOMBES CEDEX CONFIGURATION COMPLETE SERVEUR000000000000000000000019 .6000000000001000000000000000000001000.00000000000000000000000000000196.00000000000000000000000000001196.00000000
000000000022012-01-01 11:00:00 MICROSOFT MSC 39 QUAI DU PRESIDENT ROOSEVELT 92130 ISSY-LES-MOULINEAUX AMENAGEMENT SALLE INFORMATIQUE000000000000000000000019.6000000000001000000000000000000001000.00000000000000000000000000000196.00000000000000000000000000001196.00000000
000000000032012-01-01 12:00:00 MICROSOFT MSC 39 QUAI DU PRESIDENT ROOSEVELT 92130 ISSY-LES-MOULINEAUX TESTS SUR SITE000000000000000000000019.6000000000001000000000000000000003226.52000000000000000000000000000632.39792000000000000000000000003858.91792000 DELEGATION TECHNICIEN HARD000000000000000000000019.60000000000000000000000000000001.00000000000000000000000000001000.00000000000000000000000000000196.00000000000000000000000000001196.00000000
These lines:
if I = Decoup_Tab'Last then
Arr_To_Return(I) := To_Unbounded_String(Str_To_Read(Previous..Next));
end if;
will overwrite the last element in your array.
Also, are you sure that the line number (00000000001, 00000000002, etc) is one of the strings you want to split based on the integer mask? As your code is right now, you use '11' twice, once for the line number and once for the date-field. If you skip the line number, the other numbers seem to make more sense.

Strange behaviour using StrUtils 'SearchBuf'

I am tidying old code that used to use FastStrings and I've implemented an old routine of mine 'PosAnyCase' which should operate like 'Pos'. (I was hoping that SearchBuf was better than calling UpperCase on both strings).
function PosAnyCase( const AFindStr, AStr : string ) : integer;
// Returns the position of this substring within a string ignoring case
I'm using SearchBuf as follows:
function PosAnyCase( const AFindStr, AStr : string ) : integer;
// Returns the position of this substring within a string ignoring case
var
Start, ResultPos : PChar;
begin
Start := PChar( AStr );
ResultPos := SearchBuf(
Start, ByteLength( AStr ),
0, 0,
AFindStr, [soDown] );
if ResultPos = nil then
Result := 0
else
Result := ResultPos-Start+1;
end;
When I call this routine from my unit tests, the following tests PASS:
Check(
PosAnyCase( '', '123' ) = 0 );
Check(
PosAnyCase( '2', '123' ) = 2 );
Check(
PosAnyCase( 'A', 'ABC' ) = 1 );
Check(
PosAnyCase( 'a', 'ABC' ) = 1 );
Check(
PosAnyCase( 'the', 'hellot there' ) = 8 );
Check(
PosAnyCase( 'THE', 'hellot there' ) = 8 );
But this test FAILS:
Check(
PosAnyCase( 'nice', 'does not have n i c e' ) = 0 );
What am I doing wrong please? The documentation on SearchBuf is very limited....
Thanks
The call to ByteLength is incorrect. Although the documentation explicitly states that the parameter is the length in bytes, that is not the case. You should use Length instead because the function actually expects units of char rather than units of byte.

Resources