How do I TRIM a character array in standard F77? - text

I'm reading from ASCII data files with text headers. (The headers contain info about the data run.) I want to add some of the columns of each data file, then write the result to another data file, but keep the headers for each of the files. The problem is, I don't know beforehand what the lengths of the header lines are. If I use a long character variable (character*400, for example) to make sure I get the entire header lines, then my new data files have lots of white space I don't want. Basically, I want to do TRIM(HeaderVariable), but TRIM is not available to me. Any suggestions? Is there a way to WRITE only to a CrLF? I thought of using an array of character*1, and testing each character as I read it and write it, but...wow, that's sooooo complicated. Is there a simpler way to do this in standard F77?
[edit: self-answer moved to answer. could not do it at first because rep was too low.]

I got the answer. Posting here to help others. The LENGTH function below is taken from http://www.star.le.ac.uk/~cgp/prof77.html#tth_sEc7 Once you've got this LENGTH function, it's trivial to implement your own TRIM function. Functionally, this isn't much different from my initial horrid idea, but it's prettier.
LEN The LEN function takes a character argument and returns its length as an integer. The argument may be a local character variable or array element but this will just return a constant. LEN is more useful in procedures where character dummy arguments (and character function names) may have their length passed over from the calling unit, so that the length may be different on each procedure call. The length returned by LEN is that declared for the item. Sometimes it is more useful to find the length excluding trailing blanks. The next function does just that, using LEN in the process.
INTEGER FUNCTION LENGTH(STRING) !Returns length of string ignoring trailing blanks
CHARACTER*(*) STRING
DO 15, I = LEN(STRING), 1, -1
IF(STRING(I:I) .NE. ' ') GO TO 20
15 CONTINUE
20 LENGTH = I
END

Related

why there is space in the string at SAS program (enterprise guide 8.3)

I write the code in SAS enterprise guide 8.3, and find there is space in the name of the file. Anyone knows why? please reference the attached screenshot for details. The space is after the character "Y_2021"; Thanks
year1 is being padded with spaces by the concatenation operator. It is a a better practice to use cats, catt, or catx rather than the || operator for concatenation. These functions ensure that the values being concatenated are not padded.
Use the code below instead.
csvfile_temp = cats('Y_', year1, '0101_', dateyyyymmdd, '.csv');
SAS has two types of variables. Floating point numbers and fixed length character strings.
You have not explicitly set the types or lengths of any of the variables, so SAS must decide how to define them based on how they are first used in the code. Since TODAY1 is getting the results of PUT() function using a format of width 8 it will be defined as length $8. And since they other variables are first seen as the result of functions operating on TODAY1 they will also be defined as length $8.
So the TRIM() function calls in your second and third assignment statement are doing nothing. It removes the trailing spaces and then stores the value back into a fixed length variable which means that value is padded out to 8 bytes again.
You could define the variables before using them.
length today1 $8 year1 $4 ;
You could also create the variables with statements that you are sure will cause SAS to define the length to what you need.
today = today();
year = put(today,year4.);
dateyyyymmdd = put(today,yymmddn8.);
If you do need to concatenate variables that could have short values then add the TRIM() function calls into the place where you need to trimmed values. Or better still use the CATS() function instead of the concatenation operator.

COBOL substring between two finite points

I understand that the string_variable(start:length) can be used to get a substring of a string given a starting point and substring length, however, I am finding that I often need to get a substring between a 'start' and 'end' point.
While I know I could always do this:
SUBTRACT start FROM end GIVING len
string(start:len)
It seems cumbersome to have to do so every time when I am writing programs that use this functionality often. Is there perhaps a quicker/built-in way of achieving this?
How about?
move str (start-pos : end-pos - start-pos + 1) to ...
You can subtract the first from the last, but you need to add 1 to get the correct length.
STRING is a statement name, as is START, and END is reserved. LENGTH is a function name. I avoid those in anything that looks like code.

Converting character to real fails if character consists of an integer (i.e. without dot)

I am reading a text file with my fortran code. I parse the text file (which contain a bunch of stuff such as names and numbers) and I end up with strings containing real number (they are real time measuraments) such as:
string = 1.34
I simply write this string in a real number by doing
read(levelCHAR,'(f)') level
And everything worked great for a month until today, when the number in the input file was exactly 1 and I had:
string = 1
and the read statement above gave me
level=0
Therefore to fix this I added before the read statement:
if (index(string ,'.')<=0) then
string = trim(string )//'.'
endif
And this seems to have fixed the issue. However, I wanted to know if I am missing something and there is a more elegant way to do this in one line for example by replacing the format '(f)' in the read statement with a more suitable expression.
Your program is not valid Fortran:
read(levelCHAR,'(f)') level
1
Error: Nonnegative width required in format string at (1)
form.f90:5.5:
You must indicate the input field with such as f5.0. Or you can use the list-directed input read(levelChar,*) level.
Also, be sure to use the .0 and not any other number in the fw.d descriptor for input. Otherwise strange results are to be expected for integer inputs as they will be multiplied by 10**(-d).

