Printing Out Characters in Ada - string

I have these declared:
subtype Num_Char is Natural
range 1 .. Definitions.Page_Width + 1;
subtype Number_Of_Rows is Definitions.Number_Of_Rows;
type Chars is array (Number_Of_Rows, Num_Char) of Character;
The_Chars : Chars;
What is the best way to print this out to the screen using Ada.Text_IO.Put_Line()?

Assuming you want to use Ada.Text_IO and not just Put_Line specifically, and assuming that Number_Of_Rows is meant to be an integer range like Num_Char, that would be
for R in The_Chars'Range (1) loop
for C in The_Chars'Range (2) loop
Ada.Text_IO.Put (The_Chars (R, C));
end loop;
Ada.Text_IO.New_Line;
end loop;

A lot of problems in Ada actually go back to your initial choice of types. So personally, I'd suggest a slight rewrite to make your life easier:
subtype Row is String (1..Definitions.Tote_Page_Width + 1);
type Chars is array (Definitions.Number_Of_Rows) of Row;
Now you could write this out with the following:
for I in The_Chars'range loop
Ada.Text_IO.Put_Line (The_Chars (I));
end loop;
However, there is still a big problem here. Put_Line will print out all the characters in each row. Ada strings are not null-terminated, so if there unused data at the end of some of your lines, that will get printed too.
There are lots of ways to deal with this, but they are very different techniques than would be used to handle C strings. If you try to handle Ada strings like you'd handle C strings, you will drive yourself nuts.
For this reason, I would dearly like to see your code that actually fills The_Char with data (and the rationale behind it).

Related

Exercice with type String in Pascal

(Translated from German to Englisch)
I need help in this exercise :
Thread: String processing The user can make simple changes to an input sentence.
conditions
The program displays a menu for the user to select the following action. This is also displayed again after the action has been completed until the user terminates the program (a loop is therefore required).
The menu contains the following items, which should be executed when the specified letter is entered:
A. Enter the sentence
B. Determine the number of words
C. Determine the number of characters that are less than their sequence character
D. Replace all the words in the sentence with their uppercase initials
X. end
If the user enters a different letter, nothing happens or the menu is output again.
If the menu item A is selected, a prompt is issued to enter a set which is read into a string variable. This variable can not be changed by the actions of menu items B, C and D! Possibly. A copy of the set has to be prepared beforehand in another string variable.
In menu point B the number of all words in the block is to be counted. For simplicity, you can assume that there is always one space between two words. At the beginning and end of the sentence there are no spaces. The number of words is output after the calculation (e.g., "The set is 4 words").
If the user executes menu item C, the set is traversed character-by-character, and for each character it is checked whether it is smaller than its trailing character. Here is a simple character comparison (you can also write directly something like '1' <'d'). The number of characters so found is then output (e.g., "13 characters found in the sentence less than the trailing character").
In menu item D, the sentence is traversed and every word contained in it is replaced by its upper-case initial character. The capitalization is of course only made if the first character is a letter, otherwise the character remains unchanged. You can assume that the sentence never starts or ends with a space. Between two words there is always exactly one space and so it should be between the initial letters. For example, from "123 good mood" becomes "1 G L".
It is not permissible here to build up a completely new string piece by piece! Instead, you should work in a loop on a copy of the original sentence with pos, copy, length, delete and insert! It is also forbidden to "gather" the initial characters all at the beginning or end of the string; These should be inserted directly into the string at the position of the corresponding word!
Furthermore, a string can not be accessed at menu point D, because the work with string routines is to be practised explicitly here. Menu items B, C and D may only be selectable if a record has already been entered. Otherwise nothing happens or a fault message is entered when entering B, C or D in the menu and the menu is output again.
Each call to the menu items B, C or D will always work on the original set entered by the user and not on a set that has already been altered by previously executed menu items!
By entering the menu item A again, the entered block can be overwritten by a new one.
With an 'X' the user can terminate the program.
Use wherever it is the predefined string functions and do not write it yourself with difficulty loops, etc.! However, the use of the strreplace or reverseString functions is forbidden!
Here's my work till now, I only have problems with part D:
program Project2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
const
lz = ' ';
var
Satz: string;
Buchstabe: char;
i, p, j, zaehler2, index, count: integer;
writeln('A) Write Sentence');
readln(Satz);
'D':
begin
index := 2;
insert(lz, Satz, length(Satz)+1);
count := (pos(lz,Satz));
repeat
delete(Satz, index,(count - index));
index := index + 2;
count := pos(lz,copy(Satz,index,(length(Satz)-index)))+index-1;
until ;
writeln(uppercase(Satz));
end
I'm glad you've found your own solution, well done!
While you've been doing that, I've been writing the answer below and, as I
have finished it, I thought I'd post it here to show you another way
to go about the problem of extracting words from a string. There are
dozens of ways of doing that task, but I hope the one I've used is fairly
easy to follow.
Maybe the reason you were having a problem with this is that your string-indexing
expressions are a bit too complicated. I bet if you come back to your code in 6 months
it will take you a while to figure out what it is supposed to be doing and longer
to tell whether it is actually doing it. The key to avoiding problems like that
is to break your code up into chucks which are easier to follow and easier
to test. So instead of just telling you what your repeat condition should be,
I'll show you a way which is easier to follow.
The first thing to do is to extract a singe word from the input. So, first thing
I've written is a function, ExtractFirstWord which returns the first word in
the input string, whether or not the input includes spaces, and also returns
a Remainder string which is what is left or the input string after the first
word (and any spaces immediately following it have been removed). This is done
using some simple while loops which are coded to skip over the leading spaces
and then build a string from the non-space characters which follow.
Code
const
lz = ' ';
var
Satz: string;
FirstWord : String;
Remainder : String;
function ExtractFirstWord(const InputStr : String; var Remainder : String) : String;
var
P : Integer;
WordStart : Integer;
begin
Result := '';
P := 1;
// The following skips over any spaces at the start of InputStr
while (P <= Length(InputStr)) and (InputStr[P] = lz) do
Inc(P);
// Now we know where the first word starts
WordStart := P;
// Now we can get the first word, if there is one
while (P <= Length(InputStr)) and (InputStr[P] <> lz) do
Inc(P);
Result := Copy(InputStr, WordStart, P - WordStart);
Remainder := Copy(InputStr, P, Length(InputStr));
// the following is one way to remove spaces at the start of Remainder
while (Length(Remainder) > 0) and (Remainder[1] = lz) do
Delete(Remainder, 1, Length(lz));
// instead you could do something simlar to the first `while` loop above
end;
begin
Satz := ' cat dog ';
repeat
FirstWord := ExtractFirstWord(Satz, Remainder);
FirstWord := UpperCase(FirstWord);
Satz := Remainder;
writeln('First word: ', FirstWord, ' remainder: ', Remainder);
until Remainder = '';
readln;
end.
This particular way of doing it is not an ideal fit with the other requirements
specified in your task but should be easily adaptable to them. E.g, the upper-casing of words could be done "in place" on the input string by upper-casing the current character of it in the second While loop.
Btw, if you are using Delphi or Free Pascal/Lazarus, there is a much simpler
way of extracting the words from a string. It uses a TStringList. Try
looking it up in the online help and have a thing about how you might use it
to do the task.

