Converting to column major fashion with two dimensional array - c

I am trying to load my matrix so that consecutive numbers will go down the columns using pointer/addressing methods. Currently my program prints the consecutive numbers across the rows.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i,j;
int twodArray[5][5], *twodArrayptr;
int add = 0;
for(i = 0; i < 5; i++)
{
for(j = 0; j < 5; j++)
{
twodArray[i][j]= (i*5) + j;
}
}
twodArrayptr = &(twodArray[0][0]);
for(i = 0; i < 5; i++)
{
for(j = 0; j < 5; j++)
{
printf("%d ", *(twodArrayptr +((i*5)+j)));
}
printf(" \n");
}
}

If your point is to load the matrix with the opposite order, go with 4py's solution, if your point is to make use of the pointer to access the array in column order, then your solution is below.
You were SO CLOSE, your problem is here (you had i and j swapped). To change from row/col major ordering, you can do:
printf (" %2d", *(twodArrayptr + ((j * MAX) + i)));
Also note the main is type int and therefore returns a value.
Putting it together, you could do something like:
#include <stdio.h>
#define MAX 5
int main (void)
{
int i, j, twodArray[MAX][MAX] = {{0}}, *twodArrayptr = (int *)twodArray;
for (i = 0; i < MAX; i++) {
for (j = 0; j < MAX; j++) {
twodArray[i][j] = (i * MAX) + j;
printf (" %2d", twodArray[i][j]);
}
putchar ('\n');
}
putchar ('\n');
for (i = 0; i < MAX; i++) {
for (j = 0; j < MAX; j++)
printf (" %2d", *(twodArrayptr + ((j * MAX) + i)));
putchar ('\n');
}
return 0;
}
Example Use/Output
$./bin/rowcol2d
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
0 5 10 15 20
1 6 11 16 21
2 7 12 17 22
3 8 13 18 23
4 9 14 19 24
Also note:, you do not need to use the variadic function printf to output a single character use putchar instead :)

Change the assignment logic to twodArray[i][j]= (j*5) + i;
Works like a charm.
for(i = 0; i < 5; i++)
{
for(j = 0; j < 5; j++)
{
twodArray[i][j]= (j*5) + i;
}
}

Related

Why is the multiplication doubling in this C loop?

The code is supposed to take inputs to form a 3x3 Matrix and then multiply each term by the diagonal element of that line, but, for some reason that i don't know, it multiplies two times by the diagonal when the column index is bigger than the row index.
#include <stdio.h>
#define R 3
int a[R][R], i, j;
int main(void) {
for (i = 0; i < R; i++) {
for (j = 0; j < R; j++) {
printf("\nInsira o n%i%i ", i, j);
scanf("%i", &a[i][j]);
}
}
for (i = 0; i < R; i++) {
for (j = 0; j < R; j++) {
a[i][j] = a[i][j] * a[i][i];
}
}
for (i = 0; i < R; i++) {
printf("\n");
for (j = 0; j < R; j++) {
printf("%i ", a[i][j]);
}
}
}
input:
9 8 7
6 5 4
3 2 1
output:
81 648 567
30 25 100
3 2 1
The diagonal value for a given row is being changed before that row has been fully multiplied, so once the column goes past the diagonal, the multiplies are using the new value of that diagonal rather than the old value.
You can fix it (and improve the speed) as follows:
for (i = 0; i < R; i++) {
int tmp = a[i][i];
for (j = 0; j < R; j++) {
a[i][j] *= tmp;
}
}
Also, as mentioned, both i and j should be local variables.

Getting wrong output when adding elements in 2D Array

