Clear Filters
Clear Filters

Can I assign a value from textscan to anything other than a cell array?

11 views (last 30 days)
I want to assign the value from a textscan directly to an simple variable, can I do this? Example:
str = '223 87 87';
[Nx, Ny, Nz] = textscan(str, '%f %f %f');
I know this doesn't work, because textscan returns a cell array, rather than a list of numbers. So I could do something like
Narray = textscan(str, '%f %f %f');
Nx = Narray{1}; Ny = Narray{2}; Nz = Narray{3}; clear Narray;
But then it takes two lines and an extra cell array that I never wanted to exist in the first place...it seems inefficient and less readable. Is there a way that I can have the output from textscan assigned directly to the variables I want, or is an intermediate cell array always necessary? Thanks!
  1 Comment
per isakson
per isakson on 22 Mar 2016
Short answer: NO!
textread did that
[A,B,C, ...] = textread('FILENAME','FORMAT')
However, "Note: textread is not recommended. Use textscan instead."

Sign in to comment.

Accepted Answer

dpb
dpb on 22 Mar 2016
Edited: dpb on 24 Mar 2016
The insistence of textscan to return only cell array is annoying often, indeed. Only way around what you're doing I'm aware of is to not generate the three separate variables but use an array instead--then you can at least eliminate the explicit temporary
>> Nxyz=cell2mat(textscan(str,'%f'))
Nxy =
223
87
87
>>
If you're not reading a string but a file, I often still revert to textread for the same reason; in that case you can have the multiple outputs as well.
ADDENDUM
It seems one should be able to deal the outputs, but I couldn't manage to force textscan to generate a comma-separated list without the explicit temporary so ended up with the array propagated over the three variables instead of the three elements distributed. But, it might be some better than the explicit evaluation...
>> C=textscan(str,'%f%f%f')
C =
[223] [87] [87]
>> [Nx Ny Nz]=deal(C{1,:})
Nx =
223
Ny =
87
Nz =
87
>>
The difficulty here is that one must use a counted format string to force the creation of the cell array of N elements instead of the single cell of an N-sized array. And, since there's no syntax for array or cell array access after a function, the explicit temporary must be available for the dereferencing expression since
>> [Nx Ny Nz]=deal(textscan(str,'%f%f%f'))
Nx =
[223] [87] [87]
Ny =
[223] [87] [87]
Nz =
[223] [87] [87]
>>
as previously noted which is same result as is
>> [Nx Ny Nz]=deal(C)
The latter seems an incorrect choice for the implementation of deal to me but is as documented.
ADDENDUM
"The difficulty here is that one must use a counted format string ..."
Actually, it just dawned on me in thinking over Walter's most-excellent addition of dealcell that the facility of textscan to automagically parse the input record and return the proper number of elements if the formatSpec field is the empty string comes into play here...I think the best end solution is then
[Nx Ny Nz]=dealcell(textscan(str,''));
  3 Comments
dpb
dpb on 23 Mar 2016
@Walter -- I had thought I'd read/heard that Octave had addressing facilities after a function reference but a look-see at the doc's didn't reveal it if so...I'm sure it'd be a nightmare to implement but have often wished could make such references to save the temporaries hanging around...

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 23 Mar 2016
I agree it's annoying that textscan() is not very flexible. You can use cell2mat() to put it all into one array:
N = cell2mat(textscan(str, '%f %f %f'))
You can then split N up into 3 separate individual variables if you want, or use it conveniently as an array.
  6 Comments
Emily
Emily on 30 Mar 2016
Thanks for your help Walter and dpb. Would you be willing to explain this answer to me a bit? I don't understand what the line
dealcell = @(C) deal(C{:});
does. And I assume it is not the same C as in the addendum, but C is somehow a new variable, that doesn't exist before this command?
Finally, if this is a better answer, is it possible for me to unaccept the first answer so this can be recorded as the correct answer?
dpb
dpb on 30 Mar 2016
The line is defining an "anonymous function" assigned to the "function handle" dealcell. C is the dummy argument to the function and is simply a placeholder for the actual argument that will be used when the function is invoked.
Read up on anonymous functions and function handles to get the full scoop but essentially it creates a named function programmatically inline that can be used just as if there were an m-file of the same name containing the same code. Exception being that it only exists for the scope and duration of the program unit in which it is defined (or to which the handle is passed as an argument but that's more than need to get into here).
I already edit'ed the ACCEPT'ed Answer in the ADDENDUM to incorporate what I thought the best solution would be using the anonymous function so it's already been accepted. :) Although I didn't replicate the anonymous function definition therein; I simply referred to it as Walter's baby... :) But, you need both it and the subsequent line that uses it to get the end result; the function definition by itself does nothing useful (well, it creates the function handle, but nothing happens until it is subsequently invoked).

Sign in to comment.

Categories

Find more on Data Import and Export in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!