Access first element of string in Ada - arrays

I have a string passed into a function, I would like to compare the first character of the string against a number.
I.E.
if String(1) = "3" then
When I compile I get:
warning: index for String may assume lower bound of 1
warning: suggested replacement String'First + 1
I would really like to make this right, but when I try "first" it actually grabs a number, not the character.
Is there a better way to do it?
I tried looking up the 'First concept, and the below site explains I'm actually getting the number of the index, not the actual contents: http://en.wikibooks.org/wiki/Ada_Programming/Types/array
For example,
Hello_World : constant String := "Hello World!";
World : constant String := Hello_World (7 .. 11);
Empty_String : constant String := "";
Using 'First I'll get:
Array 'First 'Last 'Length 'Range
Hello_World 1 12 12 1 .. 12
World 7 11 5 7 .. 11
Empty_String 1 0 0 1 .. 0
Based on that information, I can't get H from Hello world (for a comparison like if Hello_World(1) = "H" then)
EDIT:
So the way I initially was doing it was
(insert some variable name instead of string in this case)
String(String'First .. String'First) = "1"
So that works from what I can tell, however, rather then writing all that, I found out that
String(String'First) = '1'
Does the same thing but using char comparison, which makes a lot more sense!
Thanks for all the answers everyone!

Strings are the biggest bugaboo for newbie Ada coders; particularly so for those who are already experts at dealing with strings in Cish languages.
Ada strings (in fact all Ada arrays) are not 0 based like C, or 1-based like Fortran. They are based however the coder felt like it. If someone wants to index their string from 10 ... 200, they can. So really the safest way to acces characters in an Ada string is to use the 'first attribute (or better yet, loop through them using 'range or 'first .. 'last).
In your case it looks like you want to get at only the first character in the string. The easiest and safest way to do that for a string named X is X(X'first).
In pactice you would almost never do that though. Instead you would be looping through the string's 'first...'last looking for something, or just using one of the routines in Ada.Strings.Fixed.

The warning is suggesting you use:
String(String'First + Index)
Instead of just
String(Index)

There's something odd about the code in your question. First off, that you're calling your variable "String" and that it's of type "String". Ada will balk at that right off the bat.
And the warning statements you reproduce for that code fragment don't make sense.
Let's say your variable is actually called "Value", i.e.:
Value : String := "34543";
Value(1) is not the same as Value(Value'First + 1), because Value'First (in this declaration) is 1. So you end up referencing Value(1 + 1). You appear to be experiencing this because of mentioning that you can't reference the 'H' in a "Hello World" string.
Now the warning is valid, in that you're safer using 'First (and 'Last and 'Range) to reference array bounds. But you need to use the proper indexing if you're going to offset from the bound retrieved via 'First, typically using either 0-based or 1-based (in which case you need to offset by 1). Use whichever base is more appropriate and readable in your context.

Related

In Smalltalk, how do you print specific elements of an array?

I am working on an introductory smalltalk program. The goal is to print all elements of an array of integers forward, backward, and then print only the elements of the array that end in a certain digit.
I have already done the first two, but I'm stuck on how I should handle the last goal.
Here is my code:
|myArray|
myArray _ Array new: 15.
1 to: 15 do: [:i | myArray at:i put:i*2].
myArray printNl.
myArray reverse printNl.
Is this for a class or are you following a tutorial? What other concepts have your learned (either in this class or in other languages)? If you couldn't send the #'printNl' message, what would you do?
I think that the purpose of this exercise is to introduce you to using loops (to iterate forwards and backwards), and to conditionals inside a loop (have you been introduced to conditionals and branching yet?).
If you had a loop that printed each element of the array, you could add a conditional (such as an #'ifTrue:' message) to isolate the printing.
It depends a bit on the dialect you are using.
I think the important thing is to realize that an Integer is not a String and therefore, they have different behaviour.
|myArray tail|
myArray := Array new: 15.
tail := '6'.
1 to: 15 do: [:i | myArray at:i put:i*2].
myArray do:[:entry | (entry asString matchesTail:tail) ifTrue:[entry "whatever your need to do with it"] ].

Subscript out of range when trying to get last item of an Array

For example, I have a string A-456-BC-123;DEF-456;GHI-789. And I need to search for second part:DEF-456 with keyword 456. The potential problem here is that the first part A-456-BC-123 also has the keyword 456. Currently my logic is that, split the string first using ;, split each of it again using -, get the last item of this Array, search keyword 456. Another thing is that I don't want to do a full keyword match like DEF-456, I only want to use 456 as keyword to locate DEF-456, in other words, 456 should be the last segment of the string I want.
Here are my codes:
FirstSplit= split("A-456-BC-123;DEF-456;GHI-789",";")
For each code in FirstSplit
SecondSplit = split(FirstSplit,"-")
'get Array Count
Count = Ubound(SecondSplit)
'get the last item in Array
If SecondSplit(Count-1) = "456" Then
'doing something
End if
Next
Currently, an error will generate at SecondSplit(Count-1), saying that "Subscript out of range: '[number: -1]'"
Could someone tell me how to fix it?
The real problem is here:
SecondSplit = Split(FirstSplit, "-")
You should be splitting your element which you've stored in variable code from your For Each loop. By trying to split an array you should be getting a Type Mismatch error, but perhaps vbscript is forgiving enough to attempt and return a 0 element array back or something. Anyway:
SecondSplit = Split(Code, "-")
Also, to look at the last element just use:
If secondSplit(Ubound(SecondSplit)) = "456" Then
Subtracting 1 from the ubound would get you the second to last element.
You don't need to split it twice - what you're looking for is Right():
FirstSplit = split("A-456-BC-123;DEF-456;GHI-789",";")
For each code in FirstSplit
If Right(code, 3) = "456" Then
' do something
End If
Next
Though this would also match an entry like ABC-1456. If the - symbol is a required delimiter, you'd have to say If Right(code, 4) = "-456".

Efficient allocation of cell array in matlab

I have some which converts a cell array of strings into a cell array of characters.
Note. For a number of reasons, both the input (C) and the output (C_itemised) must be cell arrays.
The cell array of strings (C) is as follows:
>> C(1:10)
ans =
't1416933446'
''
't1416933446'
''
't1416933446'
''
't1416933446'
''
't1416933446'
''
I have only shown a portion of the array here. In reality it is ~28,000 rows in length.
I have some code which does this, although it is very inefficient. The cellstr function takes up 72% of the code's time, as it is currently called thousands of times. The code is as follows:
C_itemised=cell(length(C),500);
for i=3:length(C)
temp=char(C{i});
for j=1:length(temp)
C(i-2,j)=cellstr(temp(j));
end
end
I have a feeling that some minor modifications could take out the inner loop, thus cutting down the overall running time substantially. I have tried a number of ways to do this, but I think I keep getting confused about whether to use {} or (), and haven't been able to find anything online that can help me. Can anyone see a way to make the code more efficient?
Please also note that this function is used in conjunction with other functions, and does work, although it is running slower than would be ideal. Therefore, I do not wish to change the format of C_itemised.
EDIT:
(A sample of) the output of my current function is:
C_itemised(1,1:12)
ans =
Columns 1 through 12
't' '1' '4' '1' '6' '9' '3' '3' '4' '4' '6' []
One thing I can suggest is to use the undocumented function sprintfc. This function is hidden from normal use in MATLAB, but it is used internally with a variety of other functions. Mainly, if you tried doing help sprintfc, it'll say that there's no function found! It's cool to sniff around the source sometimes!
How sprintfc works is that you provide it a formatting string, much like printf, and the data you want printed. It will take each individual element in the data and place them into individual cell arrays. As an example, supposing I had a string D = 'abcdefg';, if we did:
out = sprintfc('%c', D);
We get:
>> celldisp(out)
out{1} =
a
out{2} =
b
out{3} =
c
out{4} =
d
out{5} =
e
out{6} =
f
out{7} =
g
As such, it takes each element in your string and places them as individual characters serving as individual elements in a new cell array. The %c formatting string means that we want to print a single character per element. Check out the link to Undocumented MATLAB that I posted above if you want to learn more!
Therefore, try simplifying your loop to this:
C_itemised=cell(length(C));
for i=1:length(C)
C_itemised{i} = sprintfc('%c', C{i});
end
C_itemised will be a cell array, where each element C_itemised{i} is another cell array, with each element in this cell array being a single character that is composed of the string C{i}.
Minor Note
You said you were confused about {} and () in MATLAB for cells. {} is used to access individual elements inside the cell. So doing C{1} for example will grab whatever is stored in the first element of the cell array. () is used to slice and index into the cells. For example, if you wanted to make another cell array that is a subset of the current one, you would do something like C(1:3). This will create a three element cell array which is composed of the first three cells in C.

DNA extraction python

Now, I need to find a way in which Python can find the codon position number 5 of the above code and extract that sequence until position 12 (ATGG*CTTTACCTCGTC*TCACAGGAG). So the output should be something like this:
>CCODE1112_5..11
CTTTACCTCGTC
How can I tell python to get the begin value after the first "_" and the end value after ".." so it can do it automatically? ? THANKS!!!
def extractseq( queryseq , begin=5, end =12):
queryseq=queryseq.split('\n')#transform the string in a list of lines included in the string
return queryseq[1][begin-1:end-1]
I think this function should work, beware of the index which begin at 0 in python
after written that in your script you just have to call the function subs=extractseq(seq,5,12)
ok sorry so if you want to extract the 5 and the 12 included in the substring one way to do that easly is:
substring=queryseq.split('\n')[0].split('_')[1].split('...')#extraction of the substring
begin=substring[0]
end = substring[1]
I'd probably (sigh) use a regex to extract 5 and 12 from CCODE1112_5..12_ABC.
Then convert the extracted strings to int's.
Then use the int's as indexes in a string slice on the DNA data.
For the regex:
regex = re.compile(r'^[^]*(\d+)..(\d+)_.*$')
regex.match('CCODE1112_5..12_ABC')
match = regex.match('CCODE1112_5..12_ABC')
match.group(1)
'5'
match.group(2)
'12'
To convert those to int's, use int(match.group(1)), for example.
Then your indices are 1-based, while python's are 0-based. Also, python's starting point for a slice is at the value you want, and python's ending point for a slice is one past the value you want. So subtract one from group(1) and leave group(2) alone.
So something like:
substring = dna_data[left_point-1:right_point]

Largest word in an Array

Hey i'm having problems creating a simple button for a programme which finds the largest word in an array and puts it into a textbox. I've done most of the coding (I hope) was wondering if somebody could help me actually with the code that finds the largest text in the array as I am struggling the most with that.
Private Sub btnLongName_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLongName.Click
Dim LongName As String
Dim LengthOfLongestName As Integer
Dim UltimateName As String
For i As Integer = 0 To 5
LongName = Members(i).Name
LengthOfLongestName = Len(LongName)
If Members(i).Name.Length > LengthOfLongestName Then
End If
Next i
txtResult.Text = "The longest name is " & UltimateName & " ."
End Sub
End Class
Thanks for your time - its for college homework, struggling big time on it :(
edit: I've edited the code
Since this is homework, I won't write the code for you; instead I'll try to give you some hints that will point you in the right direction.
Declare a variable of an appropriate type to hold the <longest value so far>, initialize it with the "shortest" value for that type.
Loop through all the values in the array (perhaps with a For or For Each loop)
Pseudo-code for the inside your loop:
If the Length of <the value being checked> exceeds _
the Length of the <longest value so far> Then
Assign <the value being checked> to the <longest value so far>
End If
When the loop finishes, the <longest value so far> will be the longest value in the array.
Notes
You can use MSDN as a reference on how to use a For loop or a For Each loop (If you haven't learned For loops yet, you can also use a Do Loop)
<the value being checked> will be different on each iteration through the loop; it should correspond to each consecutive value in your array. You can verify that this is working by setting a breakpoint.
You can get the length of a string by saying myString.Length
If you've learned about Functions, consider writing a function that takes an array as a parameter, and returns the longest value in the array.
There are certainly ways you could do this with LINQ, but I don't think that is the goal of the assignment ;-]
In response to Edit 1:
Your If statement needs to be inside of some sort of loop (For, For Each, Do, etc) I think this is the key concept that you are missing.
Instead of comparing LongName.Length to LengthOfLongestName, you need to compare the length of an entry in your array to LengthOfLongestName
You're on the right track with Members(0).Name.Length, but you can't just check element 0; you have to check every element in the array.
Given your current code, you'll probably be assigning <An entry in your array>.Name to LongName
The last index in a one-dimensional array is <array>.Length - 1 or <array>.GetUpperBound(0).
The following doesn't really address anything in your assignment, but I hope it will give you some ideas on how to go through all the items in your list:
' A For loop that does a message box for each of the numbers from 0 to 5 '
For i as Integer = 0 To 5
MessageBox.Show(i)
Next i
' Code that does a message box with the names of the 2nd, 3rd and last '
' entries in Members '
' (Remember that the first item is at 0, the second item is at 1, etc...) '
MessageBox.Show(Members(1).Name)
MessageBox.Show(Members(2).Name)
MessageBox.Show(Members(Members.GetUpperBound()).Name)
In response to Edit 2:
You're getting warmer...
You should only update LongName and LengthOfLongName if the current value is the longest you've seen so far (i.e. they should be assigned inside of the If statement)
You have to go to the last index of the array, not 5. See above (the response to your first edit) on how to get that last index.
You don't really need the UltimateName variable; you can just use LongName ;-]
You might want to use <stringVariable>.Length instead of Len(<stringVariable>) to be consistent.
What you are missing is a loop that checks each member, and putting the If statement inside it and make it compare the length of the name to the longest name that you have found so far. If the name is longer, put it in the variable for the longest found, and update the length variable.
You can either initialise the variables with the name of the first member and loop from the second member and on, or you can initialise the variables with an empty string and loop all the members. Personally I prefer the latter one.

Resources