I am studying C programming now, I am not getting correct output when I am adding two elements in array, i am expecting your help to know the issue.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int limit = 0, sum[limit][3];
int a[limit][3];
int b[limit][3];
printf("Enter the size of arrays: \n");
fflush(stdout);
scanf("%d", &limit);
printf("Enter the values of Array 1");
fflush(stdout);
for (int i = 0; i < limit; i++) {
for (int j = 0; j < limit; j++) {
scanf("%d", &a[i][j]);
}
}
printf("Array 1: \n");
fflush(stdout);
for (int i = 0; i < limit; i++) {
for (int j = 0; j < limit; j++) {
printf("%d\t", a[i][j]);
}
printf("\n");
}
printf("Enter the values of Array 2");
fflush(stdout);
for (int i = 0; i < limit; i++) {
for (int j = 0; j < limit; j++) {
scanf("%d", &b[i][j]);
}
}
printf("Array 2: \n");
for (int i = 0; i < limit; i++) {
for (int j = 0; j < limit; j++) {
printf("%d\t", b[i][j]);
}
printf("\n");
}
for (int i = 0; i < limit; i++) {
for (int j = 0; j < limit; j++) {
sum[i][j]= a[i][j] + b[i][j];
}
}
printf("Sum of 2 arrays: \n");
for (int i = 0; i < limit; i++) {
for (int j = 0; j < limit; j++) {
printf("%d\t", sum[i][j]);
}
printf("\n");
}
return EXIT_SUCCESS;
}
Current output:
Enter the size of arrays:
3
Enter the values of Array 1
12
12
12
12
12
12
12
12
12
Array 1:
12 12 12
12 12 12
12 12 12
Enter the values of Array 2
11
11
11
11
11
11
11
11
11
Array 2:
11 11 11
11 11 11
11 11 11
Sum of 2 arrays:
22 22 22
22 22 22
22 22 22
The problem i found that the exact array i gave in code that doesn't workout.
My expected output is:
23 23 23
23 23 23
23 23 23
In:
int limit = 0, sum[limit][3];
int a[limit][3];
int b[limit][3];
limit is 0, your arrays will be:
int sum [0][3];
int a[0][3];
int b[0][3];
They will have space for nothing.
You should declare your arrays only after the limit input.
Also note that the second dimension of the array is fixed at 3, in your inner for cycles, instead of using limit you should use that constant value, otherwise, if limit is 4 or more, your program will access the array outside its bounds, invoking undefined behavior.
There are multiple problems:
the arrays are defined with a dimension set to 0:
int limit = 0, sum[limit][3];
int a[limit][3];
int b[limit][3];
you should define the arrays after you read the value og limit.
the nested loops use an incorrect boundary test:
for (int i = 0; i < limit; i++) {
for (int j = 0; j < limit; j++) {
j should iterate from 0 to 3 excluded.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int limit = 0;
printf("Enter the size of arrays: \n");
fflush(stdout);
if (scanf("%d", &limit) != 1 || limit < 1)
return 1;
int sum[limit][3];
int a[limit][3];
int b[limit][3];
printf("Enter the values of Array 1");
fflush(stdout);
for (int i = 0; i < limit; i++) {
for (int j = 0; j < 3; j++) {
scanf("%d", &a[i][j]);
}
}
printf("Array 1: \n");
fflush(stdout);
for (int i = 0; i < limit; i++) {
for (int j = 0; j < 3; j++) {
printf("%d\t", a[i][j]);
}
printf("\n");
}
printf("Enter the values of Array 2");
fflush(stdout);
for (int i = 0; i < limit; i++) {
for (int j = 0; j < 3; j++) {
scanf("%d", &b[i][j]);
}
}
printf("Array 2: \n");
for (int i = 0; i < limit; i++) {
for (int j = 0; j < 3; j++) {
printf("%d\t", b[i][j]);
}
printf("\n");
}
for (int i = 0; i < limit; i++) {
for (int j = 0; j < 3; j++) {
sum[i][j] = a[i][j] + b[i][j];
}
}
printf("Sum of 2 arrays: \n");
for (int i = 0; i < limit; i++) {
for (int j = 0; j < 3; j++) {
printf("%d\t", sum[i][j]);
}
printf("\n");
}
return EXIT_SUCCESS;
}
In the inner nested loops,j should iterate till j(excluding it) not limit.
Required nested loop should be like-
for (int i = 0; i < limit; i++) {
for (int j = 0; j < 3; j++) {
.
.
}
Tip:Declare your array after getting the input/size of the array from the user.

How to do an operation in two arrays and stock it in one?

I am a new programmer in C and lately i was eager to learn machine learning. I made a program just to understand how kernels work but it turned out it gives me an undefined behaviour error. Problem is most likely in the calculating O array or might be in printing it.
int S[M][N];
srand(time(NULL));
for(i = 0; i < M; i++) {
for(j = 0; j < N; j++) {
S[M][N] =rand() % ARRAY_RANGE;
printf("%d\t", S[M][N]);
}
printf("\n\n");
}
//S[M][N] initialized and printed here. No problem.
int K[3][3];
printf("Enter the kernel: \n");
for( i = 0 ; i<3; i++ ){
for(j = 0; j<3; j++){
scanf("%d", &K[i][j]);
}
}
for( i = 0 ; i<3; i++ ){
for(j = 0; j<3; j++){
printf("%4d", K[i][j]);
}
printf("\n\n\n");
}
unsigned long long int O[M][N] = {{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}};
long int sum,m,n;
for(i = 0; i < M-2 ; i++){
for(j = 0; j < N-2; j++){
for(k = 0; k < 3; k++){
for(l = 0; l < 3; l++){
O[i+1][j+1] += (S[i+l][j+k])*(K[k][l]);
}
}
}
}
for (i=0; i<M; i++){
for(j=0; j<N; j++){
printf("%d", O[i][j]);
}
printf("\n");
}
return 0;
}
It should look like:
0 0 0 0 0
0 *calculated 3 integers of O array* 0
0 *calculated 3 integers of O array* 0
0 *calculated 3 integers of O array* 0
0 0 0 0 0
but instead it gives random really big or really small numbers like"3241242" or "-2431452" where i wrote calculated 3 integers of O array.
-Edited how i initialized S array. I've included stdio.h, stdlib.h, time.h too.
You have a number of small problems (some typo, some not). To begin, the typo related errors are:
S[M][N] =rand() % ARRAY_RANGE;
printf("%d\t", S[M][N]);
Which obviously should be:
S[i][j] = rand() % ARRAY_RANGE;
printf("%d\t", S[i][j]);
You have a conversion specifier mismatch which invokes Undefined Behavior when you attempt to print O (type unsigned long long int) as "%d" (signed int). A proper conversion specifier for long long unsigned would be "%llu".
There is no need to specify zero for every element in O, simply initialize the first element and then all other elements are set zero by default, e.g.
unsigned long long int O[M][N] = {{0}};
See C11 Standard - § 6.7.9 Initialization (p21)
Putting it altogether and adding the headers and defines, you could do something similar to:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define M 5
#define N M
#define ARRAY_RANGE 1000
int main (void) {
int S[M][N];
srand(time(NULL));
for(int i = 0; i < M; i++) {
for(int j = 0; j < N; j++) {
S[i][j] = rand() % ARRAY_RANGE;
printf("%d\t", S[i][j]);
}
printf("\n\n");
}
int K[3][3];
printf("Enter the kernel: \n");
for (int i = 0 ; i<3; i++ ) {
for (int j = 0; j<3; j++) {
scanf("%d", &K[i][j]);
}
}
for (int i = 0 ; i<3; i++ ) {
for (int j = 0; j<3; j++) {
printf("%4d", K[i][j]);
}
printf("\n\n\n");
}
unsigned long long int O[M][N] = {{0}};
for (int i = 0; i < M-2 ; i++) {
for (int j = 0; j < N-2; j++) {
for (int k = 0; k < 3; k++) {
for (int l = 0; l < 3; l++){
O[i+1][j+1] += (S[i+l][j+k])*(K[k][l]);
}
}
}
}
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
printf (" %5llu", O[i][j]);
}
putchar ('\n');
}
return 0;
}
(note: the unused variables long int sum,m,n; were omitted)
Example 3x3 Entered
$ cat dat/3x3.txt
1 2 3
4 5 6
7 8 9
Example Use/Output
$ ./bin/three2d <dat/3x3.txt
445 971 809 962 208
648 547 459 981 634
656 529 534 710 10
796 548 696 998 647
215 857 384 698 54
Enter the kernel:
1 2 3
4 5 6
7 8 9
0 0 0 0 0
0 27643 33359 22960 0
0 26218 33460 27418 0
0 25653 31352 20828 0
0 0 0 0 0
Look things over and let me know if you have further questions.

