While starting on a program for getting a matrix's Reduced Row Echelon Form, I transferred my code for printing the array into its own function. As soon as I did this, I got a segfault. What puzzled me though, was the fact that an unrelated variable declaration (commented below) solved the segfault.
#include <stdio.h>
int COLS = 3;
int ROWS = 3;
void PrintArray(int array[][COLS]);
int main (int argc, char**argv) {
int i, ii = 0;
FILE *file;
file = fopen(argv[1], "r");
int array[ROWS][COLS];
fscanf(file, "%d %d", &ROWS, &COLS);
while (!feof(file))
{
fscanf(file, "%d", &array[i][ii]);
ii++;
if (fgetc(file) == '\n') {
i++;
ii = 0;
}
}
int j = 0, k = 0; //This solved the segfault.
PrintArray(array);
printf("\n");
fclose(file);
return 0;
}
void PrintArray(int array[][COLS]) //The printing function
{
int j, k;
for (j = 0; j < ROWS; j++)
{
for (k = 0; k < COLS; k++)
{
printf("%d", array[j][k]);
}
printf("\n");
}
}
After a couple hours of debugging, I eventually figured out that it may have had something to do with the scope of the variables within the for loop.
To illustrate:
int COLS = 3;
int ROWS = 3;
int a; //declared globally
//main
for (a = 0; a < ROWS; a++) {
printf("for loop");
}
works, but as soon as I declare "a" in main:
int COLS = 3;
int ROWS = 3;
//main
int a; //declared in main
for (a = 0; a < ROWS; a++) {
printf("for loop");
}
it doesn't work.
Also, if I replace the global variables with numbers, I still get a segfault, until I remove the line which originally fixed the segfault!
void PrintArray(int array[][3]) //COLS
{
int j = 0, k = 0;
for (j = 0; j < 3; j++) //ROWS
{
for (k = 0; k < 3; k++) //COLS
{
printf("%d", array[j][k]);
}
printf("\n");
}
}
This appears to be as far as I can get to understanding the problem, so your help would be appreciated.
You are getting out of array bounds. The two extra variables lay right after the array on the stack, so you begin corrupting them instead of something else, that's why segfault is “solved” (it's not solved, of course, the bug is still there).
There are severe problems with that code:
Variable i is used without being initialized
The array size is always 3x3. Reading new values for ROWS and COLS does NOT resize the array. If e.g. you have read ROWS=4 and COLS=4 from file, you will corrupt the memory outside of that allocated for array.
Related
I am relatively new to c, and I still have not been able to find a good way of passing and returning a multi-dimensional array from a function. I found the following code, however it doesn't seem like a good way to do things because it passes the array and then to use it, it creates a duplicate with the malloc function. Is there a way to do it without the copying and malloc function, or a better way to pass and return an 2d array from a function in c in general? Thanks.
#include <stdio.h>
#include <stdlib.h>
int **matrix_sum(int matrix1[][3], int matrix2[][3]){
int i, j;
int **matrix3;
matrix3 = malloc(sizeof(int*) * 3);
for(i = 0; i < 3; i++) {
matrix3[i] = malloc(sizeof(int*) * 3);
}
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
matrix3[i][j] = matrix1[i][j] + matrix2[i][j];
}
}
return matrix3;
}
int main(){
int x[3][3], y[3][3];
int **a;
int i,j;
printf("Enter the matrix1: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
scanf("%d",&x[i][j]);
}
}
printf("Enter the matrix2: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
scanf("%d",&y[i][j]);
}
}
a = matrix_sum(x,y); //asigning
printf("The sum of the matrix is: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
printf("%d",a[i][j]);
printf("\t");
}
printf("\n");
}
//free the memory
for(i = 0; i < 3; i++) {
free(a[i]);
}
free(a);
return 0;
}
The array are not copied for agurments. Just pointers to the first elements of them (int[3]) are passed.
To avoid malloc(), you should add another argument to specify the array where the result should be stored.
#include <stdio.h>
void matrix_sum(int matrix3[][3], int matrix1[][3], int matrix2[][3]){
int i, j;
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
matrix3[i][j] = matrix1[i][j] + matrix2[i][j];
}
}
}
int main(){
int x[3][3], y[3][3], a[3][3];
int i,j;
printf("Enter the matrix1: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
scanf("%d",&x[i][j]);
}
}
printf("Enter the matrix2: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
scanf("%d",&y[i][j]);
}
}
matrix_sum(a,x,y);
printf("The sum of the matrix is: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
printf("%d",a[i][j]);
printf("\t");
}
printf("\n");
}
return 0;
}
An array can be declared and used through a reference (pointer)
for instance
char array[] = {'h','e','l', 'l', 'o', '\0'};
char *pointer = array;
the way pointers work can be understood by calling sizeof() on a given type
printf("char:%d\nchar_pointer: %d\n", sizeof(char), sizeof(char*));
which results in the following output.
char:1
char_pointer: 4
these results mean that even though a char has 1byte, its pointer needs 4 in order to be stored in memory thus, they are not the same type.
now in order to pass an array as an argument to a function you have many options
void function1(array[4])
{
//this function can receive an array of four elements and only four elements;
//these types of functions are useful if the algorithm inside the function only works
//with a given size. e.g. matrix multiplication
}
//or
void function2(char array[], int size)
{
//this function can receive an array of elements of unknown size, but you can
//circumvent this by also giving the second argument, the size.
int i;
for(i = 0; i <= size; i++)
{
printf("%c", array[i]);
}
}
In order to use or call any of these functions you could pass the array or a pointer to the array
function2(array, 5);
function2(pointer, 5);
//these results are the same
The same applies to a multidimensional array
void function3(char** multi_dim_array, array_size_first_dim, array_size_second_dim);
//and you can call it by using the same syntax as before;
void main(int argc, char[] argv*)
{
char** multi_dim = malloc(sizeof(char*) * 3);
int i;
for(i = 0; i<=3 ; i++)
{
multi_dim[i] = malloc(sizeof(char) * 4);
}
function3(multi_dim, 3,4);
}
if you want to return a multidimensional array you can just return a pointer
char **malloc_2d_array(int dim1, int dim2)
{
char ** array = malloc(sizeof(char*)*dim1);
int i;
for(i = 0; i<=dim2; i++)
{
array[i] = malloc(sizeof(char) * dim2);
}
return array;
}
as a final note, the reason the code you found, copies the array, is because of functional programming(a way of programming if you will) where a function call cant modify its input, thus it will always create a new value;
First of all this is not gonna be a technical explanation. I am just gonna try and explain what works not why.
For passing a multidimensional array you can use either an array with a defined size as you did in your example code:
void matrix_sum(int matrix3[][3])
Or if you don't want to use a defined size and want to take care of memory usage you can use a pointer to a pointer. For this case you also need to pass the size (unless you are passing NULL-terminated strings). Like this:
void matrix_sum(int **matrix, int size)
BUT for this case you can't call the function with a "normal" array. You need to use a pointer to a pointer or a pointer to an array.
int **matrix;
// make sure to allocate enough memory for this before initializing.
or:
int *matrix[];
For returning an array you can just return a pointer to a pointer like you did in your code example.
But you don't need to return an array, because if you change a value in an array, (in a different function) the value will stay changed in every other function.
A short example for this:
#include <stdio.h>
void put_zeros(int matrix[][3])
{
int i;
int j;
i = 0;
while (i < 3)
{
j = 0;
while (j < 3)
{
matrix[i][j] = 0;
j++;
}
i++;
}
}
void print_matrix(int matrix[][3])
{
int i;
int j;
i = 0;
while (i < 3)
{
j = 0;
while (j < 3)
{
printf("%d ", matrix[i][j]);
j++;
}
printf("\n");
i++;
}
}
int main(void)
{
int matrix_first[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
print_matrix(matrix_first);
put_zeros(matrix_first);
print_matrix(matrix_first);
}
This will print "1 2 3 4 5 6 7 8 9" because that's the first value we assigned.
After calling put_zeros it will contain and print "0 0 0 0 0 0 0 0 0" without the put_zeros returning the array.
1 2 3
4 5 6
7 8 9
0 0 0
0 0 0
0 0 0
I need to make a little project but I completely don't know how. Im giving matrix A of size n, and it have to return me matrix B which is matrix A with zeroed first and penultimate column. All I did is
#include<stdio.h>
#include<math.h>
int main()
{
int i,n,j,;
int tab[n][n];
printf("Size of matrix:");
scanf("%d",&n);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
{
printf("A[%d][%d]=",i,j);
scanf("%lf",&tab[i][j]);
}
printf("Data:");
printf("Matrix A[%d][%d]",n,m);
}
Which I think should let me to type my matrix. What I should do next? Please help me.
There are a lot of errors in your code, the variable m is not declared, the double array is declared with n non-initialized. As the size of matrix is only known at runtime (entered by user), you need to use dynamic memory allocation functions to allocate memory for your matrix.
Try this code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i, j, n;
printf("Size of matrix: ");
scanf("%d", &n);
int *tab = (int*)malloc(sizeof(int)*n*n);
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
printf("A[%d][%d]=",i,j);
scanf("%d",(tab+i*n+j));
}
}
for (i = 0; i < n; i++)
{
*(tab+i*n) = 0;
*(tab+i*n+n-2) = 0;
}
//Print tab
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
printf("%d ", *(tab+i*n+j));
}
printf("\n");
}
return 0;
}
i am having error while running this code
negativenoinmatrix.c:10:16: error: subscripted value is neither array nor pointer nor vector
if(z[i][j]<0)
i want to calculate the number of negative integers in a matrix
#include <stdio.h>
int negnumbers(int *z, int n, int m)
{
int count = 0;
int i = 0;
int j = m - 1;
while (j >= 0 && i < n)
{
if (z[i][j] < 0)
{
count += (j + 1);
i += 1;
}
else
j -= -1;
}
return count;
}
int main()
{
int n = 3, m = 4;
int a[n][m];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
scanf("%d", &a[i][j]);
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
printf("%d ", a[i][j]);
printf("\n");
}
int val = negnumbers((int *) a, 3, 4);
printf("%d", val);
}
The function needs to accept a pointer to an array, not a pointer to a single item. Change it to
int negnumbers(int n, int m, int z[n][m])
...
int val = negnumbers(3, 4, a);
(Where int z[n][m], as per the rule of "array adjustment", will get changed by the compiler internally to a pointer to the first element, int (*z)[m].)
When you pass a 2-d array to a function, at least the 2nd dimension must be specified. Change to this:
int negnumbers(int z[][4],int n,int m)
You can then use this more straightforward approach to counting the negative numbers:
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (z[i][j] < 0)
count++;
}
}
You are calling a pointer z, and also creating a dynamic matrix out of it. So you need to allocate some memory for it which can be done with:
malloc(z[i][j])
Then after you're done, make sure you deallocate the memory now or else you'll have a memory leak, which you can read more about at Memory Leaks wikipedia.
This is done by calling free(...)
Hope this solves the not an array or pointer error!
Being new to C, and this website, I'm unfamiliar with this problem I'm having. I have a 2 dimensional array with [8][8] elements. I'm trying to get the user to enter numbers into the array until finished. The program is far from finished, but I'm stuck on this problem before I can move on. Basically I use a for loop to let the user enter into each element. However, when the first row is complete, it overwrites it's last value onto the first column second row element spot. How can I prevent this from happening: Here's my code:
#include <stdio.h>
#include <string.h>
int Check_rules();
void Print_Array(int array[][8], int size)
{
int i, j;
for (i = 0; i <= size; i++)
{
printf("\n");
for (j = 0; j <= size; j++)
{
printf("%d ",array[i][j]);
}
}
printf("\n\n");
}
int main()
{
int size = 8;
int i, j;
int fullArray[size][size];
int grid1[3][3];
int grid2[3][3];
int grid3[3][3];
int grid4[3][3];
int grid5[3][3];
int grid6[3][3];
int grid7[3][3];
int grid8[3][3];
int grid9[3][3];
for (i = 0; i <= size; i++)
{
for (j = 0; j <= size; j++)
fullArray[i][j] = 0;
}
printf("Want to play a game? Enter values 1-9 starting in row 1 column 1, \nand we will work our way from there. Here's the playing board.\nIt's Sudoku, so follow the rules of the game.\n\n");
for (i = 0; i <= size; i++)
{
printf("\n");
for (j = 0; j <= size; j++)
printf("%d ",fullArray[i][j]);
}
printf("\n\n");
int tmp;
char *keeper = (" ");//space for marker
for (i = 0; i <= size; i++)
{
for (j = 0; j <= size; j++)
{
printf("Enter first value(press 0 and ENTER to skip a box, \nand -1 to cancel game): ");
scanf("%d", &tmp);
if(tmp == -1)
return 0;
fullArray[i][j] = tmp;
Print_Array(fullArray,size);
}
}
return 0;
}
If you run this you'll see my problem when you enter the last value in row 1. It overwrites the second row first column element spot?
Everywhere you have <= size, you actually want < size. This is because C uses 0-based indexes. That means if you have an array with 5 elements, the indexes are 0, 1, 2, 3, 4. In a loop like for (int i = 0; i <= 5; i++), i would get the values 0, 1, 2, 3, 4, 5. That last one is an invalid index into the array. Using i < 5 fixes the problem (ensures i stops before it reaches 5).
Fixed and cleaned up version of your code:
#include <stdio.h>
#include <string.h>
void printArray(int size, int array[][size]) {
for (int i = 0; i < size; i++) {
printf("\n");
for (int j = 0; j < size; j++) {
printf("%d ", array[i][j]);
}
}
printf("\n\n");
}
int main() {
int size = 8;
int fullArray[size][size];
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
fullArray[i][j] = 0;
}
}
printf("Enter values in row 1 column 1, and we will work our way from there. Here's the playing board. \n\n");
printArray(size, fullArray);
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
printf("Enter first value (press 0 and ENTER to skip a box, or -1 to cancel game): ");
int number;
scanf("%d", &number);
if(number == -1) {
return 0;
}
fullArray[i][j] = number;
printArray(size, fullArray);
}
}
return 0;
}
EDIT
To clarify, this is fixed version of the original code in the question. The new code is a bit different, but I think the issue is the same.
I need help. I want to learn how to create and use dynamic matrix which is element of structure, I want to fill matrix with zeros (0) and print it out, I tried many ways but no luck. Here is the code
#include <stdio.h>
#include <stdlib.h>
typedef struct matrica
{
int **mat;
int dim; //this is dimension of squared matrix
}MATRICA;
void form_matrix(MATRICA *matrica);
int main()
{
MATRICA matrix;
form_matrix(&matrix);
return 0;
}
void form_matrix(MATRICA *matrica)
{
int i, j;
MATRICA *br;
do
{
printf("Size of matrix ");
scanf("%d", &br->dim);
}while(br->dim < 4 || br->dim > 6);
matrica->mat = (int **) calloc(br->dim, sizeof(int *));
for(i = 0; i < br->dim; i++)
{
matrica->mat[i] = (int *) calloc(br->dim, sizeof(int));
for(j = 0; j < br->dim; j++)
{
matrica->mat[i][j] = 0;
}
}
for(i = 0; i < br->dim; i++)
for(j = 0; j < br->dim; j++)
printf("%d ", matrica->mat[i][j]);
}
what am I doing wrong, my loop inside function goes only once, can someone explain to me why?
Your program exhibits undefined behavior because you are dereferencing an uninitialized pointer br. You don't need it, you simply need a variable to store your dimension input.
int i, j, dim;
do
{
printf("Size of matrix ");
if (scanf("%d", &dim) != 1) {
printf("scan failed\n");
exit(EXIT_FAILURE);
}
}while(dim < 4 || dim > 6);
matrica->dim = dim;
/* ... replace all instances of br->dim with dim */