text file I/O

47 views (last 30 days)
asad jaffar
asad jaffar on 20 Apr 2019
Edited: Jan on 19 Jan 2023
Write a function called char_counter that counts the number of a certain character in a text file. The function takes two input arguments, fname, a char vector of the filename and character, the char it counts in the file. The function returns charnum, the number of characters found. If the file is not found or character is not a valid char, the function return -1. As an example, consider the following run. The file "simple.txt" contains a single line: "This file should have exactly three a-s..."
charnum = char_counter('simple.txt','a')
charnum =
3
function charnum = char_counter(fname,character)
fid=fopen(fname);
if fid< 0
charnum = -1;
return;
end
if strcmp(character,'')==1
charnum=0;
return;
end
if double(character)>=35 && double(character)<=43 && double(character) ~=39 && double(character) ~= 41 && double(character) ~= 40
charnum = 0;
return;
end
if double(character) >=60 && double(character) <=64 && double(character) ~= 63
charnum = 0;
return;
end
if double(character) == 81 || double(character) == 88 || double(character) == 90
charnum = 0;
return;
end
cc = fgets(fid);
sumv=0;
while ischar(cc)
z = sprintf('%s',cc);
k = strfind(z,character);
sumv = sumv + length(k);
cc = fgets(fid);
end
charnum = sumv;
if charnum == 0
charnum =-1;
return;
end
can you guys tell whats wrong with this code?
  4 Comments
Ramesh Patel
Ramesh Patel on 15 Jul 2021
Edited: Ramesh Patel on 15 Jul 2021
function charnum = char_counter(fname,character)
fid = fopen(fname,'rt');
if fid<0|| ~ischar(character)
charnum=-1;
else
charnum=0;
oneline = fgets(fid);
while ischar(oneline)
n = strfind(oneline,character);
charnum = charnum + length(n);
oneline = fgets(fid);
end
end
end
%this is simplest code and having no error
Walter Roberson
Walter Roberson on 15 Jul 2021
Your code does fopen() but no fclose(), and so does have an error.

Sign in to comment.

Answers (17)

Jiaqi Liu
Jiaqi Liu on 3 Sep 2019
function charnum = char_counter(frame,character)
fid = fopen(frame,'r');
if fid < 0
charnum = -1;
return
end
if ischar(character) == 0
charnum = -1;
return
end
inhalt = fscanf (fid, '%c');
charnum = count(inhalt,character);
end
  2 Comments
Aniket Bordekar
Aniket Bordekar on 15 Sep 2020
Why is %c used?
Walter Roberson
Walter Roberson on 15 Sep 2020
fscanf() without a count asks MATLAB to read as far as possible in the file that still matches the given format. The format given is %c, which matches any one character, and since every byte stored in the file can be interpreted as a character, the result of using fscanf with '%c' format and no count, is to read the entire rest of the file one character at a time.
... Some day I should test with R2020a or later, and a byte stream that does not represent valid UTF8, to see whether %c would stop reading at that point...

Sign in to comment.


Muhammad Sadiq
Muhammad Sadiq on 7 May 2020
Edited: Muhammad Sadiq on 7 May 2020
function charnum = char_counter(frame,character)
fid = fopen(frame,'r');
if fid < 0
charnum = -1;
return
end
if ischar(character) == 0
charnum = -1;
return
end
inhalt = fscanf (fid, '%c');
charnum = count(inhalt,character);
end
  3 Comments
THIERNO AMADOU MOUCTAR BALDE
perfect Thank sir
Walter Roberson
Walter Roberson on 30 Dec 2020
This code fails to fclose(fid) under any circumstances.

Sign in to comment.


Fazlul Haque
Fazlul Haque on 15 May 2020
done with fgets and while loops
  1 Comment
Walter Roberson
Walter Roberson on 15 May 2020
If the file is valid but charv is not a character, then you leave the file open when you return.
We recommend against using sum as the name of a variable: it is very common to get confused and also want to use sum() as the name of the summation function in the same code where you use sum as a variable.

Sign in to comment.


Akshay Dengwani
Akshay Dengwani on 24 Dec 2020
function charnum = char_counter(fname,charac)
fid = fopen(fname, 'rt');
if fid < 0
charnum = -1;
return
end
line = fgets(fid);
su = 0;
while ischar(line)
lo = line == charac;
su = su + sum(lo(:));
line = fgets(fid);
end
if double(charac)>127 || double(charac)<0 || ~ischar(charac);
charnum = -1;
else
charnum = su;
end
end
  4 Comments