Calculating and printing the sums of the diagonals of a matrix

This is a program that is supposed to calculate the sum of all the diagonals in the matrix and then print them out.
ex. if the matrix is
1 2 3 4 5
2 3 4 5 6
0 1 1 2 5
5 5 5 5 5
7 8 9 7 7
the output should be
17 13 13 10 5
15 17 13 13 10
14 15 17 13 13
13 14 15 17 13
7 13 14 15 17
#include <stdio.h>
int main()
{
int n, sum=0, i, j, sub_i, sub_j, sub1_i, sub1_j;
scanf("%d ", &n);
int array1[n][n];
for(i=0;i<n;i++){
for(j=0; j<n; j++){
scanf("%d", &array1[i][j]);
}
}
for(i=0; i<n; i++){
for(j=0; j<n; j++){
sub_i=i;
sub_j=j;
sub1_i=i;
sub1_j=j;
sum=0;
if(j>i){
while(sub_j<n){
sum+=array1[sub_i][sub_j];
sub_i++;
sub_j++;
}
while(sub_j<n){
array1[sub_i][sub_j]=sum;
sub1_i++;
sub1_j++;
}
}
if(i>j){
while(sub_i<n){
sum+=array1[sub1_i][sub1_j];
sub_i++;
sub_j++;
}
while(sub1_i<n){
array1[sub1_i][sub1_j]=sum;
sub1_i++;
sub1_j++;
}
}
}
}
for(i=0; i<n; i++){
for(j=0; j<n; j++){
printf("%d ", array1[i][j]);
}
printf("\n");
}
return 0;
}
When i run the program it prints the array as if no value was assigned to the matrix. Can someone point out what is happening?
Quoting the comment by Weather Vane:
The program alters the array it is examining — see array1[sub_i][sub_j]=sum; — and then prints incorrect values, since you can't correctly sum the diagonals of an array that is changing.
The OP already realize that
... what you are telling me is to assign the values to another array and print that.
Yes, that is way easier:
#include <stdio.h>
int main(void)
{
int n;
// Checking the input is always a good idea, but you
// may prefer something less brutal, in case of error
if (scanf("%d", &n) != 1 || n < 1)
return 1;
int mat[n][n];
for (int i = 0; i < n; ++i) {
for (int j= 0; j < n; ++j) {
if (scanf("%d", &mat[i][j]) != 1)
return 1;
}
}
// Calculate and store the sum of the diagonals. Note that
// it could be done in the previous loop, but it may be better
// to refactor those snippets into separate functions.
int diagonals[2 * n + 1];
for (int i = 0; i < 2 * n + 1; ++i)
diagonals[i] = 0; // consider 'memset' instead of this loop
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
diagonals[n + i - j] += mat[i][j];
}
}
// Now print the correct values in their position
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
printf("%4d", diagonals[n + i - j]);
}
printf("\n");
}
return 0;
}
Testable HERE.
You can do like the follow:
#include <stdio.h>
#define N 5
int main()
{
int array[N][N] = {
1, 2, 3, 4, 5,
2, 3, 4, 5, 6,
0, 1, 1, 2, 5,
5, 5, 5, 5, 5,
7, 8, 9, 7, 7};
for(int i = 1; i < N; ++i)
for(int j = 1; j < N; ++j)
array[i][j] += array[i - 1][j - 1];
for (int i = 0; i + 1 < N; ++i)
for (int j = 0; j + 1 < N; ++j)
if (i == j)
array[i][j] = array[N - 1][N - 1];
else if (i > j)
array[i][j] = array[N - 1][N - 1 - i + j];
else
array[i][j] = array[N - 1 - j + i][N - 1];
for (int i = 0; i < N; ++i) {
for(int j = 0; j < N; ++j)
printf("%d ", array[i][j]);
printf("\n");
}
return 0;
}

