Saving matrix to a file (.txt format) in C - c

I'm having some issues trying to write a quick program which purpose is, given a matrix (bidimensional array allocated dinamically), saving it to a file. When checking the resulting output file I'm given at the end of each line of the file the following simbols, in bold and red, "\00".
This is my code:
/*\param n number of rows
\param m number of columns
\param mat pointer to the matrix
\param f file already opened in write mode where to write the matrix
*/
int save_to_file (char** mat, unsigned n, unsigned m, FILE* f){
int i, j;
for(i = 0;i <= n; i++)
for(j = 0; j <= m; j++)
if(j == m)
fprintf(f, "%c\n", mat[i][j]);
else
fprintf(f, "%c", mat[i][j]);
if (f == NULL)
return -1;
else
return 0;
}
Is the issue lying in the way I'm writing on the file? If that's the case, can anybody help me to fix it?

The first problem with your code is the range in the for loops. If you have n rows the loop must go from 0 to n-1 (both included). So these lines:
for(i = 0;i <= n; i++)
for(j = 0; j <= m; j++)
if(j == m)
shall be
for(i = 0;i < n; i++) // Remove =
for(j = 0; j < m; j++) // Remove =
if(j == m-1) // Insert -1
The second problem is that you check for f being NULL after you have used f. That is a bad idea and it may/will cause a program crash if f is NULL. Instead do the check as the first thing in the function:
int save_to_file (char** mat, unsigned n, unsigned m, FILE* f){
if (f == NULL) return -1;
....
....
return 0;
}
The third problem is the way you access the matrix. If your matrix is a 2D array (as you write in the text without posting the code), you can't access it correctly as a char**. The char** can be used when you have an array of char-pointers that points to arrays of chars. But not for a 2D array.
Below is an example of how the function could look for a matrix based on a 2D array.
#include <stdio.h>
int save_to_file (unsigned n, unsigned m, char mat[n][m]){
int i, j;
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
if(j == m-1)
printf("%c\n", mat[i][j]);
else
printf("%c", mat[i][j]);
}
int main(void) {
char a[2][3] = {{'a','b','c'},{'d','e','f'}};
save_to_file(2,3,a);
return 0;
}
Output:
abc
def
Notice: The above function prints to stdout instead of a file but that can be easily changed by using fprintf

Related

Displaying the output of a sorted array causes problem

I tried applying bubble sort algorithm to an array of values.
I have 5000 values in my input, from 1 to 5000. I imported values from a text file to create the array, which worked fine. The bubble sort algorithm also worked fine.
The issue is somewhere with the output. Some values do not appear in the output at all, whereas some values are being printed multiple times. I am attaching my code and the image of the output for reference.
#include<stdio.h>
#include<conio.h>
int main() {
FILE * fp;
long int i, j, n, temp;
printf("Enter array size:");
scanf("%ld",&n);
long int array[n];
fp = fopen("5000averagecase.txt", "r");
for (i=0; i < n; ++i)
fscanf(fp,"%ld",&array[i]);
for (i=0; i < n; ++i)
for (j=0; j < n-1-i; ++j)
if (array[j] > array[j+1]) {
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
temp = 0;
}
for (i=0; i< n; ++i)
printf("%ld\t", array[i]);
return(0);
}
https://i.stack.imgur.com/ZbxVU.png
Since your file has only values from 1 to 5000 and I assume they're not sorted in any way, why don't you just make another file like this
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// shuffles an array given a pointer to the array and its length
void shuffleArray(int *array, int len) {
srand(time(NULL));
int n1, n2, tmp;
for(int i = 1;i < len - 1; i++) {
// get random two positions in the array to swap
n1 = rand() % len, n2 = rand() % len;
// just swap'em
tmp = array[n1];
array[n1] = array[n2];
array[n2] = tmp;
}
}
int main() {
FILE * fp = fopen("5000averagecase.txt", "w");
// check for file pointer validity
if(fp == NULL) {
printf("Error: can't open the file!");
exit(0);
}
// creating an array of 5000 number
int arr[5000];
// fill it from 1 to 5000
for(int i = 0;i < 5000; i++) {
arr[i] = i + 1;
}
// shuffle it
shuffleArray(arr, 5000);
// write the array in `5000averagecase.txt` for later use
for(int i = 0;i < 5000; i++) {
fprintf(fp, "%d ", arr[i]);
}
// don't forget to close the file at the end
fclose(fp);
return 0;
}
Now after executing this you get your valid file, and after executing your sorting code on it you see that it works as expected

counting negative integers in a matrix

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!

array counting sort segmentation fault

