Writing txt files accurately with a restriction on the number of columns.

8 views (last 30 days)
Okay. So I am having kind of a weird problem. I am trying to write a bunch of txt files where I have some vectors (arrays) and I print/write them in txt files using fprintf. And you know when you go into Notepad to edit a txt file and you see at the right bottom corner of the program where it says "Ln X, Col Y" where it reports which line and column the cursor is in? Well, I have a restriction where I CANNOT write information in Col that is greater than 50. So if I reach Col 50, I need to move to the next line. The problem is when I have a vector like [0,0,1,2.14,3] and lets say I reached column 50 in the fourth element of the array, I cannot simply fprintf it like this:
0,0,1,2.1
4,3
It will come out weird. I have to code it such that MATLAB knows that it will reach the 50 column and stops printing the number at the current line before moving to the next line:
0,0,1,
2.14,3
I hope I described the problem accurately for someone to help me implement this in MATLAB. Thank you.
  3 Comments
Rik
Rik on 16 Apr 2023
That second option would be my suggestion. Why don't you move it to the answer section?
dpb
dpb on 16 Apr 2023
I was too lazy to write the code, Rik, so didn't think it deserved Answer status... :)

Sign in to comment.

Accepted Answer

dpb
dpb on 16 Apr 2023
Edited: dpb on 16 Apr 2023
a=randi(200,[1,25]);
fmt=['%d' repmat(',%d',1,numel(a)-1)];
s=sprintf(fmt,a)
s = '169,69,96,41,196,14,77,27,21,47,155,58,60,100,37,168,68,126,49,189,136,70,85,95,76'
LL=25;
L=strlength(s)
L = 82
O=[];
while L>0
I=strfind(s,','); % locate the delimiters
J=I(find(I<=LL,1,'last')); % get the last one within line length limit
O=[O;string(s(1:J))]; % add that to the output array
s=s(J+1:end); % get the rest of the string
L=strlength(s); % recompute the length remaining
if L<=LL % handle last line w/o trailing comma
O=[O;string(s)];
L=0;
end
end
O
O = 4×1 string array
"169,69,96,41,196,14,77," "27,21,47,155,58,60,100," "37,168,68,126,49,189," "136,70,85,95,76"
Now you can write the output string array with writematrix or you could echo out each line during the loop with the venerable fprintf but that requires you explicitly open/close the file.
The above seemed to get pretty klunky; I'm sure it could be optimized "more better", but seems to work ok.
"LL" is, of course, the line-length limit; set as wish...

More Answers (2)

Stephen23
Stephen23 on 16 Apr 2023
Edited: Stephen23 on 16 Apr 2023
V = randi(123,1,23)
V = 1×23
100 92 80 37 40 45 41 52 17 30 21 82 10 50 21 29 83 83 118 115 14 75 116
T = sprintf('%g,',V);
U = regexprep(T,'(.{1,13}),','$1\n'); % e.g. max 13 columns
fprintf('%s',U)
100,92,80,37 40,45,41,52 17,30,21,82 10,50,21,29 83,83,118,115 14,75,116
And if you want to include the trailing comma:
U = regexprep(T,'.{1,12},','$&\n'); % e.g. max 13 columns
fprintf('%s',U)
100,92,80,37, 40,45,41,52, 17,30,21,82, 10,50,21,29, 83,83,118, 115,14,75, 116,
Note that any single values longer than the requested column limit will not be broken over two lines.
  4 Comments
dpb
dpb on 17 Apr 2023
Edited: dpb on 17 Apr 2023
5 columns of %3d would be 20 characters counting the comma; the same five columns as %12E.5 would be 65; it would depend on the formatting, not the number of columns to ensure didn't pass the character count oun the line...
Now, granted, OP wrote "columns" in the title, but the problem description is actually counting characters
Stephen23
Stephen23 on 17 Apr 2023
Edited: Stephen23 on 18 Apr 2023
"but the problem description is actually counting characters"
Correct, but for MS Notepad the "Col #" value as the OP described is a count of characters (sort of):
"this counts/limits columns not characters, correct?"
Ummm.... For MS Notepad the two are basically equivalent: the "Col #" is actually the number of the column which will get printed in at the given cursor location (note Notepad++ also uses this definition). This matches what the OP described and what my code does. You appear to be using another definition of "column", which so far you have not explicitly described.
"5 columns of %3d would be 20 characters counting the comma; the same five columns as %12E.5 would be 65"
Aaaha, so you are using your own, different definition of "column".
It appears that you are thinking of "column" in terms of something like the fields per line of a CSV file, but I do not see this definition as matching what the OP described, nor the behavior of my code, nor does it match what MS Notepad provides with the "Col #" value (see OP's question above and also the MS Notepad screenshot). The OP explicitly referred to the the MS Notepad context and meaning.
Still, not very relevant for my code, which limits the columns (as MS Notepad and the OP consistently use the term, or equivalently the number of characters) per line.
"this counts/limits columns not characters, correct?"
So it appears the answer to your very first question is "no, not as you use the term".
In any case, I presume that a simple test would also resolve your question:
V = randi(123,1,23)
V = 1×23
101 87 46 96 117 21 36 45 28 100 4 50 117 65 11 119 11 102 80 90 60 69 122
T = sprintf('%12e5,',V);
U = regexprep(T,'(.{1,20}),','$1\n'); % e.g. max 20 columns
fprintf('%s',U)
1.010000e+025 8.700000e+015 4.600000e+015 9.600000e+015 1.170000e+025 2.100000e+015 3.600000e+015 4.500000e+015 2.800000e+015 1.000000e+025 4.000000e+005 5.000000e+015 1.170000e+025 6.500000e+015 1.100000e+015 1.190000e+025 1.100000e+015 1.020000e+025 8.000000e+015 9.000000e+015 6.000000e+015 6.900000e+015 1.220000e+025

Sign in to comment.


dpb
dpb on 16 Apr 2023
Still with same idea but a little cleaner implementation...
%a=randi(200,[1,25]);
%fmt=['%d' repmat(',%d',1,numel(a)-1)];
%s=sprintf(fmt,a)
s = '169,69,96,41,196,14,77,27,21,47,155,58,60,100,37,168,68,126,49,189,136,70,85,95,76'
s = '169,69,96,41,196,14,77,27,21,47,155,58,60,100,37,168,68,126,49,189,136,70,85,95,76'
LL=25; % max line length
I=strfind(s,','); % breakpoints
for i=I(fliplr(find(diff(ceil(strfind(s,',')/(LL-1)))))) % insert from back to front
s=insertAfter(s,i,newline);
end
s
s =
'169,69,96,41,196,14,77, 27,21,47,155,58,60,100, 37,168,68,126,49,189,136, 70,85,95,76'
strfind(s,newline) % all \n < LL*l where l is line number
ans = 1×3
24 48 74
  2 Comments
Stephen23
Stephen23 on 16 Apr 2023
Edited: Stephen23 on 16 Apr 2023
The last line does not seem to be split correctly, it always includes the two last values:
s = '123,456,789'
s = '123,456,789'
LL=4; % max line length
I=strfind(s,','); % breakpoints
for i=I(fliplr(find(diff(ceil(strfind(s,',')/(LL-1)))))) % insert from back to front
s=insertAfter(s,i,newline);
end
disp(s)
123, 456,789
dpb
dpb on 16 Apr 2023
I didn't check anything but longer values; seemed to work for that so I'm not sure -- the rounding is probably suspect...

Sign in to comment.

Categories

Find more on Environment and Settings in Help Center and File Exchange

Products


Release

R2021a

Community Treasure Hunt

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

Start Hunting!