How to validate a value in a two-dimensional array?

I have a two-dimensional array of integers and i want to accept only values that are different from those that were already read. I tried to do it this way:
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
printf("Number: ");
scanf("%d", &d[i][j]);
for (k = 0; k < i; k++)
{
for (l = 0; l < j; l++)
{
while (d[i][j] == d[k][l])
{
printf("Number: ");
scanf("%d", &d[i][j]);
}
}
}
}
}
Turns out it doesn't work correctly. How can i make this validation work?
The while statement shouldn't be in the inner loop, because it is only validating against that particular k, l and not against the other indices.
Split out your test into a separate function to test for a duplicate up to i,j:
int duplicateExists(float value, int i, int j)
{
for (k = 0; k <= i; k++)
{
for (l = 0; ((k < i) && (l < 5)) || (l < j); l++)
{
if(d[k][l] == value)
return 1;
}
}
return 0;
}
Then you can validate like this:
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
printf ("Number: ");
scanf ("%d", &d[i][j]);
while (duplicateExists(d[i][j], i, j))
{
printf ("Number: ");
scanf ("%d", &d[i][j]);
}
}
}
The problem is that you are not checking every previously entered value.
So when i == 2 and j == 3, values have been inputted into d[0][0 through 4], d[1][0 through 4], and d[2][0 through 2]. However, because of your for (l = 0; l < j; l++), you are checking d[0][0 through 2], d[1][0 through 2], and d[2][0 through 2].
Let's say your code has reached the inner loop, with some value of i and j.
The "validation" needs to compare d[i][j] against the following sets of values
set1: for k = 0 to i-1 compare with d[k][l] for l = 0 to 5
set2: compare with d[i][l] for l = 0 to j-1
Essentially set1 is about comparing all the rows previously read, and set2 is comparing all preceding elements in the current row.
Your two nested loops are not comparing against the combination/union of those two sets.
Note: it is not a particularly good idea to name a variable l, since it looks like a 1 (numeral one) and it is easy to make typos that are hard to see, but really screw up the meaning of your code.
You should try to change your code like this. Put an 'if', so you can see if the number you wrote is the same, of course you should change my code, but this is the base of the logic.
printf("Number: ");
scanf ("%d", &numb);
for (k = 0; k < i; k++)
{
for (l = 0; l < j; l++)
{
if (numb == d[k][j])
{
printf("Same number, try again\n");
}
else
{
d[i][j] = numb;
}
}
You have missed some of the previous entries because you didn't check the whole of each previous row, and didn't check any of the current row.
int had;
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
do
{
had = 0;
printf ("Number: ");
scanf ("%d", &d[i][j]);
// check previous rows
for (k = 0; k < i; k++)
{
for (l = 0; l < 5; l++) // <--- change end condition
{
if (d[i][j] == d[k][l])
{
had = 1;
continue;
}
}
}
//check this row
for (l = 0; l < j; l++)
{
if (d[i][j] == d[i][l])
{
had = 1;
continue;
}
}
} while (had);
}
}
It will benefit you if you break the task down into a couple of functions as indicated by others. This does away with, at minimum, 4 independent iteration variables for the indexes in the nested loop. After you have your initial array, then your primary goal is to iterate over each value in your original and verify that the new value you are attempting to add to the second doesn't exist in the first.
Take for example an existing array and an empty second array (a and b below):
int a[][ASZ] = {{19, 1,38,51,37},
{95,74,42,23,76},
{17,24,14,22,25},
{11,50,10,84,45},
{78,44,66,46,98}};
int b[ASZ][ASZ] = {{0}};
(Note: any significantly large array, iterating over every value for every addition to the second is very inefficient. To improve the efficient, it would make sense to sort the original (even in a temp array) allowing a bisection/bracketing type search to dramatically cut down on the iterations needed to check for duplicate values)
Checking for duplicates, in its simplest sense could be an integer function taking the original array and the proposed value as arguments (along with the array size) and then comparing the values, returning 1 or 0 for unique or non-unique determinations. Something like the following:
int check_uniq (int a[][ASZ], size_t n, int v)
{
size_t i, j;
for (i = 0; i < n; i++)
for (j = 0; j < ASZ; j++)
if (a[i][j] == v)
return 0;
return 1;
}
(where: ASZ is simply a constant for the row-size of the array)
With a way to check for unique values, filling the array reduces to your basic approach:
/* fill second array with values unique to values in a[][] */
for (i = 0; i < n; i++) {
for (j = 0; j < ASZ; j++) {
for (;;) {
tmp = rand() % 100 + 1;
if (check_uniq (a, n, tmp))
break;
}
b[i][j] = tmp;
}
}
(note: you can use any type of internal loop you prefer. for, while, or do .. while. A simple continual iteration with a break after a unique value is found is as simple as anything else).
Lastly, testing. Rather than having to type proposed values over and over during testing, sometimes it makes sense to set up a simple way to fill the second array with random numbers to allow thorough validation. The following is a short example putting all the pieces together. Hopefully this will help. Let me know if you have any questions:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ASZ 5
int check_uniq (int a[][ASZ], size_t n, int v);
void prn_array (int a[][ASZ], size_t n);
void prn_array_1d (int a[][ASZ], size_t n);
void quick_sort (int *a, size_t n);
int main (void) {
int a[][ASZ] = {{19, 1,38,51,37},
{95,74,42,23,76},
{17,24,14,22,25},
{11,50,10,84,45},
{78,44,66,46,98}};
int b[ASZ][ASZ] = {{0}};
int tmp = 0;
size_t i, j;
const size_t n = sizeof a/sizeof *a;
srand (time (NULL));
/* fill second array with values unique to values in a[][] */
for (i = 0; i < n; i++) {
for (j = 0; j < ASZ; j++) {
for (;;) {
tmp = rand() % 100 + 1;
if (check_uniq (a, n, tmp))
break;
}
b[i][j] = tmp;
}
}
printf ("\n the original array is:\n\n");
prn_array (a, n);
printf ("\n the second array with unique values is:\n\n");
prn_array (b, n);
printf ("\n comparison in sorted 1D array format (easier to check):\n\n");
prn_array_1d (a, n);
printf ("\n");
prn_array_1d (b, n);
printf ("\n\n");
return 0;
}
int check_uniq (int a[][ASZ], size_t n, int v)
{
size_t i, j;
for (i = 0; i < n; i++)
for (j = 0; j < ASZ; j++)
if (a[i][j] == v)
return 0;
return 1;
}
void prn_array (int a[][ASZ], size_t n)
{
size_t i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < ASZ; j++)
printf (" %3d", a[i][j]);
printf ("\n");
}
}
void prn_array_1d (int a[][ASZ], size_t n)
{
size_t i, j;
int tmp [n * ASZ];
for (i = 0; i < n; i++)
for (j = 0; j < ASZ; j++)
tmp [i * ASZ + j] = a[i][j];
quick_sort (tmp, n * ASZ);
for (i = 0; i < n * ASZ; i++)
printf (" %3d", tmp[i]);
}
void quick_sort (int *a, size_t n)
{
int pvt, tmp;
size_t i, j;
if (n < 2) return;
pvt = a[n / 2];
for (i = 0, j = n - 1;; i++, j--)
{
while (a[i] < pvt) i++;
while (pvt < a[j]) j--;
if (i >= j)
break;
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
quick_sort (a, i);
quick_sort (a + i, n - i);
}
Output
$ ./bin/array_2d_fill_uniq
the original array is:
19 1 38 51 37
95 74 42 23 76
17 24 14 22 25
11 50 10 84 45
78 44 66 46 98
the second array with unique values is:
81 16 34 69 65
87 88 35 67 79
89 43 55 18 12
77 83 93 9 99
34 94 75 2 72
comparison in sorted 1D array format (easier to check):
1 10 11 14 17 19 22 23 24 25 37 38 42 44 45 46 50 51 66 74 76 78 84 95 98
2 9 12 16 18 34 34 35 43 55 65 67 69 72 75 77 79 81 83 87 88 89 93 94 99

Resources