How to read a specific line from a text file in Pascal - pascal

So I'm making a program where the user enters some lines and saves them in a file, then we get he gets to choose what line he wrote to crypt it.
Means he'll enter a number, let's say 2 referring to line 2 in the text file.
The question is, how to get that specific line from the text file?
Seek obviously doesn't work with text files !
Procedure cryptProcess( Var msgFile, cryptFile : Text; N : Integer);
Var
pNumber : Integer;
Begin
Writeln('Select a phrase to crypt [Number : ',N,'] : ');
Readln( pNumber );
Reset( msgFile );
For i:= 1 To N Do
Begin
If ( i = pNumber ) Then
Begin
Readln( msgFile, tempVar2 );
Writeln( i );
Writeln( tempVar2 );
End;
End;
Close( msgFile );
End;

Pascal can only process text files sequentially - in order to read and use line n from a text file, you must read (and likely discard) lines 1 through n - 1. Your existing code never actually reads text from the file unless the user happens to request the first line.
What you want to do is replace
For i:= 1 To N Do
Begin
If ( i = pNumber ) Then
Begin
Readln( msgFile, tempVar2 );
Writeln( i );
Writeln( tempVar2 );
End;
End;
with
For i:= 1 To pNumber Do
ReadLn(msgFile, tempVar2);
WriteLn(pNumber);
WriteLn(tempVar2);
This reads the first pNumber lines from the file - that is, it reads up to the line that you want, and no further - and then prints the number and the line.

Related

The maximum in each row

I have a question for you. I need to write the maximum element in each line. For example, my table :
1 2 3 4
5 6 7 8
9 10 11 12
I want to get 4,8,12
I tried but no result:
Program Lab2;
type A=array[1..5,1..5] of integer;
var x:A;
i,j,s,max:integer;
Begin
writeln('Write date:');
for i:=1 to 5 do
for j:=1 to 5 do
read(x[i,j]);
for i:=1 to 5 do
for j:=1 to 5 do
begin
max:=x[i,1];
if (max<x[i,j]) then max:=x[i,j];
writeln(max);
end;
readln;
Please help me
end.
There are just three little mistakes:
1) if (max<x[i,j]) should be outside the second for loop, because you want initialize the max value only one time per row.
2) writeln(max); should be outside the second for loop, you want to print the value only one time per row.
3) read(x[i,j]); I reccomend to be readln (x[i,j]) because with read you only read one character, with readln you red characters till you find a new line character, and that will allow you to enter numbers with more than two digits.
This only make sense for strings, you can use read or readln with integers
Also I advice you to write the key word begin in the same line where you write a contol structure (for,while,if,etc), because in this way it's more similar to the C coding style convention, one of the most populars coding styles I guess. And also is better for you if you try to keep a similar coding style for any language.
so the code will be:
Program Lab2;
const SIZE=3;
type A=array [1..SIZE,1..SIZE] of integer;
var x:A;
i,j,max:integer;
Begin
writeln('Write date:');
for i:=1 to SIZE do begin
for j:=1 to SIZE do begin
readln(x[i,j]);
end;
end;
for i:=1 to SIZE do begin
max:=x[i,1];
for j:=1 to SIZE do begin
if (max<x[i,j]) then begin
max:=x[i,j];
end;
end;
writeln('the max value of the row ',i ,' is ',max);
end;
readln;
readln;
end.

Pascal syntax error 85

