Adding Character String with Numbers / Concatenate Number with String in Matlab Array - arrays

How to add character ',' or '+' in a matlab 2d array.
I've tried the following way.
clc
clear all
close all
min=0;
max=1052;
random_int = randi([min max],5,10)
% random_int=[515,586,942,742;353,588,916,436]
% load('Random_Int_x.mat')
% random_int
[m,n]=size(random_int);
for i=1:1:m
allOneString = sprintf('%d,' , random_int(i,:));
allOneString= allOneString(1:end-1)% strip final comma
Str_1(i,:)=allOneString
% allOneString= strjoin(arrayfun(#(x) num2str(x),random_int(i,:),'UniformOutput',false),',');
end
Str_1
Example of Input / Matrix
random_int =
2 9 7 7 9 8 2 5 7 5
6 1 9 9 6 1 9 4 1 0
5 0 8 8 5 6 9 0 4 6
0 9 9 8 7 5 6 3 7 8
8 4 2 0 5 5 1 8 2 6
Output:
Str_1 =
5×19 char array
'2,9,7,7,9,8,2,5,7,5'
'6,1,9,9,6,1,9,4,1,0'
'5,0,8,8,5,6,9,0,4,6'
'0,9,9,8,7,5,6,3,7,8'
'8,4,2,0,5,5,1,8,2,6'
This works properly with random number between 0-9.. However if I put input above 9 --> 10 .. then matlab throws matrix dimension error.
Subscripted assignment dimension mismatch.
Error in Number_with_String (line 14)
Str_1(i,:)=allOneString;
For Input above 9:
random_int =
76 96 88 23 26 25 92 5 61 86
87 69 32 36 86 39 46 21 55 69
42 26 56 69 55 97 91 78 76 41
74 74 24 3 46 52 29 70 88 4
7 48 13 69 15 12 79 91 90 24
Expecting output:
'76,96,88,23,26,25,92,5,61,86'
'87,69,32,36,86,39,46,21,55,69' ... etc
Any suggestion to resolve this ..

Here's a way:
random_int = randi([0 500],5,10); % example data
y = mat2cell(random_int, ones(1,size(random_int,1)), size(random_int,2)); % split into rows
y = cellfun(#(x) sprintf('%i,', x), y, 'UniformOutput', false); % strings with commas
y = cellfun(#(s) s(1:end-1), y, 'UniformOutput', false); % remove last comma from each
Example result:
>> y
y =
5×1 cell array
'74,281,294,376,124,203,211,170,242,334'
'488,268,31,84,404,74,205,178,215,20'
'120,242,390,37,113,199,140,375,395,469'
'455,94,115,476,28,20,365,213,181,31'
'130,62,138,421,261,105,114,226,398,90'

I would recommend you use string which shipped in 16b. You can convert the result to char or cellstr if you need.
>> min=0; max=1052;
>> random_int = randi([min max],5,10)
random_int =
532 145 857 264 616 793 558 494 327 688
736 157 256 648 578 400 820 12 556 725
938 271 978 498 965 597 983 354 174 787
1010 885 368 370 300 79 136 170 633 474
576 267 207 874 797 56 598 836 276 88
>> str = join(string(random_int),',')
str =
5×1 string array
"532,145,857,264,616,793,558,494,327,688"
"736,157,256,648,578,400,820,12,556,725"
"938,271,978,498,965,597,983,354,174,787"
"1010,885,368,370,300,79,136,170,633,474"
"576,267,207,874,797,56,598,836,276,88"
>> char(str)
ans =
5×39 char array
'532,145,857,264,616,793,558,494,327,688'
'736,157,256,648,578,400,820,12,556,725 '
'938,271,978,498,965,597,983,354,174,787'
'1010,885,368,370,300,79,136,170,633,474'
'576,267,207,874,797,56,598,836,276,88 '

clc
clear all
close all
min=0;
max=1052;
random_int = randi([min max],200,10);
[m,n]=size(random_int);
for i=1:1:m
allOneString = sprintf('%d,' , random_int(i,:));
allOneString= allOneString(1:end-1); % strip final comma
Str_1{i}=allOneString;
end
Str_1=Str_1'

Related

Splitting a large matrix

I'm using Julia to ingest a large two dimensional data array (data) of size 1000 x 32768; I need to break up the array into smaller square arrays along both dimensions. For instance, I would like to break data into a grid of smaller, square arrays similar to the following image:
Note that no pixels get left out -- when another square cannot be fit in along either axis, the last possible array of square pixels is returned as another array (hence the shifted pink squares on the right hand side).
Currently, I'm doing this through a function I built to decimate the raw dataset:
function decimate_square(data,fraction=4)
# Read size of input data / calculate length of square side
sy,sx = size(data)
square_side = Int(round(sy/fraction))
# Number of achievable full squares
itersx,itersy = [Int(floor(s/square_side)) for s in [sx,sy]]
# Find left/right X values
for ix in 1:itersx
if ix!=itersx
# Full sliding square can be calculated
left = square_side*(ix-1) + 1
right = square_side*(ix)
else
# Capture last square of data
left = sx-square_side + 1
right = sx
end
# Find top/bottom Y values for each X
for iy in 1:itersy
if iy!=itersy
# Full sliding square can be calculated
top = square_side*(iy-1) + 1
bottom = square_side*(iy)
else
# Capture last square of data
top = sy-square_side + 1
bottom = sy
end
# Record data in 3d stack
cursquare = data[top:bottom,left:right]
if (ix==1)&&(iy==1); global dstack=cursquare
else; dstack=cat(dstack,cursquare,dims=3)
end
end
end
return dstack
end
Which currently takes ~20 seconds to run:
rand_arr = rand(1000,32768)
t1 = Dates.now()
dec_arr = decimate_square(rand_arr)
t2 = Dates.now()
#info(t2-t1)
[ Info: 19666 milliseconds
This is the biggest bottleneck of my analysis. Is there a pre-built function that I can use, or is there a more efficient way to decimate my array?
You can take views as Przemyslaw Szufel suggests, and the CartesianIndex type comes in handy for selecting blocks of the matrix.
julia> function squareviews(data, fraction = 4)
squareside = floor(Int, size(data, 1) / fraction)
[#view(M[CartesianIndex(ix-squareside+1, iy-squareside+1):CartesianIndex(ix, iy)])
for ix in squareside:squareside:size(data, 1),
iy in squareside:squareside:size(data, 2)]
end
squareviews (generic function with 2 methods)
julia> result = squareviews(M)
4×40 Matrix{SubArray{Int64, 2, Matrix{Int64}, Tuple{UnitRange{Int64}, UnitRange{Int64}}, false}}:
[346 392 … 746 429; 380 193 … 476 757; … ; 424 329 … 285 427; 591 792 … 710 891] … [758 916 … 7 185; 26 846 … 631 808; … ; 945 713 … 875 137; 793 655 … 400 322]
[55 919 … 402 728; 292 238 … 266 636; … ; 62 490 … 913 126; 293 475 … 492 20] [53 8 … 146 365; 216 673 … 157 909; … ; 955 635 … 332 945; 354 913 … 922 272]
[278 966 … 128 334; 700 560 … 226 701; … ; 529 398 … 17 674; 237 830 … 4 788] [239 274 … 983 911; 591 669 … 762 675; … ; 213 949 … 917 903; 336 890 … 633 578]
[723 483 … 135 283; 729 579 … 1000 942; … ; 987 383 … 764 544; 682 942 … 376 179] [370 859 … 444 566; 34 106 … 320 161; … ; 310 41 … 868 349; 719 341 … 718 800]
This divides the data matrix into blocks such that result[2, 3] gives the square that is 2nd from the top and 3rd from the left. (My matrix M was 100x1000 in size, so there are 100/25 = 4 blocks vertically and 1000/25 = 40 blocks horizontally.)
If you want the results linearly like in your original function, you can instead have the second line of the function be:
julia> function squareviews(data, fraction = 4)
squareside = floor(Int, size(data, 1) / fraction)
[#view(M[CartesianIndex(ix-squareside+1, iy-squareside+1):CartesianIndex(ix, iy)])
for iy in squareside:squareside:size(data, 2)
for ix in squareside:squareside:size(data, 1)]
end
squareviews (generic function with 2 methods)
julia> squareviews(M)
160-element Vector{SubArray{Int64, 2, Matrix{Int64}, Tuple{UnitRange{Int64}, UnitRange{Int64}}, false}}:
(Note the subtle changes in the for syntax - the iy comes before ix here, there's no comma, and there's an extra for.)
This returns a vector of square matrices (views).
Your original function returned a three-dimensional matrix, in which you'd access values as originalresult[i, j, k]. Here, the equivalent would be result[k][i, j].
There's a lot of stuff going on in your code with is not recommended and making things slow. Here's a somewhat idiomatic solution, with the additional bonus of generalizing to arbitrary ranks:
julia> function square_indices(data; fraction=4)
splits = cld.(size(data), fraction)
return Iterators.map(CartesianIndices, Iterators.product(Iterators.partition.(axes(data), splits)...))
end
square_indices (generic function with 1 method)
The result of this is an iterator over CartesianIndices, which are objects that you can use to index your squares. Either the regular data[ix], or view(data, ix), which does not create a copy. (Different fractions per dimension are possible, try test_square_indices(println, 4, 4, 4; fraction=(2, 1, 1)).)
And to see whether it works as expected:
julia> function test_square_indices(f, s...; fraction=4)
arr = reshape(1:prod(s), s...)
for ix in square_indices(arr; fraction)
f(view(arr, ix))
end
end
test_square_indices (generic function with 1 method)
julia> # just try this on some moderatly costly function
#btime test_square_indices(v -> inv.(v), 1000, 32768)
81.980 ms (139 allocations: 250.01 MiB)
julia> test_square_indices(println, 9)
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
julia> test_square_indices(println, 9, 5)
[1 10; 2 11; 3 12]
[4 13; 5 14; 6 15]
[7 16; 8 17; 9 18]
[19 28; 20 29; 21 30]
[22 31; 23 32; 24 33]
[25 34; 26 35; 27 36]
[37; 38; 39;;]
[40; 41; 42;;]
[43; 44; 45;;]
julia> reshape(1:9*5, 9, 5)
9×5 reshape(::UnitRange{Int64}, 9, 5) with eltype Int64:
1 10 19 28 37
2 11 20 29 38
3 12 21 30 39
4 13 22 31 40
5 14 23 32 41
6 15 24 33 42
7 16 25 34 43
8 17 26 35 44
9 18 27 36 45
julia> test_square_indices(println, 4, 4, 4; fraction=2)
[1 5; 2 6;;; 17 21; 18 22]
[3 7; 4 8;;; 19 23; 20 24]
[9 13; 10 14;;; 25 29; 26 30]
[11 15; 12 16;;; 27 31; 28 32]
[33 37; 34 38;;; 49 53; 50 54]
[35 39; 36 40;;; 51 55; 52 56]
[41 45; 42 46;;; 57 61; 58 62]
[43 47; 44 48;;; 59 63; 60 64]
julia> reshape(1:4*4*4, 4, 4, 4)
4×4×4 reshape(::UnitRange{Int64}, 4, 4, 4) with eltype Int64:
[:, :, 1] =
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
[:, :, 2] =
17 21 25 29
18 22 26 30
19 23 27 31
20 24 28 32
[:, :, 3] =
33 37 41 45
34 38 42 46
35 39 43 47
36 40 44 48
[:, :, 4] =
49 53 57 61
50 54 58 62
51 55 59 63
52 56 60 64
Here's a bit of an illustration of how this works:
julia> data = reshape(1:9*5, 9, 5); fraction = 3;
julia> size(data)
(9, 5)
julia> # chunk sizes
splits = cld.(size(data), fraction)
(3, 2)
julia> # every dimension chunked
Iterators.partition.(axes(data), splits) .|> collect
(UnitRange{Int64}[1:3, 4:6, 7:9], UnitRange{Int64}[1:2, 3:4, 5:5])
julia> # cross product of all chunks
Iterators.product(Iterators.partition.(axes(data), splits)...) .|> collect
3×3 Matrix{Vector{UnitRange{Int64}}}:
[1:3, 1:2] [1:3, 3:4] [1:3, 5:5]
[4:6, 1:2] [4:6, 3:4] [4:6, 5:5]
[7:9, 1:2] [7:9, 3:4] [7:9, 5:5]
You could just go with views. Suppose you want to slice your data into 64 matrices, each having size 1000 x 512. In that case you could do:
dats = view.(Ref(rand_arr),Ref(1:1000), [range(1+(i-1)*512,i*512) for i in 1:64])
The time for this on my machine is 600 nanoseconds:
julia> #btime view.(Ref($rand_arr),Ref(1:1000), [range(1+(i-1)*512,i*512) for i in 1:64]);
595.604 ns (3 allocations: 4.70 KiB)

2D matrix to 3D matrix with row to [row, col] mapping

I have a 2D matrix with in the 1st dimension different channels, and in the 2nd dimension time samples. I want to rearrange this to a 3D matrix, with in the 1st and 2nd dimension channels, and in the 3rd time samples.
The channels have to mapped according to a certain mapping. Right now I am using a for-loop to do so, but what would be a no-loop solution?
N_samples = 1000;
N_channels = 64;
channel_mapping = reshape(1:64, [8 8]).';
% Results in mapping: (can also be random)
% 1 2 3 4 5 6 7 8
% 9 10 11 12 13 14 15 16
% 17 18 19 20 21 22 23 24
% 25 26 27 28 29 30 31 32
% 33 34 35 36 37 38 39 40
% 41 42 43 44 45 46 47 48
% 49 50 51 52 53 55 55 56
% 57 58 59 60 61 62 63 64
data = rand(N_channels, N_samples);
data_grid = NaN(8,8, N_samples);
for k = 1:N_samples
tmp = data(:, k);
data_grid(:, :, k) = tmp(channel_mapping);
end
You can do it in one go as follows:
data_grid = reshape(data(channel_mapping, :), 8, 8, []);

C programming to make multiplication table (1-12)

I want to make a program that takes a single integer command line argument (n) and makes n x n multiplication table resembling the 4x4 example below. It should be only 1 through 12, but shouldn't be no smaller or larger. So if there is not enough argument, it should be print a usuage: Usage: program <n> \n or if it is out of range then it should be print: n out of range (1-12)\n and exit.
Example:
./program 4
* 1 2 3 4
+----------------
1| 1 2 3 4
2| 2 4 6 8
3| 3 6 9 12
4| 4 8 12 16
My code I have tried but wasn't success. I have copied the compiled is not what I expected in the below.
#include <stdio.h>
int main(void)
{
int i, j;
printf(" +");
for (i = 1; i < 13; ++i)
{
printf("%#3d ", i);
printf("\n");
}
for (i = 1; i < 64; ++i)
{
printf("-");
printf("\n");
}
for (i = 1; i < 13; ++i)
{
printf("%#2d |", i);
for (j = 1; j < 11; ++j)
{
printf("%#3d ", i * j);
printf("\n");
}
}
return 0;
}
After compile:
gcc version 4.6.3
+ 1
2
3
4
5
6
7
8
9
10
11
12
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1 | 1
2
3
4
5
6
7
8
9
10
2 | 2
4
6
8
10
12
14
16
18
20
3 | 3
6
9
12
15
18
21
24
27
30
4 | 4
8
12
16
20
24
28
32
36
40
5 | 5
10
15
20
25
30
35
40
45
50
6 | 6
12
18
24
30
36
42
48
54
60
7 | 7
14
21
28
35
42
49
56
63
70
8 | 8
16
24
32
40
48
56
64
72
80
9 | 9
18
27
36
45
54
63
72
81
90
10 | 10
20
30
40
50
60
70
80
90
100
11 | 11
22
33
44
55
66
77
88
99
110
12 | 12
24
36
48
60
72
84
96
108
120
I have been stuck on this for 2 days and trying to figure it out why is it going straight down.. Thank you.
the following code:
corrects the output formatting,
checks if there is a command line parameter,
follows the axiom:
only one statement per line and (at most) one variable declaration per statement.
checks the command line parameter to assure it is numeric and in the range 1...12
limits the scope of each variable
calls puts() where appropriate as printf() is very expensive in CPU cycles
uses appropriate horizontal spacing for readability
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h> // exit(), EXIT_FAILURE
#include <ctype.h> // isdigit()
#define MAX_VALUE 12
#define MIN_VALUE 1
int main( int argc, char *argv[] )
{
if( argc != 2 )
{
fprintf( stderr, "USAGE: %s <maxTableSize: range 1...12>\n", argv[0] );
exit( EXIT_FAILURE );
}
// implied else, user entered a command line parameter
if( !isdigit( argv[1][0] ) )
{
fprintf( stderr, "command line parameter not numeric\n" );
exit( EXIT_FAILURE );
}
// implied else, command line parameter starts with digit
int maxTableSize = atoi( argv[1] );
if( MIN_VALUE > maxTableSize || maxTableSize > MAX_VALUE )
{
fprintf( stderr, "command line parameter not in valid range ( 1...12 )\n");
exit( EXIT_FAILURE );
}
// implied else, command line parameter contains valid value
printf(" + ");
for ( int i = 1; i <= maxTableSize; ++i )
{
printf("%4d ", i);
}
puts("");
for ( int i = 1; i < 5+(maxTableSize*5); ++i )
{
printf( "-" );
}
puts("");
for ( int i = 1; i <= maxTableSize; ++i )
{
printf( "%2d |", i );
for ( int j = 1; j <= maxTableSize; ++j )
{
printf( "%4d ", i * j );
}
puts("");
}
return 0;
}
the following demonstrates the various conditions of running the program. (where untitled is the name of the program.)
./untitled
USAGE: ./untitled <maxTableSize: range 1...12>
./untitled a
command line parameter not numeric
./untitled 0
command line parameter not in valid range ( 1...12 )
./untitled 13
command line parameter not in valid range ( 1...12 )
./untitled 1
+ 1
--------
1 | 1
./untitled 2
+ 1 2
------------
1 | 1 2
2 | 2 4
.....
./untitled 12
+ 1 2 3 4 5 6 7 8 9 10 11 12
----------------------------------------------------------------
1 | 1 2 3 4 5 6 7 8 9 10 11 12
2 | 2 4 6 8 10 12 14 16 18 20 22 24
3 | 3 6 9 12 15 18 21 24 27 30 33 36
4 | 4 8 12 16 20 24 28 32 36 40 44 48
5 | 5 10 15 20 25 30 35 40 45 50 55 60
6 | 6 12 18 24 30 36 42 48 54 60 66 72
7 | 7 14 21 28 35 42 49 56 63 70 77 84
8 | 8 16 24 32 40 48 56 64 72 80 88 96
9 | 9 18 27 36 45 54 63 72 81 90 99 108
10 | 10 20 30 40 50 60 70 80 90 100 110 120
11 | 11 22 33 44 55 66 77 88 99 110 121 132
12 | 12 24 36 48 60 72 84 96 108 120 132 144
In your code, you are making 2 mistakes.
You are adding the printf ("\n") inside the for loop. This should be outside the for loop in case of single loop. In case of nested loop, the new line should be after each internal for loop.
You are using %#3d in printf. The # should be removed.
Other than that, after making few changes in printf alignment, the updated code is below
#include <stdio.h>
int main(void)
{
int i, j;
printf(" +");
for (i = 1; i < 13; ++i)
{
printf("%4d ", i);
}
printf("\n");
for (i = 1; i < 64; ++i)
{
printf("-");
}
printf("\n");
for (i = 1; i < 13; ++i)
{
printf("%2d |", i);
for (j = 1; j < 13; ++j)
{
printf("%4d ", i * j);
}
printf("\n");
}
return 0;
}
Output is as below
+ 1 2 3 4 5 6 7 8 9 10 11 12
---------------------------------------------------------------
1 | 1 2 3 4 5 6 7 8 9 10 11 12
2 | 2 4 6 8 10 12 14 16 18 20 22 24
3 | 3 6 9 12 15 18 21 24 27 30 33 36
4 | 4 8 12 16 20 24 28 32 36 40 44 48
5 | 5 10 15 20 25 30 35 40 45 50 55 60
6 | 6 12 18 24 30 36 42 48 54 60 66 72
7 | 7 14 21 28 35 42 49 56 63 70 77 84
8 | 8 16 24 32 40 48 56 64 72 80 88 96
9 | 9 18 27 36 45 54 63 72 81 90 99 108
10 | 10 20 30 40 50 60 70 80 90 100 110 120
11 | 11 22 33 44 55 66 77 88 99 110 121 132
12 | 12 24 36 48 60 72 84 96 108 120 132 144

Weird output when printing in C

Just started C after first year of java and am already confused. I try to print an array into a multiplication table. It works otherwise but I get zeroes after the first round of printing the array. I have allocated data in the whole array and it loops the right amount after checking. Still after the first print line I get 0 0 0 0 0 0 0 after the correct output.
#include<stdio.h>
int main(void)
{
int kertotaulu[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int kertoja;
int indeksi;
for(kertoja = 0; kertoja <=15; kertoja++) {
if(kertoja == 0) {
printf("x");
printf(" ");
for(indeksi = 0; indeksi< (sizeof(kertotaulu) / sizeof(kertotaulu[0])); indeksi++) {
printf("%d", kertotaulu[indeksi]);
printf(" ");
}
}
for(indeksi = 0; indeksi< (sizeof(kertotaulu) / sizeof(kertotaulu[0])); indeksi++) {
printf("%d", kertotaulu[indeksi]*kertoja);
printf(" ");
}
printf("\n");
}
return 0;
}
and the output is:
x 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
3 6 9 12 15 18 21 24 27 30 33 36 39 42 45
4 8 12 16 20 24 28 32 36 40 44 48 52 56 60
5 10 15 20 25 30 35 40 45 50 55 60 65 70 75
6 12 18 24 30 36 42 48 54 60 66 72 78 84 90
7 14 21 28 35 42 49 56 63 70 77 84 91 98 105
8 16 24 32 40 48 56 64 72 80 88 96 104 112 120
9 18 27 36 45 54 63 72 81 90 99 108 117 126 135
10 20 30 40 50 60 70 80 90 100 110 120 130 140 150
11 22 33 44 55 66 77 88 99 110 121 132 143 154 165
12 24 36 48 60 72 84 96 108 120 132 144 156 168 180
13 26 39 52 65 78 91 104 117 130 143 156 169 182 195
14 28 42 56 70 84 98 112 126 140 154 168 182 196 210
15 30 45 60 75 90 105 120 135 150 165 180 195 210 225
kertoja is zero the first time through the loop so your second indeksi loop multiplies each element by zero giving you all of the extra 0's. You could add the second indeksi loop into an else case to avoid this, I'm not sure exactly what output you're looking for however so...
The issue could be fixed by ommitting the second loop for the index 0 as follows.
int main(void)
{
int kertotaulu[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
int kertoja;
int indeksi;
for (kertoja = 0; kertoja <= 15; kertoja++)
{
if (kertoja == 0)
{
printf("x");
printf(" ");
for (indeksi = 0; indeksi < (sizeof(kertotaulu)
/ sizeof(kertotaulu[0])); indeksi++)
{
printf("%d", kertotaulu[indeksi]);
printf(" ");
}
}
else // <-- change
{
for (indeksi = 0; indeksi < (sizeof(kertotaulu)
/ sizeof(kertotaulu[0])); indeksi++)
{
printf("%d", kertotaulu[indeksi] * kertoja);
printf(" ");
}
}
printf("\n");
}
return 0;
}
For the case when kertoja is zero it does it's own loop, but it also continues on to the second loop. A simple new line and continue should fix it.
#include<stdio.h>
int main(void)
{
int kertotaulu[15] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
int kertoja;
int indeksi;
for (kertoja = 0; kertoja <= 15; kertoja++) {
if (kertoja == 0) {
printf("x");
printf(" ");
for (indeksi = 0; indeksi < (sizeof(kertotaulu) / sizeof(kertotaulu[0])); indeksi++) {
printf("%d", kertotaulu[indeksi]);
printf(" ");
}
printf("\n"); // New Line
continue; // Continue, goes to the top of loop again
}
for (indeksi = 0; indeksi < (sizeof(kertotaulu) / sizeof(kertotaulu[0])); indeksi++) {
printf("%d", kertotaulu[indeksi] * kertoja);
printf(" ");
}
printf("\n");
}
return 0;
}

Segmentation fault : Reading values from a text file

In my code I am trying to read values from a .txt file so as to build my adjacency matrix but it keeps on returning a segmentation fault. I don't seem to be able to point out where I am going wrong. Please help.
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <math.h>
#include <limits.h>
#include <iostream>
#define MAX_VERTICES 1024
int global_adj_matrix[MAX_VERTICES][MAX_VERTICES];
int **graph_tree;
int **node_data;
int global_weight;
int number_threads;
int max_nodes;
int random_node;
int max_weight;
int finish_flag;
void readAdjMatrix();
int main(int argc, char *argv[]){
for(int i = 0 ; i < MAX_VERTICES ; i++){
for(int j = 0 ; j < MAX_VERTICES ; j++){
global_adj_matrix[i][j] = 0;
}
}
number_threads = atoi(argv[1]);
max_nodes = 0;
readAdjMatrix();
}
void readAdjMatrix(){
int source, destination, edge_weight;
max_nodes = INT_MIN;
max_weight = INT_MIN;
FILE *file_pointer = fopen("graph.txt", "r");
while(!feof(file_pointer)){
fscanf(file_pointer, "%d", &source);
fscanf(file_pointer, "%d", &destination);
fscanf(file_pointer, "%d", &edge_weight);
global_adj_matrix[source][destination] = edge_weight;
global_adj_matrix[destination][source] = edge_weight;
if(edge_weight > max_weight)
max_weight = edge_weight;
if(destination > max_nodes)
max_nodes = destination;
}
printf("%d %d", max_weight, max_nodes);
for(int i = 0 ; i <= max_nodes ; i++){
for(int j = 0 ; j <= max_nodes ; j++){
printf("%d\t", global_adj_matrix[i][j]);
}
printf("\n");
}
fclose(file_pointer);
}
This is my .txt file
0 1 281
0 2 242
0 3 344
0 4 340
0 5 372
0 6 161
0 7 49
0 8 278
0 10 190
0 11 213
0 12 55
0 13 239
0 14 321
0 15 162
1 0 281
1 2 249
1 3 58
1 4 331
1 5 189
1 6 84
1 7 259
1 9 256
1 11 188
1 12 149
1 13 330
1 14 17
1 15 370
2 0 242
2 1 249
2 3 125
2 4 179
2 5 355
2 6 11
2 7 232
2 8 199
2 9 67
2 10 390
2 12 312
2 13 3
2 14 237
2 15 96
3 0 344
3 1 58
3 2 125
3 4 105
3 5 192
3 6 180
3 7 335
3 8 280
3 9 185
3 10 66
3 11 65
3 13 274
3 14 72
3 15 282
4 0 340
4 1 331
4 2 179
4 3 105
4 5 149
4 6 286
4 7 265
4 8 359
4 9 341
4 10 211
4 11 367
4 12 340
4 13 14
4 14 69
4 15 128
5 0 372
5 1 189
5 2 355
5 3 192
5 4 149
5 6 167
5 7 268
5 8 20
5 9 270
5 10 210
5 11 369
5 12 131
5 13 133
5 15 167
6 0 161
6 1 84
6 2 11
6 3 180
6 4 286
6 5 167
6 7 208
6 8 335
6 9 353
6 10 12
6 11 307
6 12 199
6 13 273
6 14 118
7 0 49
7 1 259
7 2 232
7 3 335
7 4 265
7 5 268
7 6 208
7 8 182
7 9 327
7 10 272
7 11 198
7 12 103
7 13 132
7 15 161
8 0 278
8 2 199
8 3 280
8 4 359
8 5 20
8 6 335
8 7 182
8 9 108
8 10 112
8 11 344
8 12 192
8 13 264
8 14 207
8 15 231
9 1 256
9 2 67
9 3 185
9 4 341
9 5 270
9 6 353
9 7 327
9 8 108
9 10 395
9 11 205
9 12 365
9 13 8
9 14 57
9 15 132
10 0 190
10 2 390
10 3 66
10 4 211
10 5 210
10 6 12
10 7 272
10 8 112
10 9 395
10 11 11
10 12 7
10 13 288
10 14 143
10 15 226
11 0 213
11 1 188
11 3 65
11 4 367
11 5 369
11 6 307
11 7 198
11 8 344
11 9 205
11 10 11
11 12 203
11 13 136
11 14 252
11 15 168
12 0 55
12 1 149
12 2 312
12 4 340
12 5 131
12 6 199
12 7 103
12 8 192
12 9 365
12 10 7
12 11 203
12 13 90
12 14 344
12 15 11
13 0 239
13 1 330
13 2 3
13 3 274
13 4 14
13 5 133
13 6 273
13 7 132
13 8 264
13 9 8
13 10 288
13 11 136
13 12 90
13 14 39
13 15 39
14 0 321
14 1 17
14 2 237
14 3 72
14 4 69
14 6 118
14 8 207
14 9 57
14 10 143
14 11 252
14 12 344
14 13 39
14 15 154
15 0 162
15 1 370
15 2 96
15 3 282
15 4 128
15 5 167
15 7 161
15 8 231
15 9 132
15 10 226
15 11 168
15 12 11
15 13 39
15 14 154
Your segmentation fault is because you're trying to read a nonexistent index in the argument vector of main. If you want to avoid that, you should rewrite it to match something like this:
int main (int argc, const char *argv[]) {
if (argc > 1 && (number_threads = atoi(argv[1]))) {
max_nodes = 0;
readAdjMatrix();
}
return 0;
}
This ensures that you have an argument to convert to begin with, and also that it is a nonzero number. I believe atoi has undefined behavior if it isn't a valid string though, so you should harden against that. You also do some other unnecessary things. For one, this block here:
for(int i = 0 ; i < MAX_VERTICES ; i++){
for(int j = 0 ; j < MAX_VERTICES ; j++){
global_adj_matrix[i][j] = 0;
}
}
is pointless because if you initialize a 2D array as an external/global variable then it is automatically zeroed upon initialization. Only local/automatic variables will be filled with garbage data. Therefore, you can omit it.
Finally, I would also change your while loop to look more or less like this (Credit: Chux for better loop guard).
while(fscanf(file_pointer, "%d %d %d", &source, &destination, &edge_weight) == 3) {
global_adj_matrix[source][destination] = global_adj_matrix[destination][source] = edge_weight;
if(edge_weight > max_weight)
max_weight = edge_weight;
if(destination > max_nodes)
max_nodes = destination;
}
This ensures you correctly scanned the amount of variables necessary per line. And the extended assignment just saves a bit of room.
Hope this fixed the problem you were having.
I am posting my answer by neglecting the bigger code which you have not mentioned in your question. I have trimmed down the unnecessary code. The code is given below.
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#define MAX_VERTICES 1024
int global_adj_matrix[MAX_VERTICES][MAX_VERTICES];
int global_weight,max_nodes,random_node,max_weight;
void readAdjMatrix();
int main()
{
int i,j;
max_nodes = 0;
readAdjMatrix();
return 0;
}
void readAdjMatrix()
{
int source, destination, edge_weight,i,j;
max_nodes = INT_MIN;
max_weight = INT_MIN;
FILE *file_pointer = fopen("graph.txt", "r");
while(!feof(file_pointer))
{
fscanf(file_pointer, "%d", &source);
fscanf(file_pointer, "%d", &destination);
fscanf(file_pointer, "%d", &edge_weight);
global_adj_matrix[source][destination] = global_adj_matrix[destination][source] =edge_weight;
if(destination > max_nodes)
max_nodes = destination;
}
printf( "%d\n", max_nodes);
for( i = 0 ; i <= max_nodes ; i++){
for( j = 0 ; j <= max_nodes ; j++){
printf("%d\t", global_adj_matrix[i][j]);
}
printf("\n");
}
fclose(file_pointer);
}
PS : Simply execute this code with ./a.out with no command line argument. In case you are using the command line argument (as given in your question), please use the following syntax to execute your code :
./a.out "your desired number which works with the bigger code"

Resources