need guidance with basic function creation in MATLAB

I have to write a MATLAB function with the following description:
function counts = letterStatistics(filename, allowedChar, N)
This function is supposed to open a text file specified by filename and read its entire contents. The contents will be parsed such that any character that isn’t in allowedChar is removed. Finally it will return a count of all N-symbol combinations in the parsed text. This function should be stored in a file name “letterStatistics.m” and I made a list of some commands and things of how the function should be organized according to my professors' lecture notes:
Begin the function by setting the default value of N to 1 in case:
a. The user specifies a 0 or negative value of N.
b. The user doesn’t pass the argument N into the function, i.e., counts = letterStatistics(filename, allowedChar)
Using the fopen function, open the file filename for reading in text mode.
Using the function fscanf, read in all the contents of the opened file into a string variable.
I know there exists a MATLAB function to turn all letters in a string to lower case. Since my analysis will disregard case, I have to use this function on the string of text.
Parse this string variable as follows (use logical indexing or regular expressions – do not use for loops):
a. We want to remove all newline characters without this occurring:
e.g.
In my younger and more vulnerable years my father gave me some advice that I've been turning over in my mind ever since.
In my younger and more vulnerableyears my father gave me some advicethat I’ve been turning over in my mindever since.
Replace all newline characters (special character \n) with a single space: ' '.
b. We will treat hyphenated words as two separate words, hence do the same for hyphens '-'.
c. Remove any character that is not in allowedChar. Hint: use regexprep with an empty string '' as an argument for replace.
d. Any sequence of two or more blank spaces should be replaced by a single blank space.
Use the provided permsRep function, to create a matrix of all possible N-symbol combinations of the symbols in allowedChar.
Using the strfind function, count all the N-symbol combinations in the parsed text into an array counts. Do not loop through each character in your parsed text as you would in a C program.
Close the opened file using fclose.
HERE IS MY QUESTION: so as you can see i have made this list of what the function is, what it should do, and using which commands (fclose etc.). the trouble is that I'm aware that closing the file involves use of 'fclose' but other than that I'm not sure how to execute #8. Same goes for the whole function creation. I have a vague idea of how to create a function using what commands but I'm unable to produce the actual code.. how should I begin? Any guidance/hints would seriously be appreciated because I'm having programmers' block and am unable to start!
I think that you are new to matlab, so the documentation may be complicated. The root of the problem is the basic understanding of file I/O (input/output) I guess. So the thing is that when you open the file using fopen, matlab returns a pointer to that file, which is generally called a file ID. When you call fclose you want matlab to understand that you want to close that file. So what you have to do is to use fclose with the correct file ID.
fid = open('test.txt');
fprintf(fid,'This is a test.\n');
fclose(fid);
fid = 0; % Optional, this will make it clear that the file is not open,
% but it is not necessary since matlab will send a not open message anyway
Regarding the function creation the syntax is something like this:
function out = myFcn(x,y)
z = x*y;
fprintf('z=%.0f\n',z); % Print value of z in the command window
out = z>0;
This is a function that checks if two numbers are positive and returns true they are. If not it returns false. This may not be the best way to do this test, but it works as example I guess.
Please comment if this is not what you want to know.

MIPS: Check how many alphabetic characters are in a string

Right now I'm trying to load a null-terminated string and return the number of alphabetic characters that are in that string. Currently I have three functions: the Main, countAlpha (which is intended to count the number of characters), and isAlpha, which determines whether the character is alphabetic or not. I would like some help with my algorithm.
So, for my Main I load the string, jump and link to countAlpha, and then load the syscall commands to print int and exit the program.
For my countAlpha, which I am having trouble with, I want to create a for loop that goes through each character in the string and if isAlpha returns a 1 (indicating that the character is alphabetic), then increase the count.
isAlpha is straightforward-just determine if the character is between specific numbers in ASCII.
So I guess my question is how do I attack countAlpha. Thanks for your help. (Note: I don't want actual code, just tips and hints)
Sounds like you want to test a return value / register for the call to isAlpha and add/increment a seperate register/count var everytime the test is true. Or you could just add the return value directly to your count register every time through the loop if the value is returned as a 0 or 1. Then, just setup your loop to keep going until the current character is a '\0' char. Then your count register holds your final value.
Is this in-depth enough to help you out?

Resources