SOUMYAJIT MONDAL
SOUMYAJIT MONDAL on 2 Sep 2021
Please explain
In the line sum(line==charac) , what does line==charac means ?
Walter Roberson
Walter Roberson on 2 Sep 2021
fread() with '*char' and inf size will cause fread() to return a character vector that contains all remaining characters in the file. Those will be stored in the variable named line
Character vectors are (for most purposes) stored as arrays of 16 bit integers that are unicode code points. Unicode is an international standard that gives a specific ordering to lots and lots of characters and symbols; https://home.unicode.org/ . For example the character 'A' is stored as 16 bit integer with value 65. They really are numeric internally (together with a flag that says that the numeric values represent characters.)
The == operator is the equality test operator. In this context, == is used to compare the character codes (integer) used to represent the data in the line variable, to the character code that is used to represent the character that is stored in charac which is known to be a single character. So internally you have a numeric vector ('line') being compared to a numeric scalar ('charac') . The result of comparing a vector and a scalar is defined by MATLAB to be a logical vector, in which the value is false for each place the comparison failed, an true for each place the comparison succeeded. So the output of == is a logical vector the same length as the variable line .
What you need to know after that point is that logical false is represented by numeric value 0, and logical true is represented by the numeric value 1. Because of that, when you want to know how many locations the comparison held at, you can sum() the vector, which contributes 1 to the sum for every true and the result at the end is going to be the number of places the comparison was true.
So what will be stored in su is the number of places a character in the variable line was the same as the character in the variable charac .

Sign in to comment.


Pranav Mishra
Pranav Mishra on 8 Jun 2020
function charnum = char_counter(fname,character)
fid = fopen(fname,'rt');
if (fid < 0)
charnum = -1;
return;
end
if (ischar(character) ==0)
charnum = -1;
else
c = 0;
oneline = fgets(fid);
while ischar(oneline)
character_line = char(oneline);
[a b] = size(strfind(character_line,character));
c = c + b;
oneline = fgets(fid);
end
charnum = c;
end
fclose(fid);
end
  1 Comment
Walter Roberson
Walter Roberson on 8 Jun 2020
Note that the result of fgets() is already a character vector (unless end of file), so you do not need to use char() on oneline.

Sign in to comment.


Hari Kiran Tirumaladasu
Hari Kiran Tirumaladasu on 21 Jun 2020
function charnum = char_counter(fname,character)
fid = fopen(fname,'r');
if fid < 0 || ischar(character) == 0
charnum = -1;
error('The file entered is either incorrect or the character entered could not be found');
return;
end
incount = fscanf(fid,'%c');
charnum = count(incount,character);

Adityesh Satam
Adityesh Satam on 23 Jul 2020
I was able to get all correct using this code:
function charnum = char_counter(fname,character)
fid = fopen(fname,'rt');
charnum = 0;
ii = 0;
if fid < 0
charnum = -1;
return;
end
if ischar(character) == 0
charnum = -1;
end
% Reading a file one line at a time
one_line = fgets(fid);
while ischar(one_line)
for ii = 1:length(one_line)
if strcmp(one_line(ii),character) && ischar(character)
charnum = charnum + 1;
end
end
one_line = fgets(fid);
end
fclose(fid);
end
  1 Comment
Walter Roberson
Walter Roberson on 23 Jul 2020
If the character parameter is not a valid parameter, you go ahead and read the file anyhow, but each time testing again that ischar(character) is true. That is a waste of time. If ischar(character) is false then do not bother reading the file.

Sign in to comment.


Walter Roberson
Walter Roberson on 20 Apr 2019
We already explained. If you are passed something that is a character but the character is not found in the file then you need to return 0 not -1. Only return -1 if the file does not exist or what you are passed is not character data type.
  2 Comments
asad jaffar
asad jaffar on 20 Apr 2019
@walter roberson can you tell me the line number where i have to return 0 and not -1 , i mean to say at which line do i have to make changes?
Walter Roberson
Walter Roberson on 20 Apr 2019
Line 33.

Sign in to comment.


Arup Kumar Debnath
Arup Kumar Debnath on 1 Jun 2020
I was trying to answer this question. But i stuck there, Can any one help me and find the fault in this code?
Disclaimer= I am a noob here.
function charnum=char_counter(fname,character)
fid=fopen(fname,'rt');
if fid<0
error('error opening file\n');
charnum=-1;
return;
end
total=fgets(fid);
ii=1;
a=size(total);
charnum=0;
while ii<=a
if total(ii)=='character';
charnum=charnum+1;
else
ii=ii+1;
end
end
  1 Comment
Walter Roberson
Walter Roberson on 1 Jun 2020
Edited: Walter Roberson on 1 Jun 2020
you do not validate that the second input is a character.
You are comparing the input to the literal character vector ['c' 'h' 'a' 'r' 'a' 'c' 't' 'e' 'r'] instead of to what the input variable named character holds.
You are not incrementing ii if the comparison is true.

