I have a text file that looks like the following.
5
2 7
3 4 2
Basically,
row 1 has 1 element,
row 2 has 2 elements,
row 3 has 3 elements,
...
up to n rows with n elements.
I need to read them, and put into a 2-d array in this fashion:
a[0][0] = 5
a[1][0] = 2
a[1][1] = 7
a[2][0] = 3
a[2][1] = 4
a[2][2] = 2
...
You get the drift.
However I know n (the number of rows) only at run time. How would I go about reading the file into a 2x2 array?
I know I can do the following if I know the number of elements in each line of text, and if that number is the same for each line.
fa = fopen("file.txt", "r");
for(i = 0; i < n; i++) {
fgets(str, 1000, fa);
sscanf(str, "%d %d %d", &a[i][0], &a[i][1], &a[i][2]);
}
fclose(fa);
But it wouldn't help me here as I have varying number of elements in each row.
How do I go about this?
Allocate memory for the array like this:
int** array;
array = malloc(n * sizeof(*array)); /* Assuming `n` is the number of rows */
if(!array) /* If `malloc` failed */
{
fputs(stderr, "Error allocating memory; Bailing out!");
exit(-1);
}
int count = 1;
for(int i = 0; i < n; i++)
{
array[i] = malloc(count * sizeof(**array));
if(!array[i]) /* If `malloc` failed */
{
for(int j = 0; j < i; j++) /* free previously allocated memory */
{
free(array[j]);
}
free(array);
fputs(stderr, "Error allocating memory; Bailing out!");
exit(-1);
}
count++;
}
Then, read data from the file into the array by using:
FILE* fp = fopen("file.txt", "r");
if(!fp)
{
for(int i = 0; i < n; i++) /* free previously allocated memory */
{
free(array[i]);
}
free(array);
fputs(stderr, "Error opening 'file.txt'; Bailing out!");
exit(-1);
}
int max = 1;
for(int i = 0; i < n; i++)
{
for(count = 0; count < max; count++)
{
fscanf(fp, "%d", &array[i][count]);
}
max++;
}
Then print the results:
max = 1;
for(int i = 0; i < n; i++)
{
for(count = 0; count < max; count++)
{
printf("array[%d][%d] = %d", i, count, array[i][count]);
}
max++;
}
And finally, free the allocated memory:
for(int i = 0; i < n; i++)
{
free(array[i]);
}
free(array);
Related
Basically, the input file should look like this:
4
1 2 3 4
2 1 4 3
4 3 2 1
3 4 1 2
Where the first line is the size of the square matrix. However, I can't properly load the input directly into n and then into the matrix. I avoided such problem by creating a "loader" array.
int n, loader[100], p=0;
while(feof(data) == 0) {
if(p == 0) {
fscanf(data, "%d", &n); //taking n
p++;
} else {
fscanf(data, "%d", &loader[p]); //taking matrix values for p>0
p++;
}
}
//loading the matrix
int mat[n][n], o = 1; //o is set to 1, as the loader
//has been loaded from position 1.
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++){
printf("%d\n", loader[o]);
mat[i][j] = loader[o];
o++;
}
}
However, I think it is just unnecessary and there might be a faster way to directly take the matrix size and its values. When I programmed in such way, I received a welcoming Segmentation Fault error.
This code seems to work:
int loadMatrix(char *pth)
{
int i, j, n, **mat, p = 0, num;
FILE *fd;
fd = fopen(pth, "r");
if(fd == NULL) return(-1);
/* Read matrix size */
if(fscanf(fd, "%d", &n) == EOF) return(-1);
printf("Size: %d\n", n);
mat = malloc(n * sizeof(int *));
for(i = 0; i < n; i++) mat[i] = malloc(sizeof(int) * n);
while(fscanf(fd, "%d", &num) != EOF && p < (n * n)) {
mat[p / n][p % n] = num;
p++;
}
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
printf("%d ", mat[i][j]);
}
printf("\n");
}
for(i = 0; i < n; i++) free(mat[i]);
free(mat);
fclose(fd);
return(0);
}
I need to write a program that will allocate the memory for multiplication table. The problem is that single call of malloc, calloc and realloc is limited to 80 bytes and I don't know how to allocate memory stage by stage.
If anyone could help me I would be grateful.
Here is what I have tried already. It works if I allocate the memory for 400 bytes in one call.
int main()
{
int row = 10;
int col = 10;
int w=0;
int k=0;
int *tab = (int *)malloc(row*col*sizeof(int));
if(tab == NULL)
{
printf("Failed to allocate memory");
return 8;
}
int i=0;
for (w=0; w<row; w++)
{
for(k=0; k<col; k++)
{
*(tab+w*col+k) = ++i;
}
}
for (w=0; w<row; w++){
for(k=0; k<col; k++){
printf("%3d ", *(tab+w*col+k) );
}
printf("\n");
}
free(tab);
return 0;
}
Nested mallocs() are what you'll need to use. But, be careful, because you'll also need to use several frees()!
// 80 bytes
int** table = malloc(row * sizeof(int*));
for (int i = 0; i < row; i++) {
// 80 bytes
table[i] = malloc(col * sizeof(int));
}
// The 6th element in the first row is set to 5.
table[0][5] = 5;
i have this small piece of code which i cant get to work.
I am kinda new and i just cant find a mistake i did. Thanks
int main (void)
{
int **array;
int i,j, m;
scanf("%d", &m);
array = malloc(sizeof(int) * (m*m));
for (i = 0; i < m; i++)
{
for (j = 0; j < m; j++)
{
scanf("%d", &array[i][j]);
}
}
for (i = 0; i < m; i++)
{
for (j = 0; j < m; j++)
{
printf("%d", array[i][j]);
}
}
return 0;
}
What you are allocating is an one dimensional array of size m*m but you are using it as if you have allocated a jagged array where each row contains m elements.
You can allocate a bit different way than what you did
array = malloc(sizeof *array * m);
if( array == NULL)
{
// error in malloc
}
for(size_t i =0; i<m; i++)
{
array[i]= malloc(sizeof *array[i] * m);
if( array[i] == NULL)
{
// error
}
}
...
for(size_t i = 0; i<m ; i++)
free(array[i]);
free(array);
Alternatively you can put all the elements in a linear manner using i and j.
int *array;
...
for (i = 0; i < m; i++)
{
for (j = 0; j < m; j++)
{
if( scanf("%d", &array[i*m+j]) != 1){
// error in getting input.
}
}
}
...
free(array);
Same goes with printf also.
Also don't forget to free the memory you have allocated dynamically after you are done working with it.
I am working on a Matrix Multiplication problem and I am dynamically allocating arrays
Here is what I currently have:
global:
int **a;
in my allocatematrix function: (m - row, k - col)
a = (int **)malloc(m * sizeof(int *));
for (i=0; i<m; i++)
{
a[i] = (int *)malloc(k * sizeof(int));
}
// Note that arr[i][j] is same as *(*(arr+i)+j)
// just to test my array allocation is working
for (i = 0; i < m; i++)
{
for (j = 0; j < k; j++)
{
a[i][j] = ++count; // OR *(*(arr+i)+j) = ++count
}
}
for (i = 0; i < m; i++)
{
for (j = 0; j < k; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
// I would like to pass my pointer to pointer
// into a subroutine, such that it transforms the
// the global double array, but it keeps blowing up here
loadMatrix(fp, &a, m, k);
load matrix function:
// read in the file
void loadMatrix(FILE *fp, int ***arr, int size1, int size2)
{
//fp = fopen(name, "r");
if (fp == NULL)
{
printf("Error while opening file!\n");
exit(0);
}
int i, j;
for(i = 0; i < size1; i++)
{
for(j = 0; j < size2; j++)
{
int value = 0;
fscanf(fp, "%d", &value);
printf("Current Value: %d\n", value);
//value = (((arr + i)) + j);
// line below is where I think I have the issue
*(*(*(arr+i)+j)) = value;
}
}
}
sample run: with this line commented ((*(arr+i)+j)) = value;
3 2 3
1 2
3 4
5 6
Current Value: 1
Current Value: 4
Current Value: 2
Current Value: 5
Current Value: 3
Current Value: 6
with out commented out:
3 2 3
1 2
3 4
5 6
Current Value: 1
Current Value: 4
Current Value: 2
Segmentation fault (core dumped)
You don't need a int *** pointer, if you are passing a pointer, the data it points to will be modified by the function, what you can do is this
// read in the file
void loadMatrix(FILE *fp, int **arr, int size1, int size2)
{
if (arr == NULL)
return;
if (fp == NULL)
{
printf("Error while opening file!\n");
exit(0);
}
int i, j;
for (i = 0 ; i < size1 ; i++)
{
for (j = 0 ; j < size2 ; j++)
{
int value = 0;
/* test that fscanf() succeeded reading an integer */
if (fscanf(fp, "%d", &arr[i][j]) != 1)
arr[i][j] = 0; /* this just prevents that arr[i][j] be uninitialized */
}
}
}
Where you say you test your allocation is working, that doesn't test anything, the only test you can performa is the return value from malloc(), if the allocation fails it returns NULL, so testing that your allocation worked is done like this
a = malloc(m * sizeof(int *));
if (a == NULL)
pleaseDoSomethingAboutIt_AllocationFailed_DoNotContinue();
for (i = 0 ; i < m ; i++)
{
a[i] = malloc(k * sizeof(int));
if (a[i] == NULL)
{
while (--i)
free(a[i]);
free(a);
pleaseDoSomethingAboutIt_AllocationFailed_DoNotContinue();
}
}
If the allocation fails, and you still dereference the pointer, like in your test, you will invoke undefined behavior, and hence you can't test for anything, because you can't know what is going to happen.
I'm having trouble with one task.
I need to read two matrices from a text file and multiply them together.
The problem is that I know how to read one matrix but I don't understand how to read the two matrices separated (for example) by two spaces in a file.
Matrix.txt:
1 2 3 1 2 3
4 5 6 4 5 6
7 8 9 7 8 9
Maybe someone could explain me how to do that.
Now i'm trying to read first matrix:
#include <stdlib.h>
#include <stdio.h>
int main(){
FILE *fp;
int eSk = 0, sSk = 0,
matrix1[10][10] = {0}, i, j;
char c;
fp = fopen("matrix.txt", "r+");
while(!feof(fp)) {
while(getc(fp) != ' ') {
fscanf(fp, "%d", &matrix1[eSk][sSk]);
sSk++;
}
eSk++;
}
for(i = 0; i < eSk; i++) {
for(j = 0; j < sSk; j++) {
printf("%d ", matrix1[eSk][sSk]);
}
printf("\n");
}
puts("");
system("pause");
return 0;
}
what's wrong ?
Thank you for any help.
You need to skip the second matrix while reading the first and viceversa. Try this:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *file;
int matrixA[3][3], matrixB[3][3];
int garbage[3];
int i, j, k;
i = j = k = 0;
file = fopen("matrix.txt", "rt");
/* Read the first matrix */
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
fscanf(file, "%d", &matrixA[i][j]);
}
/* Skip the second matrix */
for (k = 0; k < 3; k++) fscanf(file, "%d", &garbage[k]);
}
/* Reposition the stream */
fseek(file, 0, SEEK_SET);
/* Read the second matrix */
for (i = 0; i < 3; i++) {
/* Skip the first matrix */
for (k = 0; k < 3; k++) fscanf(file, "%d", &garbage[k]);
for (j = 0; j < 3; j++) {
fscanf(file, "%d", &matrixB[i][j]);
}
}
/* Multiply them ... */
/* Show first matrix */
for (i = 0; i < 3; i++) {
printf("\n");
for (j = 0; j < 3; j++) {
printf(" %d ", matrixA[i][j]);
}
}
printf("\n");
/* Show second matrix */
for (i = 0; i < 3; i++) {
printf("\n");
for (j = 0; j < 3; j++) {
printf(" %d ", matrixB[i][j]);
}
}
return 0;
}
If the format of the string is standardized, you can read both matrices at one go. For your example above, please find a modified version as below.
int main(){
FILE *fp;
int eSk = 0, sSk = 0, i, j;
int mat1[3][3], mat2[3][3];
char line[256];
char c;
fp = fopen("matrix.txt", "r+");
if(NULL == fp) {
printf("Can't open the file\n");
exit(-1);
}
// Read one line
fgets(line, 256, fp);
while(!feof(fp)) {
// Convert line to array
sscanf(line,"%d %d %d %d %d %d", &mat1[eSk][0], &mat1[eSk][1], &mat1[eSk][2], &mat2[eSk][0], &mat2[eSk][1], &mat2[eSk][2]);
// Increment counter
eSk++;
//Read next line
fgets(line, 256, fp);
}
printf("Matrix1\n");
for(i = 0; i < eSk; i++) {
for(j = 0; j < 3; j++) {
printf("%d ", mat1[i][j]);
}
printf("\n");
}
printf("Matrix2\n");
for(i = 0; i < eSk; i++) {
for(j = 0; j < 3; j++) {
printf("%d ", mat2[i][j]);
}
printf("\n");
}
puts("");
system("pause");
return 0;
}