Certificate ---------------------------------------------------------------------------------------------------------------------------------------------
This is from http://www.phon.ucl.ac.uk/courses/spsci/matlab/lect6.html. Some additional string tools such as substring are available at http://home.online.no /~ Pjacklam/Matlab/software/util/strutil /.
Certificate ---------------------------------------------------------------------------------------------------------------------------------------------
Objectives
By the end of the session you should:
Q be able to write simple functions and programs that manipulate text files and tables of strings.
Q be able to re-use a number of simple programming templates for some common programming tasks.
Outline
1.Writing to a text file
To save the results of some computation to a file in text format reqires the following steps:
A. Open a new file, or overwrite an old file, keeping a 'handle' for the file.
B. Print the values of expressions to the file, using the file handle
C. close the file, using the file handle
The file handle is a just a variable which identifies the open file in your program. This allows you to have any number of files open at any one time.
% Open File
FID = fopen('myfile.txt ', 'wt'); % 'wt 'means "write text"
If (FID <0)
Error ('could not open file "myfile.txt "');
End;
% Write some stuff to file
For I = 1:100
Fprintf (FID, 'Number = % 3d square = % 6D \ n', I, I * I );
End;
% Close the file
Fclose (FID );
2.Reading from a text file
To read some results from a text file is straightforward if you just want to load the whole file into memory. This requires the following steps:
A. Open an existing file, keeping a 'handle' for the file.
B. Read expressions from the file into a single array, using the file handle
C. close the file, using the file handle
The fscanf () function is the inverse of fprintf (). however it returns the values it reads as values in a matrix. you can control the 'shape' of the output matrix with a third argument.
A = fscanf (FID, "% G \ n", [3, INF]) % A has 3 rows and 1 Col per line
Disp (A (1, 1) % display first value on first line
Disp (A (1, 2) % display first value on second line
Disp (A (2, 1) % display second value on first line
Thus to read back the data we saved abve:
% Open File
FID = fopen('myfile.txt ', 'rt'); % 'rt 'means "Read text"
If (FID <0)
Error ('could not open file "myfile.txt "');
End;
% Read from file into table with 2 rows and 1 column per line
Tab = fscanf (FID, 'Number = % d square = % d \ n', [2, INF]);
% Close the file
Fclose (FID );
Rtab = tab '; % convert to 2 columns and 1 row per line
Reading a table of strings is more complex, since the strings have to be the same length. we can use the fgetl () function to get a line of text as characters, but we'll first need to find out the length of the longest string, then ensure all strings are the same length. here is a complete function for loading a text file as a table of fixed-length strings:
Function tab = readtextfile (filename)
% Read a text file into a matrix with one row per input line
% And with a fixed number of columns, set by the longest line.
% Each string is padded with NUL (ASCII 0) characters
%
% Open the file for reading
IP = fopen (filename, 'rt '); % 'rt' means read text
If (IP <0)
Error ('could not open file'); % just abort if error
End;
% Find length of longest line
Max = 0; % record length of longest string
CNT = 0; % record number of strings
S = fgetl (IP); % get a line
While (ischar (s) % while not end of File
CNT = CNT + 1;
If (length (s)> MAX) % keep record of longest
Max = length (s );
End;
S = fgetl (IP); % get next line
End;
% Rewind the file to the beginning
Frewind (IP );
% Create an empty matrix of appropriate size
Tab = char (zeros (CNT, max); % fill with ASCII Zeros
% Load the strings for real
CNT = 0;
S = fgetl (IP );
While (ischar (s ))
CNT = CNT + 1;
Tab (CNT, 1: length (s) = s; % slot into table
S = fgetl (IP );
End;
% Close the file and return
Fclose (IP );
Return;
Here is an example of its use:
% Write some variable length strings to a file
OP = fopen('weekdays.txt ', 'wt ');
Fprintf (OP, 'Sunday \ nmonday \ ntuesday \ nwednesday \ n ');
Fprintf (OP, 'Thursday \ nfriday \ nsaturday \ n ');
Fclose (OP );
% Read it into memory
Tab = readtextfile('weekdays.txt ');
% Display it
Disp (Tab );
3.Randomising and sorting a list
Assuming we have a table of values, how can we randomise the order of the entries? A good way of achieving this is analogous to shuffling a pack of cards. we pick two positions in the pack, then swap over the cards at those two positions. we then just repeat this process enough times that each card is likely to be swapped at least once.
Function rtab = randomise (Tab)
% Randomise the order of the rows in tab.
% Columns are unaffected
[Nrows, ncols] = size (Tab); % get size of input matrix
CNT = 10 * nrows; % enough times
While (CNT> 0)
Pos1 = 1 + fix (nrows * rand); % get first random row
Pos2 = 1 + fix (nrows * rand); % get second random row
TMP = tab (pos1, :); % save first row
Tab (pos1, :) = tab (pos2, :); % swap second into first
Tab (pos2, :) = TMP; % move first into second
CNT = cnt-1;
End;
Rtab = tab; % return randomised table
Return;
Sorting a list is easy if you just want some standard alphabetic ordering. But what if you want to choose some arbitrary ordering function? For example, how cocould you sort strings when case was not important? Here we use the ability of MATLAB to evaluate a function by name (feval () so that we can provide the name of a function for doing the comparisons the way we want. this function shocould take two rows and return-1 if the first row sorts earlier than the second, 1 if the second row sorts earlier than the first and 0 if there is no preference. here is a case-independent comparison function:
Function flag = comparenocase (str1, str2)
% Compares two strings without regard to case
% Returns-1, 0, 1 If str1 is less than, equal, greater than str2.
Len1 = length (str1 );
Len2 = length (str2 );
For I = 1: min (len1, len2)
C1 = str1 (I );
C2 = str2 (I );
If ('A' <= C1) & (C1 <= 'Z '))
C1 = char (ABS (C1)-32); % convert lower case to upper
End;
If ('A' <= c2) & (C2 <= 'Z '))
C2 = char (ABS (C2)-32); % convert lower case to upper
End;
If (C1 <C2)
Flag =-1; % str1 sorts earlier
Return;
Elseif (C2 <C1)
Flag = 1; % str2 sorts earlier
Return;
End;
End;
% Strings match up to length of shorter, so
If (len1 <len2)
Flag =-1; % str1 sorts earlier
Elseif (len2 <len1)
Flag = 1; % str2 sorts earlier
Else
Flag = 0; % no preference
End;
Return;
Here is a sort function that might be used with this comparison function.
Function stab = functionsortrows (tab, funcname)
% Sorts the rows of the input table using the supplied
% Function name to provide an ordering on pairs of rows
[Nrows, ncols] = size (Tab );
For I = 2: nrows % sort each row into place
J = I;
TMP = tab (J, :); % save row
% Compare this row with higher rows to see where it goes
While (j> 1) & (feval (funcname, TMP, tab (J-1, :)) <0 ))
Tab (J, :) = tab (J-1, :); % shift higher rows down
J = J-1;
End;
Tab (J, :) = TMP; % Put in ordered place
End;
Stab = tab; % return sorted table
Return;
4.Searching a list
How might we search a list of items for an item matching a specific value? If the list is unordered, all we can do is run down the list testing each entry in turn. this function finds the index of a row in a table that contains (anywhere) the characters in the supplied match string:
Function idx = findstring (tab, STR)
% Find the row Index containing a matching string
% Returns 0 if the string is not found
[Nrows, ncols] = size (Tab );
For idx = 1: nrows
Matches = findstr (tab (idx, :), STR );
If (length (matches)> 0)
Return;
End;
End;
Idx = 0;
Return;
However, the process can be much faster if the listed is sorted and we are searching for an exact match only. a so-called binary search is the fastest possible way of finding an item in a sorted list:
Function idx = binarysearch (tab, Val)
% Returns the row index of Val in sorted table Tab
% Returns 0 if Val is not found
[Nrows, ncols] = size (Tab );
Lo = 1;
Hi = nrows;
While (Lo <= Hi)
Idx = fix (Lo + hi)/2;
If (Val <tab (idx ,:))
Hi = idx-1;
Elseif (Val> tab (idx ,:))
Lo = idx + 1;
Else
Return;
End;
End;
Idx = 0;
Return;
5. cell arrays
Operations with text and tables of strings are made simpler in MATLAB through the use of "cell arrays ". these are a generalisation of MATLAB matrices such that cells can contain in any type of object. this allows MATLAB to manipulate tables of Variable Length strings. we will not be going into cell arrays in this course.