Sign in to comment.


SHASHANK SINGH
SHASHANK SINGH on 7 Jun 2020
function charnum = char_counter(fname, character)
fid = fopen(fname,'r');
if fid < 0 || ischar(character) == 0
charnum = -1;
return
end
inhalt = fscanf(fid, '%c');
charnum = count(inhalt, character);
end
  3 Comments
Jobin Geevarghese Thampi
Jobin Geevarghese Thampi on 18 Feb 2021
@Walter Roberson what happens when we doesnt write 'return'. i havent understood about return function could you explain me?
Walter Roberson
Walter Roberson on 20 Feb 2021
When return is encountered, MATLAB leaves the function and goes back to the place it was called, exactly the same as if MATLAB had reached the end of the function. It does not execute any more code in the function.
In the code that Shashank Singh posted, if the return had not been there, then after charnum was assigned -1, the code would continue on after the if , and so the code would attempt to do the fscanf(). But if the fid was < 0 indicating the file could not be opened, then fscanf(fid) would be an error and the function would crash.
It is always possible to rewrite code that uses return to not use return, but it can be messy to do so. In the case of the above code it could be instead written as
function charnum = char_counter(fname, character)
fid = fopen(fname,'r');
if fid < 0 || ischar(character) == 0
charnum = -1;
else
inhalt = fscanf(fid, '%c');
charnum = count(inhalt, character);
end
end
which is not bad at all in this case. But consider proper checking of ischar():
function charnum = char_counter(fname, character)
if ischar(character) == 0
charnum = -1;
else
fid = fopen(fname,'r');
if fid < 0
charnum = -1;
else
inhalt = fscanf(fid, '%c');
charnum = count(inhalt, character);
end
end
end
and compare that to the same with return:
function charnum = char_counter(fname, character)
if ischar(character) == 0
charnum = -1;
return
end
fid = fopen(fname,'r');
if fid < 0
charnum = -1;
return
end
inhalt = fscanf(fid, '%c');
charnum = count(inhalt, character);
end
Notice that using return the code is more compact and does not need as many if/else levels.

Sign in to comment.


Ujjawal Barnwal
Ujjawal Barnwal on 8 Jun 2020
function charnum = char_counter(fname,character)
fid = fopen(fname,'rt');
charnum = 0;
if fid < 0 || ~ischar(character)
charnum = -1;
return;
end
oneline = fgets(fid);
while ischar(oneline)
a=length(findstr(oneline,character));
charnum = charnum + a;
oneline = fgets(fid);
end
fclose(fid);
end
  1 Comment
Walter Roberson
Walter Roberson on 12 Jun 2020
If the fname is valid but character is not a character, then you leave the file open when you return.

Sign in to comment.


Sachin Patare
Sachin Patare on 27 Sep 2020
function charnum=char_counter(fname,character)
fid=fopen(fname,'rt');
if fid<0
charnum=-1;
return
end
x=fileread(fname);
if ischar(character)==1
a=findstr(x,character);
b=size(a);
charnum=b(1,2);
else
charnum=-1;
end
  3 Comments
Jan
Jan on 27 Sep 2020
If you use fileread, you can omit the fopen. If you use fopen, do not forget to close the file with fclose.
numel() is easier than getting the 2nd output from size. ischar replies a logical already, so there is no need to compare it with "== 1".
findstr is deprecated for more than 10 years now. Use strfind instead.
function charnum=char_counter(fname, character)
charnum = -1; % Default value
if exist(fname, 'file') == 2 % Check existence of file
s = fileread(fname);
if ischar(character) && isscalar(character)
charnum = sum(s == character);
% Or charnum = numel(strfind(s, character));
end
end
Walter Roberson
Walter Roberson on 28 Sep 2020
The one advantage of testing the fopen() over testing file existence with exist, is that fopen() will fail smoothly if the file exists but you do not have permission to read it, or the file exists but it is locked so you cannot read it at the moment. In either of those cases, fileread() would generate an exception that would have to be handled with a try/catch to replicate the fopen() ability to detect that the file cannot be read.

Sign in to comment.


Sumanth Bayya
Sumanth Bayya on 19 Oct 2021
function charnum=char_counter(fname,character)
fid=fopen(fname,'rt');
charnum=0;
ii=0;
if fid<0
charnum=-1;
return
end
if ischar(character)==0
charnum=-1;
end
one_line=fgets(fid);
while ischar(one_line)
for ii=1:length(one_line)
if strcmp(one_line(ii),character)&& ischar(character)
charnum=charnum+1;
end
end
one_line=fgets(fid);
end
fclose(fid);
end
  4 Comments
