function fn = address( varargin ) %ADDRESS by itself is an address book. % The program stores several fields such as FirstName, % LastName, Phone number, address, etc. for a list of % people like an address book. The list (a structure) % is saved to a *.mat file for storage. The program % repeatedly displays the menu until an exit character % is selected ('q' or 'x'). The book is automatically % resorted by last name whenever it is saved. % To start a new address book, use the command % ADDRESS('initialize'). It would be helpful to edit % the initialization fields to suit your own needs before % actually initializing the file (use 'edit address'). % Fields may be only be added or deleted before the % initialization is performed. % % Notes: % To run the program, either use 'run address' or % just 'address' with no arguments. % The 'LastName' field must be present because the % program sorts by last name. Everything else is done % blindly, that is, only if it exists. % The Matlab 'clc' command can be used in the main menu % to clear the screen. % % Last edit: Colin Joye, 9/9/02 % --------------- begin user definitions 1/2 -------------------- %fname = 'c:\matlab6p1\work\address_book'; % Address book file. fname = 'address_book'; % Address book file. % --------------- end user definitions 1/2 -------------------- chg = 0; % chg == 1 if the address book may have been modified. if any(strcmp(varargin,'initialize')), c = 'y'; if exist([fname '.mat'])==2, c = input(['File ' fname '.mat already exists. You can create a new ' ... 'book by typing "edit address" and changing the "fname" variable ' ... 'Continue to initialize and erase existing? (y/n):' ],'s'); end if strcmp(lower(c),'y'), % Delete or add fields (*.X) to suit your needs below, but only % before the initialization is done, or else an existing 'fname' % file may be overwritten. 'A' is the address book structure used % throughout the program. % --------------- begin user definitions 2/2 -------------------- A.title = '' % Normally use for Dr., Prof., etc. A.FirstName = 'Colin'; % FirstName should be present. A.LastName = 'Joye'; % LastName must be present. A.email1 = 'colin.joye@villanova.edu'; A.email2 = 'cjoye@mit.edu'; A.email3 = 'cdanjo@aol.com'; A.phone_home = '610-524-0296'; A.phone_cell = ''; A.phone_other = ''; A.address_home = '226 Llandovery Dr., Exton, PA 19341'; A.address_other = 'MIT, Cambridge, MA (school)'; A.association = ''; A.notes = ''; A.class = ''; % --------------- end user definitions 2/2 -------------------- err = ''; % Error string. chg = 1; disp('> Initialization complete.'); else err = ['> Initialization cancelled.']; disp(err); end else % don't initialize, but just run the program... err = ''; % Error string causes program termination if used. try, load(fname); % loads the existing address book *.mat file. catch, err = ['> File ' fname '.mat does not exist.']; disp(err); disp([' Use ADDRESS(''initialize'') to start an ' ... 'address book']); end end %--------- Main program loop begins here --------------------- while strcmp(err,''), LA = length(A); % Menu section: displays menu for control. disp(' ');disp(' ');disp(' '); disp('------------------------------------'); disp('--------------- Menu ---------------'); disp('Select by typing the corresponding letter and hit enter'); disp(' A: Add a new entry.'); disp(' C: Count the entries.'); disp(' D: Delete an entry.'); disp(' E: Edit an entry.'); disp(' F: Find by keyword.'); disp(' H: Help and info.'); disp(' P: Print the book to a file.'); disp(' S: Save current address book (*.mat).'); disp(' L: List all names in book.'); disp(' V: View entire address book.'); disp(' Q or X: Exit the program.'); z = input( '--- Your Choice? >> ','s'); disp(' '); switch lower(z) case 'a' % add a new field. A = add_field(A); chg=1; case 'c' % provide a count of all entries. count(A); case 'clc' % clear screen. clc; case 'd' % delete a field. A = delete_field(A); chg=1; case 'e' % edit a field. A = edit_field(A); chg=1; case 'f' % find a field. arg = input('- Find keyword: ','s'); n = find_field(A,arg); format_out( A(n),n ); disp(['> ' int2str(length(n)) ' entries found.']); case 'h' % help and info. help address; case 'p' % print the entire address book to a file. print_field(A); case 's' % save entire address book. A = save_book(fname,A); chg=0; case 'l' % list all names in book. list_names(A,[]); case 'v' % view entire address book. for m=1:LA, format_out( A(m),m ); end case {'q','x'} % quit the program. quitting(A,fname,chg); break; otherwise % invalid char. disp(['** Unknown Option: ''' z ''', try again.']); end % ends switch-case. end % ends main while-loop. %--------- Main Program Loop Ends Here --------------------- %--------- Subfunction Defs Begin Here --------------------- % Add_field prompts for new information to add to the book. % If the LastName field is blank, nothing is added. function q = add_field(k) disp('Add field: '); q = k; Lk = length(k); fn = fieldnames(k); for m=1:length(fn), % Loop prompts used for input for each cfn = char(fn(m,:)); % field that exists in 'A' already. s = ['q(Lk+1).' cfn]; new = input(['- ' cfn ': '],'s'); ss=[s '= ''' new ''';' ]; eval(ss); end if isempty(q(Lk+1).LastName), disp('** A Last name must be entered. Try Again. **'); q=k; end return; %---------- % Delete_field finds the entry and prompts for permission % to delete it. function q = delete_field(k) arg = input('- Find keyword: ','s'); n = find_field(k,arg); n = choose_field(k,n); % n==[] means cancel. if ~isempty(n), format_out(k(n),n); yn = input('Delete above entry? (y/n) ','s'); if strcmp(lower(yn),'y'), % Deletion done by the "accordion Lk = length(k); % method". q( 1:(n-1) ) = k( 1:(n-1) ); q( n:(Lk-1) )=k( (n+1): Lk ); disp(' {Entry deleted}'); else q=k; disp(' {Entry not deleted}'); end else q=k; disp(' {No entries deleted}'); end return; %---------- % Edit_field finds the field and then prompts % the user for any changes. The "!<" and "!>" % options can be used to append information to the % existing string for convience. function q = edit_field(k) disp('Edit: '); arg = input('- Find keyword: ','s'); n = find_field(k,arg); n = choose_field(k,n); % n==[] means cancel. q=k; if ~isempty(n), format_out(k(n),n); fn=fieldnames(k); disp(' (!< to prepend to the existing chars, !> to postpend, !d to delete existing)'); for m=1:length(fn), cfn = char(fn(m,:)); s1 = ['q(n).' cfn]; s2 = ['cur=char( k(n).' cfn ');']; eval(s2); new = ''; new = input(['- Edit [' cfn ': ' cur ']: '],'s'); % lookfor prepend/postpend option. if ~isempty(findstr('!<',new)), new = strrep(new,'!<',''); new = [new cur]; % prepend. elseif ~isempty(findstr('!>',new)), new = strrep(new,'!>',''); new = [cur new]; % postpend. elseif ~isempty(findstr('!d',new)), new=''; s3=[s1 '= '''';' ]; % delete the existing eval(s3); % data. end if ~strcmp(new,''), % Just hitting enter on a field s3=[s1 '= ''' new ''';' ]; % keeps the existing eval(s3); % data. end end else disp(' {Edit cancelled}'); end return; %---------- % Find_options searchs a string 'in' for the % prepend/postpend/delete options and returns a string % which has these options chars removed, as well as the % complete string. function out = find_options( cur, new ) out=''; return; %---------- % Find_field returns all ind(ex/ices) of 'arg' in the % found in the structure 'k'. To find a substring, the % first letters must match (ignores case). function n = find_field(k,arg) m=0;n=[]; K = struct2cell(k); if ~isempty(arg), for m=1:size(k,2), if ~isempty( strmatch( lower(arg),lower( strvcat(K{:,m})) ) ), n = [n m]; end end end if isempty(n), disp(['The string ''' arg ''' could not be found.']); end return; %---------- % Count counts all of the fields and provides statistics. function count(k) Lk = length(k); z=struct2cell(k); fn = fieldnames(k); cnt=0; disp('Count of entries: '); disp(['> Total number of entries: ' int2str(Lk)]); for m=1:length(fn), for n=1:Lk, if ~cellfun('isempty',z(m,:,n)), cnt=cnt+1; end end disp(['- ' char(fn(m)) ': ' int2str(cnt)]); cnt=0; end return; %---------- % Subfunction Choose_field prompts the user to choose a % result if several are found.. function q = choose_field(k, n); Ln = length(n); if Ln>1, % then there are several results. flag = 0; % =1 exits when choice has been made. disp('---------------'); list_names(k,n); disp(' Cancel'); c = input(['-- ' int2str(Ln) ' results found, choose one: '],'s'); N = valid_choice(c,Ln);% prompts user for a valid choice. if N==0, % cancel character. q = []; return; else q = n(N); end else % there is only one result. q = n; end return; %---------- function list_names(k,n) % List_names lists all first and last names in the order % dictated by vector 'n'. If 'n' isempty, the names are % listed in order of entry into 'k'. if isempty(n), n = 1:length(k); end for m = 1:length(n), % display resulting names. fn = []; tt = []; if isfield(k, 'title'), if ~all(isspace(k(n(m)).title)), tt = [k(n(m)).title ' ']; end end if isfield(k, 'FirstName'), fn = k(n(m)).FirstName; end disp(['<' int2str(m) '> ' tt fn ' ' k(n(m)).LastName]); end return; %---------- function print_field(k) % Prints any or all of the fields to a file. fn = [fieldnames(k); cellstr('all')]; disp(['Print: Make a text file containing all of the ' ... 'entries of any of the options.']); for m=1:length(fn), % display resulting names. disp(['<' int2str(m) '> ' char(fn(m))]); end disp([' Cancel Print request.']); c = input('-- Select one or more (separate by SPACEBAR): ','s'); n = valid_choice(c,m+1); if all(n~=0), fid = input(['-- Input a file name with an extension: '],'s'); if ~isempty(fid), make_file(k,fn(n),fid); else disp('No filename was entered, try again.'); return; end end return; %---------- function n = valid_choice(c,Ln) % Prompts used for a valid choice from a menu. 'n==0' means % that 'exit' was chosen. 'c' is the input choice (char), % 1:Ln is the range of valid choices and 'n' is the valid % choice(s) (int). 'c' may also be a vector. n=0; while 1, % Keep prompting for choice until valid. v=str2num(c); if any(strcmp(c,'x')), break; elseif ~isempty(v) & all(v <= Ln) & all(v > 0), % valid choice. n = v; break; else % invalid choices c=input(['Unknown option: ''' c '''' ... ', Choose again or ''x'' to cancel: '],'s'); end end return %---------- % Prints requested info (k.name) to file (fid). function make_file(k,name,fid); try fprintf(fid,''); catch disp(['The file ''' fid ''' could not be written to.']); return; end fn = fieldnames(k); if strcmp(name,'all'), w=[]; else w=['.' name]; end for m=1:length(name) s=['z=k(' int2str(m) ')' w ';']; eval(s); end return; %---------- % Save_book sorts the book by LastName and saves 'A' % to *.mat file. function A = save_book(fname,B) [f,n] = sortrows(str2mat(B.LastName)); % Alphabetize. A = B(n); try, save(fname,'A'); catch, err = ['> Could not save file ' fname '.mat.']; disp(err); end disp(['File saved and sorted: ' fname '.mat']); return; %---------- % Formats structure 'z' for displaying. % 'n' is the index in the book. function format_out(z,n) x=struct2cell(z); for m=1:length(z), v=[]; % 'v' holds the indices of non-blank fields. for k=1:size(x,1), % Removing blank fields... if ~cellfun('isempty',x(k,:,m)), v=[v k]; end end f = fieldnames(z(m)); q=cell2struct(x(v,:,m),f(v),1); % Print in nice format... X = upper(z(m).LastName(1)); disp([' [ ' X ' ]~~~~~~~~~~~|-' int2str(n(m)) ... '-|~~~~~~~~~~~~~~~~']); disp(' '); disp( q ); disp([' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~']); disp(' '); end return; %---------- % Ask user for permission to save changes. function quitting(A,fname,chg) if chg & strcmp(lower(input('Save changes? (y/n) ','s')),'y'), save_book(fname,A); end return; %------- End adress.m -------------