MATLAB Answers

Replace text in a struct with new values

3 views (last 30 days)
Michael Boyle
Michael Boyle on 15 Oct 2021
Edited: dpb on 16 Oct 2021
I have a struct where each row is a line from a text file. I am trying to replace values in a given row with new ones.
idx = 1;
new_value = 0.6411;
text_file(idx).text = '* .57735 .57735 .57735';
text_file(idx).text = strrep(text_file(idx).text,num2str(cell2mat(textscan(text_file(idx).text(9:25),'%f'))),num2str(new_value));
I am trying to keep the struct formatted like the text file so it can be written out into a new file when the replacement is complete. When I run these lines it doesn't change the value

Answers (1)

dpb
dpb on 16 Oct 2021
The problem is the string you're building for the substitution doesn't match the actual string in the struct substring owing to the peculiarities of C printf formatting string behavior for floating point values (and hence for fprintf and friends in MATLAB which are derived from the C i/o RTL).
Illustration of problem follows --
>> text_file(idx).text(9:25) % the substring you're selecting
ans =
'.57735 .'
>> num2str(cell2mat(textscan(text_file(idx).text(9:25),'%f'))) % what your conversion to string produces
ans =
'0.57735'
>>
num2str and all variants based on the C conversion formatting produce the leading 0 in front of the decimal point. This means that string doesn't match the string in the text which is
>> text_file(idx).text
ans =
'* .57735 .57735 .57735'
>>
The most brute-force but least modification to the existing code to make it work would be
>> strrep(text_file(idx).text,strrep(num2str(cell2mat(textscan(text_file(idx).text(9:25),'%f'))),'0.','.'),num2str(new_value,5))
ans =
'* 0.6411 0.6411 0.6411'
>>
which just does an internal string replacement of "0." with "." first.
I'd suggest the above can be simplified some by using the low-level sscanf instead of textscan
>> strrep(text_file(idx).text,strrep(num2str(sscanf(text_file(idx).text(9:25),'%f')),'0.','.'),num2str(new_value))
ans =
'* 0.6411 0.6411 0.6411'
>>
which gets rid of the cell returned by textscan in lieu of the double directly.
Alternatively, use some of the new-fangled string functions --
>> strrep(text_file(idx).text,extractBetween(text_file(idx).text(9:25),'.',' '),extractAfter(string(new_value),'.'))
ans =
"* .6411 .6411 .6411"
>>
  2 Comments
dpb
dpb on 16 Oct 2021
Or, alternatively to the above, one could keep the numeric array and then just do blanket character substitution into the text file image of the indexed locations to change overwriting the full field width instead of doing character substitution.
The above just treating as numeric and writing on demand still seems the simpler solution without seeing the full problem to be solved, however.

Sign in to comment.

Products


Release

R2020b

Community Treasure Hunt

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

Start Hunting!