CaptainProg
CaptainProg

Reputation: 5690

Multi-line fprintf() using one element from each array per line

I've hit some unexpected behaviour using the fprintf() function in MATLAB. I'm trying to print a multi-line file using the contents of a cell array and a numerical array. I know that I can use the fprintf() function as follows to print out the contents of a cell array:

myCellArray = {'one','two','three'};
fprintf('%s\n',myCellArray{:})

This results in the following output:

one
two
three

I can also print out a numerical array as follows:

myNumericalArray = [1,2,3];
fprintf('%i\n',myNumericalArray)

This results in:

1
2
3

However, the weird behaviour appears if I try to mix these, as follows:

fprintf('%s is %i\n',myCellArray{:},myNumericalArray)

This results in:

one is 116
wo is 116
hree is 1

I think this happens because MATLAB tries to print the next entry in myCellArray in the place of the %i, rather than using the first entry in myNumericalArray. This is evident if I type the following:

fprintf('%s %s\n',myCellArray{:},myCellArray{:})

Which results in:

one two
three one
two three

...Is there some way to ensure that only one element from each array is used per line?

Upvotes: 3

Views: 1244

Answers (3)

Luis Mendo
Luis Mendo

Reputation: 112659

This is similar to the loop solution, only more compact:

arrayfun(@(c,n) fprintf('%s is %i\n', c{1}, n), myCellArray, myNumericalArray)

Upvotes: 1

obchardon
obchardon

Reputation: 10792

fprintf(formatSpec,A1,...,An) will print all the element of A1 in column order, then all the element of A2 in column order... and size(A1) is not necessarily equal to size(A2).

So in your case the easiest solution is IMO the for loop:

for ii = 1:length(myCellArray)
   fprintf('%s is %d\n',myCellArray{ii},myNumericalArray(ii))
end

For the small explanation foo(cell{:}) is similar to the splat operator (python, ruby,...) so matlab will interpret this command as foo(cell{1},cell{2},...,cell{n}) and this is why your two arguments are not interpreted pair-wise.

Upvotes: 2

HansHirse
HansHirse

Reputation: 18895

I agree with your idea. So, I could only think of circumventing this by creating a combined cell array with alternating values from your two initial arrays, see the following code:

myCombinedArray = [myCellArray; mat2cell(myNumericalArray, 1, ones(1, numel(myNumericalArray)))];
fprintf('%s is %i\n', myCombinedArray{:})

Gives the (I assume) desired output:

one is 1
two is 2
three is 3

Upvotes: 3

Related Questions