Question about sprintf not handling list{:} properly

7 views (last 30 days)
Hi,
I have a few weird bugs trying to use sprintf on arrays. I've made a toy example of each. Can y'all see what I'm doing wrong? I'm so confused.
1)
X = ["a","b","c"]
Y = [1, 2, 3]
catinated = [X;Y]
a = sprintf("(%s,%d) \n",catinated{:})
When I run this, I get:
>> a =
"(a,49)
(b,50)
(c,51)
"
Y is an array of doubles, so %d should be fine... why is it 49 50 51 instead of 1 2 3?
2) Even weirder - sometimes I this will get rid of the first letter of my string:
X = ["abcd","efgh","i j k l", "m_n_o_p"];
Y = [12.34,56.78,91.01,23.45];
cat = [X;Y];
a = sprintf("%s, %d ", cat{:})
returns
a =
"abcd, 49
2.34, 101
fgh, 53
6.78, 105
j k l, 57
1.01, 109
_n_o_p, 50
3.45, "
So... these numbers are weird and (i think) mixing the askii of characters and cutting the first character from the next line.... and the very last string is just dropped? IDK I'm pretty new to matlab.
For reference,
cat =
2×4 string array
"abcd" "efgh" "i j k l" "m_n_o_p"
"12.34" "56.78" "91.01" "23.45"
At the end of the day, I really wanted an array of each of these combinations as strings, but i found this while trying to do that. Imagine if i wanted my output to be a list like [" A 1", "B 2", "C 3"] - would I have to build it in a for loop or is there a nice way to do this by mashing the string and int array together?
Thanks!

Accepted Answer

Walter Roberson
Walter Roberson on 2 May 2025
X = ["a","b","c"]
X = 1x3 string array
"a" "b" "c"
Y = [1, 2, 3]
Y = 1×3
1 2 3
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
catinated = [X;Y]
catinated = 2x3 string array
"a" "b" "c" "1" "2" "3"
Look carefully at the output and notice that it is a string array. The numeric 1 2 3 has been converted to "1" "2" "3"
a = sprintf("(%s,%d) \n",catinated{:})
a =
"(a,49) (b,50) (c,51) "
then the "a" gets converted as a string but the "1" is no longer numeric and in %d format gets converted to "code points" as (0+char("1")) which is double precision 49
0 + '1'
ans = 49
Your error was in putting the two parts together using the concatenation operator [] . Concatenating a string array and a numeric array results in the numeric array being formatted as strings.
X1 = num2cell(X)
X1 = 1x3 cell array
{["a"]} {["b"]} {["c"]}
Y1 = num2cell(Y)
Y1 = 1x3 cell array
{[1]} {[2]} {[3]}
catinated1 = [X1; Y1]
catinated1 = 2x3 cell array
{["a"]} {["b"]} {["c"]} {[ 1]} {[ 2]} {[ 3]}
a1 = sprintf("(%s,%d) \n",catinated1{:})
a1 =
"(a,1) (b,2) (c,3) "
  2 Comments
Walter Roberson
Walter Roberson on 2 May 2025
X = ["abcd","efgh","i j k l", "m_n_o_p"];
Y = [12.34,56.78,91.01,23.45];
cat = [X;Y]
cat = 2x4 string array
"abcd" "efgh" "i j k l" "m_n_o_p" "12.34" "56.78" "91.01" "23.45"
Look closely and see that you have generated a string array -- again the numeric part has been formatted as string. When you sprintf() with a '%s,%d' format, the first "abcd" gets converted with that %s format. Then the "12.34" gets interpreted as the vector ['1' '2' '.' '3' '4] and the %d converts the first element of the vector to 49 for the same reason as above (because '1' is char(49)) . That leaves the ['2' '.' '3', '4'] in the buffer to be converted by the %s format. Then the "efgh" gets intepreted as ['e' 'f' 'g' 'h'] and the first element of that, 'e' gets interpreted by the %d format, leaving ['f' 'g' 'h'] in the buffer to be interpreted by the %s format...
You have the same basic problem as before, that the numeric elements are being formatted as string when you do the [] operator.
It is not possible to have a single basic array in which some of the elements are string entries but other elements are numeric -- for that you need a cell array.
X = {"abcd","efgh","i j k l", "m_n_o_p"}
X = 1x4 cell array
{["abcd"]} {["efgh"]} {["i j k l"]} {["m_n_o_p"]}
Y = {12.34,56.78,91.01,23.45}
Y = 1x4 cell array
{[12.3400]} {[56.7800]} {[91.0100]} {[23.4500]}
cat = [X;Y]
cat = 2x4 cell array
{["abcd" ]} {["efgh" ]} {["i j k l"]} {["m_n_o_p"]} {[12.3400]} {[56.7800]} {[ 91.0100]} {[ 23.4500]}
a = sprintf("%s, %d ", cat{:})
a = "abcd, 1.234000e+01 efgh, 5.678000e+01 i j k l, 9.101000e+01 m_n_o_p, 2.345000e+01 "
Notice, by the way, the formatting mess you get from trying to convert floating point numbers such as 12.34 with a %d format.
Walter Roberson
Walter Roberson on 2 May 2025
Edited: Walter Roberson on 2 May 2025
For the last part, it is easy:
X = ["a","b","c"]
X = 1x3 string array
"a" "b" "c"
Y = [1, 2, 3]
Y = 1×3
1 2 3
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
X + " " + Y
ans = 1x3 string array
"a 1" "b 2" "c 3"
or
compose("(%s,%d)", X(:), Y(:))
ans = 3x1 string array
"(a,1)" "(b,2)" "(c,3)"

Sign in to comment.

More Answers (0)

Categories

Find more on Characters and Strings 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!