First off, I'm new to programming and I've just started learning pascal. I've encountered an error 85: ";" expected. I searched through the whole thing multiple times but I haven't been able to find the problem. Any suggestions?
Here's the code:
program test;
var
a,b,c:real;
begin
D:=sqr(b)-4*a*c;
writeln('Enter a value for a');
readln(a);
writeln('Enter a value for b');
readln(b);
writeln('Enter a value for c');
readln(c);
if ( D<0 ) then
begin
writeln('There is no solution.');
else
if ( D>0 ) then
begin
x1:=(-b+sqrt(D))/2*a;
x2:=(-b-sqrt(D))/2*a;
writeln('x1 is:');
writeln('x1:=',x1);
writeln(x2 is:);
writeln('x2:=',x2);
end;
end.
You have three begin and only two end statements. Indent your code and you would notice your mistake. Variable D, X1, and X2 are also undefined. There are other syntax errors in your output, ie, missing tic marks 'in one of your writeln statements near the end.
And you need a end before the else ..
program test;
var
a,b,c:real;
begin
D:=sqr(b)-4*a*c;
writeln('Enter a value for a');
readln(a);
writeln('Enter a value for b');
readln(b);
writeln('Enter a value for c');
readln(c);
if ( D<0 ) then
begin
writeln('There is no solution.');
end
else
if ( D>0 ) then
begin
x1:=(-b+sqrt(D))/2*a;
x2:=(-b-sqrt(D))/2*a;
writeln('x1 is:');
writeln('x1:=',x1);
writeln(x2 is:);
writeln('x2:=',x2);
end;
end.

read() strings of variable length

