×
INTELLIGENT WORK FORUMS
FOR ENGINEERING PROFESSIONALS

Log In

Come Join Us!

Are you an
Engineering professional?
Join Eng-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!
  • Students Click Here

*Eng-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Jobs

How to parse strings character by character?

How to parse strings character by character?

How to parse strings character by character?

(OP)
One of the more frustrating things when coming from Nice Old FORTRAN(NOF) is input/output.  I have text output files from programs like NASTRAN which can vary slightly from version to version.  My simple FORTRAN code can parse the text line by line and character by character until I match a key word, then the real program can take over.  Another program's text output may have a text header but contain a floating point I want to capture, then have inconsistant row data (inconstant due to poor output routines of the originating code such that one line has 5 floats, the next five more, then two, then five, etc.).  I am forcing myself to use Matlab as a general rule these days, but fundamental I/O like this is not obvious (to me anyway).

Has anyone conquered this (and how)???

RE: How to parse strings character by character?

Below is one approach to reading FORTRAN (formatted) files.  Basically, the file is read with a textread command, and converted into a character array.  Key header lines (that indicate the start of data) are located with the strmatch command.  The data can be check to see if stars were written out (fortran overflow) with the findstr command.  And the numbers are read with the str2num command.  If you need/want further guidance on your specific example, let me know.  The example below is somewhat complex, since the data may have overflow (stars) and the number of eigenvalues to be read changes for each case.  But you should be able to follow it.

In step by step directions

1) Open the file with textread, and convert to a character array (using char command).  Store in a character array named file.

example code: Open a file named 'fortran.dat'

fname = 'fortran.dat'
file = char(textread(deblank(fname),
'%s','delimiter','\n','whitespace',''));

2) Find key lines using strmatch command.  A key line is a line with some type of a header, and the data that you want to read is a fixed number of lines from that header.  

example code: Find all occurances of the header line "1EIGENVALUES"

eigen_row=strmatch('1EIGENVALUES',file);

3) Determine how many header lines were found via size command.

example code: Determine the number of 1EIGENVALUE headers

ni = size(eigen_row,1);

4) Loop through the header lines with for statement

example code: Loop through header lines

for ii=1:ni

5) Numbers can be read with the str2num command.  You need to specifiy how many rows down from the header line, and the column range.

typical code: num = str2num(file(header_row+nlines,start_col:end_col));

example code:

    % Start and end of eigenvalues
    
    ic_start = eigen_row(ii)+12;
    ic_end = ic_start+mxx(ii)-1;
    ic_err = eigen_row(ii)-3;

        % Copy data into temp array
        
        eig_lines=file(ic_start:ic_end,:);
        
        % Correct each line for length
        
        eig_lines = my_adjust_eig(eig_lines);
        
        % Read each of the eigenvalue table lines
        
        nlines = size(eig_lines,1);
        neig=0;
        
        for iline=1:nlines   % Loop over the lines
            
            line=eig_lines(iline,:);     
            
            [im_lambda, err] = check_str(line(47:57));
            
            if (im_lambda >= 0)
                neig = neig+1;
                freq_hz(neig,ii) = check_str(line(71:83));
            end
            
        end


6) If needed, use findstr to check for valid data.  For fortran, you could check for stars (overflow write)

stars = findstr(str,'*');
if isempty(stars) ~= 0
    
    num = str2num(str);
    err = 0;
    if length(num)~=1
        num = nan;
        err=1;
    end
else
    num = nan;
    err=1;
end


Here is a complete program, you should be able to follow it

function read_freq

fname='freq9b.com.out';
[rpm,coll,f_cpm]=readcmrd(fname);

iline=0;
for icase=1:size(f_cpm,2);
%   for ifreq=size(f_cpm,1):-1:1
    for ifreq=size(f_cpm,1):-1:size(f_cpm,1)
        iline=iline+1;