Hello i am trying to use counting sort to sort numbers that i read from a file. this is my code:
void CountingSort(int array[], int k, int n)
{
int i, j;
int B[100], C[1000];
for (i = 0; i <= k; i++)
{
C[i] = 0;
}
for (j = 1; j <= n; j++)
{
C[array[j]] = C[array[j]] + 1;
}
for (i = 1; i <= k; i++)
{
C[i] = C[i] + C[i-1];
}
for (j = 1; j <= n; j++)
{
B[C[array[j]]] = array[j];
C[array[j]] = C[array[j]] - 1;
}
printf("The Sorted array is : ");
for (i = 1; i <= n; i++)
{
printf("%d ", B[i]);
}
}
void max(int array[],int *k,int n){
int i;
printf("n je %d\n",n);
for (i = 0; i < n; i++)
{
if (array[i] > *k) {
*k = array[i];
}
}
}
int main(int brArg,char *arg[])
{
FILE *ulaz;
ulaz = fopen(arg[1], "r");
int array[100];
int i=0,j,k=0,n,x,z;
while(fscanf(ulaz, "%d", &array[i])!=EOF)i++;
fclose(ulaz);
n=i;
max(array,&k,n);
printf("Max je %d\n",k);
CountingSort(array,k,n);
return 0;
}
i have no errors but when i start my program i get Segmentation fault error. pls help! (dont read this bot is asking me to write some more details but i have none so i just write some random words so i can post my question and hopefully get an answer)
The problem is that your implementation of the counting sort is incorrect: it uses arrays as if they were one-based, while in C they are zero-based.
After carefully going through your loops and fixing all situations where you use a for loop that goes 1..k, inclusive, instead of the correct 0..k-1, the code starts to work fine:
int i, j;
int B[100], C[1000];
for (i = 0; i <= k; i++){
C[i] = 0;
}
for (j = 0; j < n; j++){
C[array[j]]++;
}
for (i = 1; i <= k; i++){
C[i] += C[i-1];
}
for (j = 0; j < n; j++) {
B[--C[array[j]]] = array[j];
}
printf("The Sorted array is : ");
for (i = 0; i < n; i++) {
printf("%d ", B[i]);
}
Demo.
Note: I modified some of the operations to use C-style compound assignments and increments/decrements, e.g. C[array[j]]++ in place of C[array[j]] = C[array[j]] + 1 etc.
The problem most likely is here
int B[100], C[1000]; // C has space for numbers up to 999
...
for (i = 1; i <= k; i++)
C[i] = C[i] + C[i-1]; // adding up till C[k] == sum(array)
for (j = 0; j < n; j++)
B[C[array[j]]] = array[j]; // B has space up to 99, but C[k] is sum(array)
so you're reserving space for C for a highest value of 999 but in B you're assuming that the sum of all input values is less than 100...
the resolution of your problem is to first probe the input array and get the maximum and the sum of all input values (and minimum if the range may be negative) and allocate space accordingly
edit: you probably meant j < n and not j <= n
Adding to dasblinkenlight's spot-on answer:
Is your input data guaranteed to be in the range [0, 999]? If it isn't, it's obvious that segmentation faults can and will occur. Assume that the maximum value of array is 1000. C is declared as
int C[1000];
which means that C's valid indices are 0, 1, 2, ... 999. But, at some point, you will have the following:
C[array[j]] = ... /* whatever */
where array[j] > 999 so you will be attempting an out-of-bounds memory access. The solution is simple: probe array for its maximum value and use dynamic memory allocation via malloc:
/* assuming k is the maximum value */
int * C = malloc((k + 1) * sizeof(int));
Note: an alternative to this, which would also nullify the need for an initialization loop to make all elements of C equal to 0, would be to use calloc, which dynamically allocates memory set to 0.
// allocate C with elements set to 0
int * C = calloc(k + 1, sizeof(int);
Another important factor is the range of your running indices: you seem to have forgotten that arrays in C are indexed starting from 0. To traverse an array of length K, you would do:
for (i = 0; i < K; ++i)
{
processArray(array[i]);
}
instead of
for (i = 1; i <= K; ++i)
{
processArray(array[i]);
}

C Program using Gauss Elimination Method and Partial Pivoting to solve systems of linear algebraic equations

I have a C Program (below) which uses Gauss Elimination Method and Partial Pivoting to solve systems of linear algebraic equations. My friend told me that I should rewrite it. He told me to begin cycles for with 0 instead of 1. Unfortunately I am not in touch with him anymore so he can not explain to me why is his solution better. I tried to rewrite these cycles for but the program does not work right. Maybe it is need to rewrite just some of these cycles not all of them. Would you please explain this problem to me (I want this program to be perfect)?
Systems of linear algebraic equation looks like A*X=B. This program reads input from a file matrix.txt.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
typedef double **Matrix;
typedef double *Row;
typedef double *Col;
typedef double Elem;
Matrix allocate_matrix(int n);
Col allocate_col(int n);
Row allocate_row(int n);
void free_matrix(Matrix M, int n);
void pivot_partial(Matrix A, Col S,Col B, int n);
void forward_elimination(Matrix A,Col B,int n);
Col back_substitution(Matrix A, Col B, int n);
Col scale_factor(Matrix A,int n);
void gauss(Matrix A, Col B, int n);
void swap_rows(Row *r1, Row*r2);
void print_matrix(Matrix M, int n, char * name);
void print_col(Col C, int n, char *name);
void print_row(Row R, int n, char *name);
int main(int argc, char *argv[])
{
FILE *ifp;
int n,i,j;
Matrix A;
Col B;
if(argc < 2)
{
printf("\nInput filename not passed \n");
exit(1);
}
ifp = fopen(argv[1],"r");
if(ifp == NULL)
{
printf("\nCould not open file %s\n",argv[1]);
exit(1);
}
fscanf(ifp,"%i",&n);
printf("A * X = B\n");
printf("\nDimension(A) = %i\n",n);
A = allocate_matrix(n);
for( i = 1; i <= n; ++i)
for(j = 1; j <= n; ++j)
fscanf(ifp,"%lf", &A[i][j]);
B = allocate_col(n);
for(j = 1; j <= n; ++j)
fscanf(ifp,"%lf",&B[j]);
fclose(ifp);
print_matrix(A,n,"A");
print_col(B,n,"B");
gauss(A,B,n);
free_matrix(A,n);
free(B + 1);
getchar();
return 0;
}
void print_matrix(Matrix M, int n, char * name)
{
int i,j;
printf("\n[%s] = ",name);
printf("\n\n");
for(i = 1; i <= n; i++)
{
for(j = 1; j <= n; ++j)
printf("%6lG ",M[i][j]);
printf("\n");
}
}
void print_col(Col C, int n, char * name)
{
int j;
printf("\n[%s] = ",name);
printf("\n\n");
for(j = 1; j <= n; ++j)
printf("%6lg\n",C[j]);
}
void print_row(Row R, int n, char * name)
{
int i;
printf("\n[%s] = ",name);
for(i = 1; i <= n; ++i)
printf("%6lg ",R[i]);
printf("\n");
}
Matrix allocate_matrix(int n)
{
Matrix A;
int i,j;
A = malloc(n * sizeof(Row));
if(!A)
{
printf("\nError : Could not allocate
memory for matrix\n");
exit(1);
}
--A;
for(i = 1; i <= n; ++i)
{
A[i] = malloc(n * sizeof(Elem));
if(!A[i])
{
printf("\nError : Could not allocate
memory for matrix\n");
exit(1);
}
--A[i];
}
return A;
}
void free_matrix(Matrix M, int n)
{
int i;
for(i = 1; i <= n; ++i)
free(M[i] + 1);
free(M + 1);
}
Col allocate_col(int n)
{
Col B;
B = malloc(n * sizeof(Elem));
if(!B)
{
printf("\nError : could not allocate
memory\n");
exit(1);
}
--B;
return B;
}
Row allocate_row(int n)
{
Row B;
B = malloc(n * sizeof(Elem));
if(!B)
{
printf("\nError : could not allocate
memory\n");
exit(1);
}
--B;
return B;
}
Col scale_factor(Matrix A, int n)
{
int i,j;
Col S ;
S = allocate_col(n);
for(i = 1; i <= n; ++i)
{
S[i] = A[i][1];
for(j = 2; j <= n; ++j)
{
if(S[i] < fabs(A[i][j]))
S[i] = fabs(A[i][j]);
}
}
return S;
}
void pivot_partial(Matrix A, Col S,Col B, int n)
{
int i,j;
Elem temp;
for(j = 1; j <= n; ++j)
{
for(i = j + 1; i <= n; ++i)
{
if(S[i] == 0)
{
if(B[i] == 0)
printf("\nSystem doesnt
have a unique solution");
else
printf("\nSystem is
inconsistent");
exit(1);
}
if(fabs(A[i][j]/S[i])>fabs(A[j][j]/S[j]))
{
swap_rows(&A[i],&A[j]);
temp = B[i];
B[i] = B[j];
B[j] = temp;
}
}
if(A[j][j] == 0)
{
printf("\nSingular System Detected\n");
exit(1);
}
}
}
void swap_rows(Row *r1, Row*r2)
{
Row temp;
temp = *r1;
*r1 = *r2;
*r2 = temp;
}
void forward_elimination(Matrix A,Col B,int n)
{
int i,j,k;
double m;
for(k = 1; k <= n-1; ++k)
{
for(i = k + 1; i <= n; ++i)
{
m = A[i][k] / A[k][k];
for(j = k + 1; j <= n; ++j)
{
A[i][j] -= m * A[k][j];
if(i == j && A[i][j] == 0)
{
printf("\nSingular
system detected");
exit(1);
}
}
B[i] -= m * B[k];
}
}
}
Col back_substitution(Matrix A, Col B, int n)
{
int i,j;
Elem sum;
Col X = allocate_col(n);
X[n] = B[n]/A[n][n];
for(i = n - 1; i >= 1; --i)
{
sum = 0;
for(j = i + 1; j <= n; ++j)
sum += A[i][j] * X[j];
X[i] = (B[i] - sum) / A[i][i];
}
return X;
}
void gauss(Matrix A, Col B, int n)
{
int i,j;
Col S, X;
S = scale_factor(A,n);
pivot_partial(A,S,B,n);
forward_elimination(A,B,n);
X = back_substitution(A,B,n);
print_col(X,n,"X");
free(S + 1);
free(X + 1);
}
Arrays in C are naturally indexed starting at 0, not 1. So if you have a[5], you get five slots: a[0], a[1], a[2], a[3], a[4]. So the "first" element of array a is in a[0].
You got around this with a trick. In your allocate functions, you decrement the pointer that is returned from malloc. This has the effect of shifting the array slots over by one. So what a[1] would have referred to is now getting what is in a[0]. That allows you to use the for loops starting a 1 and going up to n.
While the existing code will probably work just fine on any normal system and compiler, it isn't standard C. This is probably what your friend meant about rewriting the code.
If you are going to change it, remove the pointer decrements in the allocate functions, then
change the for loops to go from 0 to n-1 instead of 1 to n.
for (i=0; i < n; i++)
The for loops that don't go from 1 to n, you will have to examine the logic carefully to see if it is correct. Remember, lowest array element is 0, greatest is n-1.
I can see that your code resemble a lot the style introduced (or presented - I don't know whether they have borrowed it) in "Numerical Recipes in C". I really love this book, I own the 1st (yellow) edition, but I have a strong critique to address regarding their idea to let the C syntax resemble Fortran's. The two languages are different and simply Fortran (especially from Fortran90) has a strong dynamic matrix oriented syntax, while C as a light, static, multidimensional syntax.
In particular the two odd points, that are in your code as in Numerical Recipes are:
minor: the "trick", as already pointed out by Gene, of offsetting the arrays to be able to count from 1 to N.
major horror: the idea of allocating a matrix as an array of vectors, to be able to use the syntax A[i][j] with dynamic multidimensional arrays.
I personally think that the problem has been surpassed with C++ (see MTL, matrix template library for example), with which you can present an almost arbitrary interface with an arbitrary efficient implementation.
However I believe that it is wrong to search for a "nice" syntax, when it is not an accepted language best practice (point 1) and especially when it is not performance wise (point 2): using array of arrays means that you are accessing elements by dereferencing two times every time you access one element of the matrix!
IMHO, coming back to C, The correct way - and I often have adapted NR's algorithms to this idea - is that an 2D, M (rows) by N (columns) array must be dynamically allocated as:
float *A = (float*)malloc(M*N*sizeof(float));
And can be accessed both by rows (elements in a row are contiguous in memory, and after the last element of a row, there is the first element of the following row), counting from zero:
for(i=0; i<M; ++i) {
for(j=0; j<N; ++j) {
x = A[i*N + j];
...
}
}
That's how it is more common for the C style: this is how static multidimensional arrays in C works, except for the syntax used to dereference the elements (note: one dereferencing per element).
However it is possible to use the same array "by column" (that's the typical Fortran memory layout):
for(j=0; j<N; ++j) {
for(i=0; i<M; ++i) {
x = A[i + j*M];
...
}
}
Note that I have exchanged the two loops: for performance it's better - whenever possible - to perform the inner loop over contiguous elements (more cache friendly).
One more practical and very important reason to use this style is that optimized BLAS and LAPACK libraries (see ATLAS, libgoto, mkl, acml....) for C use both of these approaches (by rows and by columns), counting from 0, all the time.
To let your code be perfect, I would change the NR's style to a more C conformant style... I hope that's the meaning of the question, and of your friend's comment :)

Need explanation for odd for loop/scope problem

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.

Resources