I've got rows of two values (input from console) that look likes this:
David 89000
Peter 99500
Jim 23999
END 1
is there a way to save the string and number into a variable other than to loop-read a char when you don't know the string length?
str:=''; salary:=0; i:=1;
while str<> 'END' do
begin
str:=''; salary:=0;
read(ch);
while ch <> ' ' do
begin
str:=str+ch;
read(ch);
end;
read(salary);
array[i].name:=str;
array[i].salary:=salary;
i:=i+1;
readln;
end;
You can do it with a single call to ReadLn and then parse the input yourself:
var
TextIn: string;
Person: string;
Salary: Integer;
begin
while true do
begin
ReadLn(TextIn); // Requires user to hit Enter
if Copy(TextIn, 1, 3) <> 'END' then
begin
Person := Copy(TextIn, 1, Pos(' ', TextIn) - 1);
Salary := StrToInt(Copy(TextIn, Pos(' ', TextIn) + 1, 255);
end
else
Exit;
end;
end;
I didn't include any error checking (which should be there), because your original code doesn't have any either.
Not with standard I/O functions. Of course you can put that code in a separate procedure, or split with tstringlist.

How does this program to count vowels work?

I want to understand this code, especially PROCEDURE
PROGRAM vowels;
USES crt;
{Program that counts the number of vowels in a sentence}
CONST space=' ';
maxchar=80;
TYPE vowel=(a,e,i,o,u);
VAR buffer:ARRAY[1..maxchar] of char;
vowelcount:ARRAY[vowel] of integer;
PROCEDURE initialize;
VAR ch:vowel;
BEGIN
FOR ch:=a TO u DO
BEGIN
vowelcount[ch]:=0;
END;
END;
PROCEDURE textinput;
VAR index:integer;
BEGIN
writeln('Input a sentence');
FOR index:=1 TO maxchar DO
IF eoln THEN buffer[index]:=space
ELSE read(buffer[index]);
readln;
END;
PROCEDURE analysis;
VAR index:integer;
ch:vowel;
BEGIN
index:=1;
WHILE index<>maxchar+1 DO
BEGIN
IF buffer[index] IN ['a','e','i','o','u'] THEN
BEGIN
CASE buffer[index] OF
'a':ch:=a;
'e':ch:=e;
'i':ch:=i;
'o':ch:=o;
'u':ch:=u;
END;
vowelcount[ch]:=vowelcount[ch]+1;
END;
index:=index+1;
END;
END;
PROCEDURE vowelout;
VAR ch:vowel;
BEGIN
clrscr;
writeln;
writeln(' a e i o u');
FOR ch:=a TO u DO
write(vowelcount[ch]:4);
writeln;
END;
BEGIN
initialize;
textinput;
analysis;
vowelout;
END;
Overall: Okay this code is counting the number of vowels supplied in the input string.
Lets Begin....
TYPE vowel=(a,e,i,o,u); VAR
buffer:ARRAY[1..maxchar] of char;
vowelcount:ARRAY[vowel] of integer;
This code is defining a list of the vowels in english (a,e,i,o,u).
PROCEDURE initialize; VAR ch:vowel;
BEGIN FOR ch:=a TO u DO BEGIN
vowelcount[ch]:=0; END; END;
It then defines a variable to collect the number of each vowel, called vowelcount. That variable is an array, looks sort of like this:
vowelcount[a]=0;
vowelcount[e]=0;
vowelcount[i]=0; #... etc
Then the procedure "Analysis" is defined. This takes the input from the screen (which will be called later on in the program) and steps through each letter in the input.
WHILE index<>maxchar+1 DO BEGIN IF
buffer[index] IN ['a','e','i','o','u']
THEN BEGIN CASE buffer[index] OF
'a':ch:=a; 'e':ch:=e; 'i':ch:=i;
'o':ch:=o; 'u':ch:=u; END;
If any of those letters happens to be in the list of letters than matches a vowel, then it will add one to the number in the vowelcount array above. (vowelcount[ch]:=vowelcount[ch]+1) where ch is the matched letter. As you can see this is only triggered if it is a valid vowel (IF buffer[index] IN ['a','e','i','o','u'] )
Finally. The main code of the program, or what is actually run:
BEGIN clrscr; writeln; writeln(' a e i
o u'); FOR ch:=a TO u DO
write(vowelcount[ch]:4); writeln; END;
BEGIN initialize; textinput; analysis;
vowelout; END.
This basically strings the application together, starting by clearing the screen (in a dos prompt) and then outputting the vowels onto the screen. It then adds some formatting and outputs the current count of vowelcount (as above).
It will then request your input and finally it will output the contents of vowelcount again, which has been updated with the vowelcounts from the input you made.

Concatenation with Zero is not occurring properly in code?

I was trying to reverse a number in PL/SQL. It's working fine, but when my number contains any 0, the output is unexpected. For example:
1234 output 4321
1000 output 1
1203 ouput 3021
10001 output 1
DECLARE
r number(9);
num number(9):=&p_num;
BEGIN
WHILE num>=1 LOOP
IF mod(num,10)=0 THEN -- extracting last digit of a number .
r:=r||0; --if end digit is 0 then concat r with 0
ELSE
r:=r||mod(num,10);--if mod is not 0 then it would be last digit.
END IF;
num:=trunc(num/10);--Removing last digit from number
END LOOP;
dbms_output.put_line(r);
END;
Try changing the type of the variable "r" to varchar2.
Since it's declared as number, leading zeros are discarded.
'Reversing a number' is fundamentally a string operation, not a numerical one. Numerically, the reverse of 10, 100, 1000, etc are all 1 - the leading zeroes in the result don't count. And the operation is not, therefore, invertible; all numbers with the same leading (significant) digits and with zero or more trailing zeroes produce the same output when reversed.
So, you need to revise your code to generate a character string, not a number.
You can't preserve leading zeros with numbers; you must use strings (varchar2). Try something like this to see:
DECLARE
r varchar2(9);
num varchars(9):=&p_num;
BEGIN
r := REVERSE(num);
dbms_output.put_line(r);
END;
I'm not sure what's going wrong in your code Vineet but perhaps this will work.
DECLARE
newStr varchar2(9) = "";
numStr varchar2(9) := to_char(&p_num);
i number;
BEGIN
i = length(numStr);
WHILE i>0 LOOP
newStr := newStr || substr(numStr, i, i + 1);
i = i - 1;
END LOOP;
dbms_output.put_line(r);
END;
Edit: Or as gabe correctly points out, just use the REVERSE function.
The problem is you're dealing with a NUMBER value. When you reverse 1000, you get 0001, which when output unformatted is 1.
What you really need is something akin to:
CREATE OR REPLACE FUNCTION rev(p_num NUMBER)
RETURN VARCHAR2 IS
v_chr VARCHAR2(50);
BEGIN
v_chr := p_num;
IF LENGTH(v_chr) > 1 THEN
RETURN SUBSTR(v_chr, -1, 1)||rev(SUBSTR(v_chr, 1, LENGTH(v_chr)-1));
END IF;
RETURN v_chr;
EXCEPTION
WHEN OTHERS THEN
RETURN 'Bad Input';
END;
/
Function created
SQL> SELECT rev(100000) FROM dual;
REV(100000)
--------------------------------------------------------------------------------
000001
SQL>

Resources