1
votes

Thank you all again for the help yesterday, I appreciate it. But I still have some issues with my MatLab programming.

Background

I have a lengthy string (200k+ chars) that I need to parse. It's all in Hex and I need to get MatLab to plot it. I'm trying to break down the steps. I need to put a '\t' (tab char) every 4 chars in this string.

Lets forget what i really need to do for now, though. Lets focus on something more general. Say my string is:

abcdefghijklmnopqrstuvwxyz

and I want MatLab to output:

abcd efgh ijkl mnop qrst uvwx yz

My pitiful attempts

for k = 4:length(Vader)
    Vader = horzcat(Vader(1:k), ' ', Vader(k+1:end))
    k= k+5;
end
Vader

This outputs:

abcd                         efghijklmnopqrstuvwxyz

There are 26 ' ' (space chars) inbetween the abcd and efghijk...etc. When I try this though:

k= 4;
Vader = horzcat(Vader(1:k), ' ', Vader(k+1:end))
k= k+5;
Vader = horzcat(Vader(1:k), ' ', Vader(k+1:end))
k= k+5;
Vader = horzcat(Vader(1:k), ' ', Vader(k+1:end))
k= k+5;
.....etc

The output is:

abcd efgh ijkl mnop qrst uvwx yz

Totally right!

What is going on?

Why is the for loop different than just writing out all my steps? They seem the same to me. I am lost. Also, I need this to do it for any string, any character I want to put in (\t, \n, 'somechars', etc) and for any length string. My eventual goal is to get it to handle hex strings of 4 chars in groups of 6 with 2 stop/start chars at the end (28 total chars)

Thank you for any and all help, I appreciate it.

EDIT

I am a doofus:

for k = 4:5:(length(Vader))
    Vader = horzcat(Vader(1:k), char(13), Vader(k+1:end));
    k = k+1; 
end
Vader

I need the stepsize portion for this

k = 4:5:(length(Vader))

vs my old code

k = 4:(length(Vader))

However this will not loop through the entire thing. As a commenter below points out, the length(Vader) part is initialized at the beginning. The code will then stop before the desired output is reached and the string is now longer that it initially was.

Any ideas on how to force the length(Vader) portion to update with every loop? Thank you.

EDIT 2:

Ok, got it! You have to pre-calculate the length your final string is going to be and have that be the limit for the 'for' loop:

jarJar = 4;         %how many in string you want to skip over
luke = ceil(length(Vader)*((1+jarJar)/jarJar));
for hanSolo = jarJar:(1+jarJar):luke
    Vader = horzcat(Vader(1:hanSolo), ' ', Vader(hanSolo+1:end));
    hanSolo = hanSolo+1; 
end
Vader

The ceil() part is important. You can get fractional values and you want to go past the end of the final string length, not under it (as floor() would give you).

Thanks for the help Bob Gilman and the brain pickings. It really helps to have a rubber duck that can sometimes talk back to you.

2
My first reaction was to say that you wanted to use for k=1:4:length(Vader) (note that I'm using the begin:stepsize:end range syntax, not the begin:end syntax that you used), but even that isn't right. Keep in mind that length(Vader) in the for loop conditional will be evaluated once, before the loop starts executing. But by the time that the loop finishes, Vader will be longer, so you're not really looping through to the end of Vader.Bob Gilmore
Thank you Bob Gilmore for the 'begin:stepsize:end' condition. I also am running into the issue where the for loop evals the size at the beginning, and not for the entirety of the loop. I'll try a 'while' loop with the 'for' loop nested and see where that gets me. I hope I remember to post the answer back hereuser3320919
Bob Gilamn, see my edits above for the solution. You have to calculate the length of the final string first, then use that as the limit for the for loopuser3320919
@user3320919 You should post the solution you found as an answer to your question and then accept it, so that people reading the question recognize immediately that your problem has been resolved.jerad
ok, will do! thank youuser3320919

2 Answers

3
votes

You can use reshape turn the string into a 4-column matrix, then concatenate a column of tabs to it; then convert it back.

Here's an example, given your starting string:

>> str = 'abcdefghijklmnopqrstuvwxyz';

Note that length(str) is 26, which is indivisible by 4. to make this work out, let's find how far away from the next number divisible by 4. Then we'll add that many spaces to the string. This is necessary because reshape gets you the same number of elements before and after the operation; it won't add more elements just to make the size correct.

>> numSpaces = 4 - mod(length(str), 4)
numSpaces = 
    2
>> str = [str repmat(' ', [1 numSpaces])];

Now, let's reshape. Reshape operates column-wise, so we need to transpose the output.

>> reshapedStr = reshape(str, 4, []).'
reshapedStr = 
abcd
efgh
ijkl
mnop
qrst
uvwx
yz

Then, separately create a new column vector tabs, which has the same length as the reshapedStr:

>> tabs(1:length(reshapedStr), 1) = sprintf('\t');

Concatenate this column to our array:

>> reshapedStr = [reshapedStr tabs];

And reshape it back (note that we transpose reshapedStr because it operates column-wise, not row-wise)

>> finalStr = reshape(reshapedStr.', 1, [])
finalStr = 
abcd    efgh    ijkl    mnop    qrst    uvwx    yz

You can probably remove the final spaces and tab trailing yz if you want, also.

0
votes
jarJar = 4;         %how many in string you want to skip over
luke = ceil(length(Vader)*((1+jarJar)/jarJar));
for hanSolo = jarJar:(1+jarJar):luke
    Vader = horzcat(Vader(1:hanSolo), ' ', Vader(hanSolo+1:end));
    hanSolo = hanSolo+1; 
end
Vader

This is a great way of doing it, see the edits above for a more detailed explanation. Thank you.