fscanf not reading integers

16 views (last 30 days)
John
John on 30 Nov 2022
Answered: Walter Roberson on 30 Nov 2022
I have a text file food.txt:
Food Name Taste Eating Rating
1 Ham 8.4 1.8 0.25
2 Turkey 9.2 2 0.5
3 Chicken 8.2 1.75 0.25
4 Steak 8.4 1.25 0.25
5 Ribeye 8.6 1.75 0.08
6 Ribs 8.8 2.25 0.25
7 Pork 8.3 1.9 0.17
8 Fish 8.7 1.5 0.3
9 Tofu 8.5 1.5 0.25
10 Salad 8.5 1.6 0.17
I proceed to use integers=fscanf(food.txt,"i",1) but all that comes back is a []. What should I do to get back the first integer in this text file (I wantt the number 1 back).

Accepted Answer

Image Analyst
Image Analyst on 30 Nov 2022
You forgot to attach your text file!
But try this
t = readtable('food.txt');
integers = t.Food
  2 Comments
John
John on 30 Nov 2022
Hey, Thanks for the help. If I wanted to do it with fscanf though , how would I go about doing that?
This is the text file:
Image Analyst
Image Analyst on 30 Nov 2022
I guess you'd start by looking up the documentation if you wanted to do it the hard way. I played around with fscanf, sscanf, and textscan but couldn't get it working and it's not worth the trouble when a much simpler solution exists. But you're welcome to try.

Sign in to comment.

More Answers (1)

Walter Roberson
Walter Roberson on 30 Nov 2022
fscanf(food.txt,"i",1)
if food is not a defined variable at that point, then that would give you an error about undefined variable.
If food is defined but is not a struct or object, then that would give you an error about dot indexing not being supported for variables of that type.
If food is defined as a struct that does not have a field named txt then you would get an error Unrecognized field name "txt".
If food is defined as a scalar struct that has a field named txt then the food.txt would evaluate to whatever was stored there.
If food is defined as a nonscalar struct that has a field named txt then food.txt would be a structure expansion, and probably you would get an error from fscanf about too many inputs, or about invalid options.
If food is defined as an object but there is no txt method or property for that class, then you would get an error about Unrecognized method, property, or field 'txt' for class
If food is defined as an object that has a class or method txt then you would get whatever it happened to evaluate to.
If food is the result of food = importdata('food.txt') then food would be a struct, but it would have field names textdata and data but no field named txt . The textdata field would be a cell array of character vectors, and the data field would be a numeric array containing just the numbers.
The first parameter you pass to fscanf needs to be a file identifier, which is a non-negative integer. If the first parameter (so, whatever food.txt evaluated to) does not happen to be a scalar non-negative integer, you would get an error message "Invalid file identifier. Use fopen to generate a valid file identifier." . This includes cases where the user tries to pass a file name to fscanf() instead of a file identifier. You must use fopen() to open a file and pass the file identifier to fscanf() to use fscanf(). If you pass the integers 1 or 2 you will get a different error message, Operation is not implemented for requested file identifier. In most cases if you pass the integer 0 you will get that not-implemented message, but in some cases 0 just might work for reading data (I would have to test that obscure case to be certain.)
The second parameter to fscanf() must be a format character vector or string scalar object. Any text in the format that is not either whitespace or starting with a '%' character will be looked for literally -- so your format of 'i' tells MATLAB to look for the literal character i inside the file at the current location. If a literal character is found then the rest of the format will be processed; if the literal character is not found then the processing would end, and whatever was processed so far would be returned. Literal characters that are matched do not result in any output from fscanf(): they are "consumed" from the input stream. So if the file previously opened and whose file identifier had been stored in food.txt just happened to start with i then the "i" format would "consume" that i leaving the file positioned after it, but if it happens to start with any other character such as F then the fscanf() would fail at that point leaving the file positioned at the beginning of file.
If you were intending to read a number you would use a % followed by a conversion specification. %d would be used to indicate that a base 10 int32 number is to be read; %i would be used to indicate that an integer is to be read, but that the first characters of the input would be examined to determine whether the number was hexidecimal ( 0x or 0X ) or octal ( 0 not followed by x or X) or decimal (number does not start with 0). %f would be used for floating point numbers.
What should you do? Well, you should use readtable() . Or textscan(). But if for some reason you are commanded to use fscanf() then you would work like this:
inventory_numbers = [];
names = {};
stats = zeros(0,3);
fid = fopen('food.txt', 'r');
fgetl(fid); %read and discard the header line
counter = 0;
while ~feof(fid)
thisinvent = fscanf(fid, '%f', 1);
if isempty(thisinvent); break; end %reached end of file
counter = counter + 1;
inventory_numbers(counter) = thisinvent;
thisname = fscanf(fid, '%s', 1);
names{counter} = thisname;
thisstats = fscanf(fid, '%f%f%f', [1 3]);
stats(counter,:) = thisstats;
end
fclose(fid)

Tags

Community Treasure Hunt

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

Start Hunting!