Walter Roberson
Walter Roberson on 19 Oct 2021
If you look at the right hand side of the "Insert" controls, the blob to the right of the paperclip is the "Code examples" button. It allows you to insert formatted code that is not executed if you "Run".
This is one of the facilities carried over from LiveScript. In the context of LiveScript it makes more sense that there would be cases where you need a block of code to be formatted but not executable.
Jan
Jan on 20 Oct 2021
Edited: Jan on 20 Oct 2021
% I got it. Thanks, Walter

Sign in to comment.


Milad Mehrnia
Milad Mehrnia on 1 Nov 2021
function charnum = char_counter(fname,c)
fid = fopen(fname,'rt');
charnum = 0;
if ~ischar(c)
charnum = -1;
elseif fid < 0
charnum = -1;
else
line = fgets(fid);
while ischar(line)
for i = 1:length(line)
if line(1,i) == c
charnum = charnum + 1;
end
end
line = fgets(fid);
end
fclose(fid);
end
end
  1 Comment
Walter Roberson
Walter Roberson on 1 Nov 2021
In the case where the file exists and is readable, but the user entered something that was not a character for the second parameter, then you open the file but you do not close it.

Sign in to comment.


Duong Nguyen
Duong Nguyen on 13 Mar 2022
Edited: Duong Nguyen on 13 Mar 2022
function charnum = char_counter(fname,character)
fid = fopen(fname, 'rt');
charnum = 0;
if fid<0||~(ischar(character))
charnum = -1;
return
end
%if you not use 'return' the while loop below will assign charnum = 0;
oneline = fgets(fid);
while ischar(oneline)
[~,temp] = size(strfind(oneline,character));
charnum = charnum + temp;
oneline = fgets(fid);
end
fclose(fid);
  1 Comment
Walter Roberson
Walter Roberson on 13 Mar 2022
In the case where the file exists and is readable, but the user entered something that was not a character for the second parameter, then you open the file but you do not close it.

Sign in to comment.


Zia Ur Rehman
Zia Ur Rehman on 1 Sep 2022
Hi folks,
please check my code and suggest me if I can improve this
function charnum = char_counter(fname,character)
fid = fopen(fname,'rt'); % opening the text named(fname) file to read(rt)
if fid<0 || ~ischar(character) % checking the existance of file and checking if second argument of char_counter is valid char
%fprintf('Error opening file %s\n\n',fname);
charnum = -1;
return;
end
charnum=0;
oneline = fgets(fid); % reading 1st line using 'fgets'
while ischar(oneline)
for i = 1:length(oneline) % loop for traversing through each char of the line
b = strcmp(oneline(i),character); % comparing ith char with 2nd argument(character)
if b
charnum= charnum+1; % if we find the char then add 1
end
end
oneline = fgets(fid); %reading the next line and returned to online
end
fclose(fid); % closing the file
end
  6 Comments
Jan
Jan on 3 Sep 2022
@Zia Ur Rehman: If you use fileread, there is no need to open the file with fopen before.
You can simplify:
b = strcmp(file_text(i),character); % comparing ith char with 2nd argument(character)
if b
charnum= charnum+1; % if we find the char then add 1
end
to
charnum = charnum + strcmp(file_text(i),character);
strcmp replies true or false, which is converted to 1 or 0.
But you can avoid the loop: file_text == character replies a vector of 0 and 1 also. Then sum() counts the matchs.
See also: isfile, fileread. Then 6 lines of code solve the problem.
Zia Ur Rehman
Zia Ur Rehman on 4 Sep 2022
ok ok, i will try this, thanks a lot

Sign in to comment.


Rahim Ullah
Rahim Ullah on 18 Jan 2023
your code looks lengthy and complex please try this one
function charnum=char_counter(fname,character)
fid=fopen(fname,'rt'); %file open
if fid<0 %check if the file open correctly or not
fprintf('file cant be open')
charnum=-1; %in case file is not opened due to any reason
return
end
file_content=fileread(fname); % reads the file contents and store it as a string
charnum=sum(file_content==character); %sum all the matching characters found in the strings
if ischar(character)==0 %check for valid character
charnum=-1;
return
end
  5 Comments
Rahim Ullah
Rahim Ullah on 19 Jan 2023
So should I delete my answer now ???
Jan
Jan on 19 Jan 2023
Edited: Jan on 19 Jan 2023
@Rahim Ullah: Your answer is a valid contribution concerning Matlab and does not violate the policies. Therefore the editors will not remove it.
I'd insert an fclose(fid) or use isfile() instead. But this is your contribution. Feel free to do, what you like.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!