Displaying positive symbol for positive elements in MATLAB array?

I have an array in MATLAB, and I wanted to display the positive symbol, "+" in front of positive elements, and keep the negative symbol, "-" in already existing negative values. I thought I could do the following:
I was thinking of constructing a sort of cell string or string array, and having an if, else system where if the numbers magnitude was >0, then I should store the value as '+' concatenated with the conversion of the element. If it was 0, just do a straight up char conversion since 0 has no sign, and if it was negative, just convert it. I know what to do, however, logistically, I think my order of commands is whacky.
How can I implement this?
I have the following script for an array x, but it just spews out values, I want an orderly string array I can copy and paste for use outside of MATLAB.
x;
pos = '+';
bound = length(x);
for i=1:bound
if(x(i)==0)
num2str(x(i))
end
if(x(i)>0)
num2str(x(i))
strcat(pos,num2str(x(i)))
end
if(x(i)<0)
num2str(x(i))
strcat(pos,num2str(x(i)))
end
end
I think you are searching for this.
Let's make an example.
First type in your command window :
test = 5;
Then:
sprintf('%+d',test)
You should have in this way what you want.
Of course you need to adapt it to your case. I suggest you to read this.
I hope it helps.

(F)Lex checking symbol without "consuming" it

The purpose of this is to concatenate strings (with (f)lex if possible) if they're written consecutively separated only by whitespace.
Strings start and end with "s.
The thing is I used states and while it can concatenate the strings it also consumes the next character/symbol that comes right after the strings.
For example -- "this " "is only " "1 string"id -- this will concatenate the strings ("this is only 1 string") but it will also "consume" the i in id thus destroying one token.
Is there a way to check the next char/symbol without actually "consuming/disposing" (can't really think of a term) it.
\" yy_push_state(X_STRING); yylval.s = new std::string("");
<X_STRING>\" yy_push_state(X_CONC);
<X_STRING>. yylval.s += yytext;
<X_STRING>\n yyerror("newline in string");
<X_CONC>[ ^\n] ;
<X_CONC>\" yy_pop_state();
<X_CONC>. yy_pop_state(); yy_pop_state(); return STRING
Any way to do it?
You can use yyless(0) to cause the current token to be rescanned. Make sure you change start condition, or you'll end up with an endless loop.
By the way, I think your code would be more readable if you switched start conditions with BEGIN rather than using the state stack. In fact, you could easily avoid start conditions, but that would make interpreting escape sequences more complicated. Possibly better would be to just avoid X_CONC by using a rule for \"[[:space:]]*\"

Parsing strings in Fortran

I am reading from a file in Fortran which has an undetermined number of floating point values on each line (for now, there are about 17 values on a line). I would like to read the 'n'th value on each line to a given floating point variable. How should i go about doing this?
In C the way I wrote it was to read the entire line onto the string and then do something like the following:
for(int il = 0; il < l; il++)
{
for(int im = -il; im <= il; im++)
pch = strtok(NULL, "\t ");
}
for(int im = -l; im <= m; im++)
pch = strtok(NULL, "\t ");
dval = atof(pch);
Here I am continually reading a value and throwing it away (thus shortening the string) until I am ready to accept the value I am trying to read.
Is there any way I can do this in Fortran? Is there a better way to do this in Fortran? The problem with my Fortran code seems to be that read(tline, '(f10.15)') tline1 does not shorten tline (tline is my string holding the entire line and tline1 what i am trying to parse it into), thus I cannot use the same method as I did in my C routine.
Any help?
The issue is that Fortran is a record-based I/O system while C is stream-based.
If you have access to a Fortran 2003 compliant compiler (modern versions of gfortran should work), you can use the stream ACCESS specifier to do what you want.
An example can be found here.
Of course, if you were really inclined, you could just use your C function directly from Fortran. Interfacing the two languages is generally simple, typically only requiring a wrapper with a lowercase name and an appended underscore (depending on compiler and platform of course). Passing arrays or strings back and forth is not so trivial typically; but for this example that wouldn't be needed.
Once the data is in a character array, you can read it into another variable as you are doing with the ADVANCE=no signature, ie.
do i = 1, numberIWant
read(tline, '(F10.15)', ADVANCE="no") tline1
end do
where tline should contain your number at the end of the loop.
Because of the record-based I/O, a READ statement will typically throw out what is after the end of the record. But the ADVANCE=no tells it not to.
If you know exactly at what position the value you want starts, you can use the T edit descriptor to initiate the next read from that position.
Let's say, for instance, that the width of each field is 10 characters and you want to read the fifth value. The read statement will then look something like the following.
read(file_unit, '(t41, f10.5)') value1
P.s.: You can dynamically create a format string at runtime, with the correct number after the t, by using a character variable as format and use an internal file write to put in this number.
Let's say you want the value that starts at position n. It will then look something like this (I alternated between single and double quotes to try to make it more clear where each string starts and stops):
write(my_format, '(a, i0, a)') "(t", n, ', f10.5)'
read(file_unit, my_format) value1

Modifying a character in a string in Lua

Is there any way to replace a character at position N in a string in Lua.
This is what I've come up with so far:
function replace_char(pos, str, r)
return str:sub(pos, pos - 1) .. r .. str:sub(pos + 1, str:len())
end
str = replace_char(2, "aaaaaa", "X")
print(str)
I can't use gsub either as that would replace every capture, not just the capture at position N.
Strings in Lua are immutable. That means, that any solution that replaces text in a string must end up constructing a new string with the desired content. For the specific case of replacing a single character with some other content, you will need to split the original string into a prefix part and a postfix part, and concatenate them back together around the new content.
This variation on your code:
function replace_char(pos, str, r)
return str:sub(1, pos-1) .. r .. str:sub(pos+1)
end
is the most direct translation to straightforward Lua. It is probably fast enough for most purposes. I've fixed the bug that the prefix should be the first pos-1 chars, and taken advantage of the fact that if the last argument to string.sub is missing it is assumed to be -1 which is equivalent to the end of the string.
But do note that it creates a number of temporary strings that will hang around in the string store until garbage collection eats them. The temporaries for the prefix and postfix can't be avoided in any solution. But this also has to create a temporary for the first .. operator to be consumed by the second.
It is possible that one of two alternate approaches could be faster. The first is the solution offered by PaĆ­lo Ebermann, but with one small tweak:
function replace_char2(pos, str, r)
return ("%s%s%s"):format(str:sub(1,pos-1), r, str:sub(pos+1))
end
This uses string.format to do the assembly of the result in the hopes that it can guess the final buffer size without needing extra temporary objects.
But do beware that string.format is likely to have issues with any \0 characters in any string that it passes through its %s format. Specifically, since it is implemented in terms of standard C's sprintf() function, it would be reasonable to expect it to terminate the substituted string at the first occurrence of \0. (Noted by user Delusional Logic in a comment.)
A third alternative that comes to mind is this:
function replace_char3(pos, str, r)
return table.concat{str:sub(1,pos-1), r, str:sub(pos+1)}
end
table.concat efficiently concatenates a list of strings into a final result. It has an optional second argument which is text to insert between the strings, which defaults to "" which suits our purpose here.
My guess is that unless your strings are huge and you do this substitution frequently, you won't see any practical performance differences between these methods. However, I've been surprised before, so profile your application to verify there is a bottleneck, and benchmark potential solutions carefully.
You should use pos inside your function instead of literal 1 and 3, but apart from this it looks good. Since Lua strings are immutable you can't really do much better than this.
Maybe
"%s%s%s":format(str:sub(1,pos-1), r, str:sub(pos+1, str:len())
is more efficient than the .. operator, but I doubt it - if it turns out to be a bottleneck, measure it (and then decide to implement this replacement function in C).
With luajit, you can use the FFI library to cast the string to a list of unsigned charts:
local ffi = require 'ffi'
txt = 'test'
ptr = ffi.cast('uint8_t*', txt)
ptr[1] = string.byte('o')

Resources