fprintf uiputfile of multiselect data file doesnt work....

1 view (last 30 days)
Hi, everyone.... I just so confused with this data, so let me share my wrongness code right below :
[namafile,direktori]=uigetfile({'*.txt', 'Text-files (*.txt)'},'Load Data Magnet LEMI Non RAW Non IAGA (Menitan / Detikan)','Multiselect','on');
full = fullfile(direktori,namafile);
nfiles = size(full,2);
f = cellstr(fullfile(direktori,namafile));
file = length(f);
if file == 1
[~, base, ~] = fileparts(full);.... %This completed code was good
if file > 1 %This is my code for multiselect file from uigetfile function
for k = 1:nfiles
[~, namafile{k}] = fileparts(full{k});
nama = namafile{k};
lastIndex2 = length(nama);% Capitalize first character and lower case remaining characters.
m1 = contains(nb, '1m');
s1 = contains(nb, '1s');
lem = contains(nb, 'lemi');
sta = extractBefore(nb,"_lemi");
sti2 = "Hasil Ekstrak Gabungan File Komponen Magnet H dan F Data Lemi" + " " + "(" + tipe2 + ")" + " " + "Stasiun" + " " + sta2 ;
opts = delimitedTextImportOptions('Delimiter',' ',...
'VariableNames', {'VarName1','VarName2','VarName3','VarName4','VarName5','VarName6','VarName7','VarName8','VarName9','VarName10','VarName11','VarName12','VarName13'},...
'WhiteSpace', '');
B = readmatrix(full{k}, opts);
tahun = cellfun(@str2num,(B(1:end,1))); %: Mendapatkan data tahun pada kolom 1
bulan = cellfun(@str2num,(B(1:end,2))); %: Mendapatkan data bulan pada kolom 2
tanggal = cellfun(@str2num,(B(1:end,3))); %: Mendapatkan data tanggal pada kolom 3
jam = cellfun(@str2num,(B(1:end,4))); %: Mendapatkan data jam pada kolom 4
menit = cellfun(@str2num,(B(1:end,5))); %: Mendapatkan data menit pada kolom 4
detik = cellfun(@str2num,(B(1:end,6))); %: Mendapatkan data detik pada kolom 6
x = cellfun(@str2num,(B(1:end,7))); %: Mendapatkan data magnet arah sumbu x pada kolom 7
y = cellfun(@str2num,(B(1:end,8))); %: Mendapatkan data magnet arah sumbu y pada kolom 8
z = cellfun(@str2num,(B(1:end,9))); %: Mendapatkan data magnet arah sumbu z pada kolom 9
h = cellfun(@str2num,(B(1:end,10))); %: Mendapatkan data medan magnet Komponen H pada kolom 10
h_combine(:,k) = h(:);
h = h(:);
D = datetime(tahun,bulan,tanggal,0,0,0,'TimeZone','Asia/Jakarta');
D_combine(:,k) = D(:);
D = D(:);
date = string(D_combine(:));
time = hours(jam) + minutes(menit) + seconds(detik);
time.Format = 'hh:mm:ss';
time_combine(:,k) = time(:);
time = time(:);
tim = string(time);
wak = D + time;
wak_combine(:,k) = wak(:);
wak = wak(:);
waks = wak_combine(:,1:k);
waks = waks(:);
ntropy = string(waks);
DOHk = sqrt((x.^2)+(y.^2));
DOHk_combine(:,k) = DOHk(:);
DOHk = DOHk(:);
komph = DOHk_combine(:,1:k);
komph(:) = double(komph(:));
DOFk = sqrt((x.^2)+(y.^2)+(z.^2));
DOFk_combine(:,k) = DOFk(:);
kompf = DOFk_combine(:,1:k);
kompf(:) = double(kompf(:));
output_combine2 = horzcat(DOHk_combine(:),DOFk_combine(:));
%Im trying to let the variable become so many like that because im still trying and error...
if m2 == 1 || s2 == 1 || lem2 == 1
[namafile3, direktori1, ~] = uiputfile({'*.txt', 'Text-files (*.txt)'}, 'Simpan Hasil Sebagai', sti2);
eval(['cd ''' direktori1 ''';']);
fprintf(fout,'%s %f %f\n',ntropy, komph(:), kompf(:));% This is the [expletive deleted--dpb] output that brings me so confused
This output of " fprintf(fout,'%s %f %f\n',ntropy, komph(:), kompf(:)); ", just bring me so confused because although the length of ntropy, komph(:), and kompf(:) variables are matched each other, no matter how hard i try, it always give this terrible output :
02-Jul-2019 00:00:59 NaN NaN
02-Jul-2019 00:03:59 NaN NaN
02-Jul-2019 00:06:59 NaN NaN
02-Jul-2019 00:09:59 NaN NaN
02-Jul-2019 00:12:59 NaN NaN
02-Jul-2019 00:15:59 NaN NaN
02-Jul-2019 00:18:59 NaN NaN
Why it always give me the NaN???? it should be a double variable data, right? So, would anyone lend me a hand to solve my problem here?? Thank you very much. (I have attached my data sample for anyone who wanna try my data with my code...)
Im sorry for interrupt your days... /.\ /.\ /.\
Tyann Hardyn
Tyann Hardyn on 13 Aug 2021
Alright, yes, thats solve a bit of my problem... Everyone in forum always do the same advice to me, i just forgot about that. Thank you very much, Sir...

Sign in to comment.

Accepted Answer

Cris LaPierre
Cris LaPierre on 13 Aug 2021
Edited: Cris LaPierre on 13 Aug 2021
The issue is with how MATLAB is plugging numbers into your format spec '%s %f %f\n'. When you supply fprintf with more than 1 variable, and those variables are not scalars, it uses all the values from the first variable before moving to values from the second variable. In this case, notice that the first time in your oput is '02-Jul-2019 00:00:59' but the second is '02-Jul-2019 00:03:59'. The 2nd and 3rd ntropy values (01:59 and 02:59) were written using %f, but the data is string, so you get NaN displayed.
The solution is to either put the fprintf statement inside a for loop that writes a single value from each variable each time,
for v = 1:length(ntropy)
fprintf(fout,'%s %f %f\n',ntropy(v), komph(v), kompf(v));
or organize your data so that it is formatted in a way where the format string aligns with the data. Since MATLAB uses column-major ordering by default, this means putting each variable in a matrix row so that as the data is read out column by colum, the 3 rows align with the 3 formats.
fprintf(fout,'%s %f %f\n',[ntropy, komph, kompf]');
Tyann Hardyn
Tyann Hardyn on 20 Aug 2021
Edited: Tyann Hardyn on 20 Aug 2021
@Cris LaPierre Ohh, yes, you re right, Sir. I have a problem with that order of data. And i remember that i ever ask about it in this question. So i try again what you share to me, and its work also by using this code !!!
fprintf(fout,'%s %f %f\n',[ntropy, komph, kompf]');
Without the code of yours, my previous code is :
fprintf(fout,'%s %s %s %s %s %s %s %s\n', 'DATE', 'TIME', 'H(Calc)', 'H(Obs)', 'F(Calc)', 'X(Obs)', 'Y(Obs)', 'Z(Obs)');
fprintf(fout,'%s %s %.2f %.2f %.2f %.2f %.2f %.2f\n', char(D), times, DOH, h, DOF, x, y, z);
And it brings me the confused output with NaN thing.
After that, i retype again by using your format so the code above become like this :
fprintf(fout,'%s %s %s %s %s %s %s %s\n', 'DATE', 'TIME', 'H(Calc)', 'H(Obs)', 'F(Calc)', 'X(Obs)', 'Y(Obs)', 'Z(Obs)');
fprintf(fout,'%s %s %.2f %.2f %.2f %.2f %.2f %.2f\n', [char(D), times, DOH, h, DOF, x, y, z]');
And voila, it Work!! Thank you very much, Sir
So, matlab is indeed, a column based script.

Sign in to comment.

More Answers (1)

dpb on 13 Aug 2021
Edited: dpb on 13 Aug 2021
fprintf(fout,'%s %f %f\n',ntropy, komph(:), kompf(:));% This is the [expletive deleted--dpb] output that brings me so confused
The problem is that fprintf is vectorized and outputs each argument in its entirety before going on to the next and tries to match the elements in sequence to the formatting string. Your output string says it expects one string and then two floats in sequence but it is passed an array of strings, then an array of double, then another array of double.
Low level i/o has to be written a record at a time -- something like
[namafile3, direktori1, ~] = uiputfile({'*.txt', 'Text-files (*.txt)'}, 'Simpan Hasil Sebagai', sti2);
for i=1:numel(komph)
fprintf(fout,'%s %f %f\n',ntropy(i),komph(i),kompf(i));
There are examples of outputting formatted text files in the documentation for fprintf that illustrate this.
Mixed data types are more difficult to deal with than consistent types that can be put into single arrays.
You might want to look into using the table data structure instead; writetable then will handle the various data types transparently for you.
I've not looked at the rest of the code, but almost certainly most of the machinations could be avoided by reading the variables as the proper type. See detectImportOptions and readtable
Also, as the logic is presently, there is nothing happening for the case of trying to read one file.
dpb on 14 Aug 2021
Edited: dpb on 14 Aug 2021
" I never think about the use of " numel " before"
It and size are the two workhorses -- length, while handy and by the name seemingly the proper function, is very dangerous/error-prone and should be avoided in general practice. The reason is that it is defined as
and so for a 2D array will return either the number of rows if the array is "taller" than "wide" but will return the number of columns if the array is "wider" than "tall".
For a vector, they turn out to be the same, of course, but still it will be either the number of columns if a row vector or number of rows if column vector. It is the same number as numel() for the vector, but in general, length can lead to a surprise on occasion.
"This is one of the best solution of my problem here..."
It is the "plain vanilla" solution and doesn't rely on any of the newer features such as compose that could be used as others have illustrated.
I've not tried to compare the performance of the direct i/o in the loop as above to the vectorized creation of the string array and then outputting it. For relatively small arrays I'm sure either as adequate; if the size grew to be really large I'd guess one would be able to see the difference and the direct use of the runtime i/o libraries would win over the preprocessing-first route.

Sign in to comment.


Find more on Characters and Strings in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!