%       s=sprintf('%6.4f     %4.1f     %4.0f', f_cpm(ifreq,icase)/rpm(icase), rpm(icase), coll(icase));
        s=sprintf('%5.1f  %5.1f  %6.4f', coll(icase), rpm(icase), f_cpm(ifreq,icase)/rpm(icase));
        ns=size(s,2);
        sp(iline,1:ns)=s;
    end
    iline=iline+1;
end
sp

function [rotor_speed_rpm,coll_deg,freq_cpm] = readcmrd(fname)

file = char(textread(deblank(fname),'%s','delimiter','\n','whitespace',''));
eigen_row=strmatch('1EIGENVALUES',file);
performance_row=strmatch('ROTORCRAFT PERFORMANCE  ',file);
mxx_row = strmatch('NUMBER OF STATES,   MXX =',file);
mxx=str2num(file(mxx_row,27:30));
ni = size(eigen_row,1);
for ii=1:ni
    % Read the rotor speed
    rotor_speed_rpm(ii) = str2num(file(performance_row(ii)+11,112:120));
    coll_deg(ii) = str2num(file(performance_row(ii)+19,25:35));
    % Read the eigenvalues
    % Two difficulties in reading eigenvalues
    % 1) The initial spaces are skipped, so the location of the number
    %    depends on how much white space is on that line
    % 2) Data with stars in freq, damp, real/sec or imag/sec has to be removed
    % 3) Remove data with negative imaginary part
    % 4) Print information if an error occurs
    
    % Start and end of eigenvalues
    
    ic_start = eigen_row(ii)+12;
    ic_end = ic_start+mxx(ii)-1;
    ic_err = eigen_row(ii)-3;
    
    if (strcmp(file(ic_err,1:9),'*** ERROR') == 0)
        
        % Copy data into temp array
        
        eig_lines=file(ic_start:ic_end,:);
        
        % Correct each line for length
        
        eig_lines = my_adjust_eig(eig_lines);
        
        % Read each of the eigenvalue table lines
        
        nlines = size(eig_lines,1);
        neig=0;
        
        for iline=1:nlines   % Loop over the lines
            
            line=eig_lines(iline,:);     
            
            [im_lambda, err] = check_str(line(47:57));
            
            if (im_lambda >= 0)
                neig = neig+1;
                freq_hz(neig,ii) = check_str(line(71:83));
            end
            
        end
        
    else
        
    end
    
end

freq_cpm = freq_hz*60;

function lines2 = my_adjust_eig(lines1)

% The last character in each line is in column 127

nlines = size(lines1,1);

for iline=1:nlines
    sp = findstr(lines1(iline,:),' ');
    lastchr = size(lines1,2);
    csp = size(sp,2);
    while (lastchr == sp(csp))
        lastchr = lastchr-1;
        csp=csp-1;
    end
    fchar=121;
    if((lines1(iline,lastchr)== 'n') == 1)
        lines2(iline,1:fchar-lastchr-12) = ' ';
        lines2(iline,fchar-lastchr-12+1:fchar-12) = lines1(iline,1:lastchr);
        lines2(iline,fchar-12+1:fchar) = ' ';
    else
        lines2(iline,1:fchar-lastchr) = ' ';
        lines2(iline,fchar-lastchr+1:fchar) = lines1(iline,1:lastchr);
    end
    
end

function [num, err] = check_str(str);

stars = findstr(str,'*');
if isempty(stars) ~= 0
    
    num = str2num(str);
    err = 0;
    if length(num)~=1
        num = nan;
        err=1;
    end
else
    num = nan;
    err=1;
end

RE: How to parse strings character by character?

(OP)
Great!  Thank you, I took your examples and was able to develop code to do what I needed.  This will be very helpful in the future.  Thank you again.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Eng-Tips Forums free from inappropriate posts.
The Eng-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Eng-Tips forums is a member-only feature.

Click Here to join Eng-Tips and talk with other members!


Resources