Read matrix from input in C without <iostream> features - c

In C++, I can read a matrix with something like
int main()
{
int i,j,k,n;
float a[10][10]={0},d;
clrscr();
cout<<"No of equations ? "; cin>>n;
cout<<"Read all coefficients of matrix with b matrix too "<<endl;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
cin>>a[i][j];
...
return 0;}
in C I cannot use
#include <iostream>
and related functions as
- clrscr();
- cout<<
- cin>>
How should I fix my code to work in c?

For simple cases like this, using scanf() is not rocket science:
if (scanf("%d", &n) != 1)
…report unexpected EOF or format error…
if (n > 10)
…report that n is too big…
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
if (scanf("%f", &a[i][j]) != 1)
…report unexpected EOF or format error…
Use %f because a is an array of float. Check that you got a value each time you try to read one. You can capture the return from scanf() if you want to distinguish between (premature) EOF and format error.
OTOH, in more complex scenarios, scanf() is extremely hard to use correctly. Use with caution. Consider using fgets() or
getline() along with
sscanf(); it is often easier to control the input handling and usually improves the error reporting.

Here you go:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int n, i, j;
double **M;
// prompt the user to enter number of equations
printf("Enter # of equations:");
if (scanf("%d", &n) != 1 && n > 0) exit(1);
// allocate square n x n matrix
M = (double**) malloc(sizeof(double*) * n);
for (i = 0; i < n; ++i) M[i] = (double*)malloc(sizeof(double)* n);
// prompt user to enter matrix coefficients
printf("Read all coefficients of matrix with b matrix too\n");
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
if (scanf("%lf", &(M[i][j])) != 1) exit(1);
}
}
// print values of matrix
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
printf("%lf ", M[i][j]);
}
printf("\n");
}
// free allocated memory
for (i = 0; i < n; ++i) {
free(M[i]);
}
free(M);
return 0;
}

Related

To printf a matrix

When i want to print a matrix which i input,i can use code:
#include <stdio.h>
int main(void)
{
int n, m; //row and column
printf("Enter row and column:\n");
scanf("%d %d", &n, &m);
int x[n][m];
printf("Enter your matrix:\n");
for (int i = 0; i < n; i++) //input my matrix
{
for (int j = 0; j < m; j++)
{
scanf("%d", &x[i][j]);
}
}
printf("print it:\n");
for (int i = 0; i < n; i++) //print it
{
for (int j = 0; j < m; j++)
{
printf("%d ", x[i][j]);
}
putchar('\n');
}
}
enter image description here(a possible case)
In code above, I have to assign values to the rows and columns of the matrix,which named "n" and "m".
int n, m;
scanf("%d %d", &n, &m);
But now I am asking a way to automatic tally .
Can I get this one directly?
enter image description here
You can simulate a two-dimensional array with a one-dimensional array, if that's what you mean:
#include <stdio.h>
#include <stdlib.h>
#define DIGITS 3
int main(void) { // It's good practice to fill function arguments with void if not planning on using them
/* scanf("%d %d", &n, &m); Using scanf with uninitialised variables will result in
* undefined behaviour if it is unable to convert the input. Using fgets
* is easier to debug, safer, and cleaner.
* I highly recommend this: http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html
*/
char buf[DIGITS+1];
printf("%s", "Enter array rows:");
fgets(buf, DIGITS+1, stdin);
const int n = atoi(buf);
printf("%s", "Enter array columns:");
fgets(buf, DIGITS+1, stdin);
const int m = atoi(buf);
int x[n*m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
printf("Enter array value at %d, %d: ", i, j);
fgets(buf, DIGITS+1, stdin);
x[i+j] = atoi(buf);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
printf("%d ", x[i+j]);
}
printf("\n");
}
}
I'm not really sure as to why you would do this when C supports your two-dimensional array answer equally.
But now I am asking a way to automatic tally. Can I get this one directly?
Yes.
Form a linked-list of lines. Initially the list is empty.
Read the first line of input, the "1 2 3" into a string. Use fgets().
Parse the line to detect the number of values in it.
Append the line to the linked list of lines.
Continue doing so until 1) end-of-file, 2) a blank line or 3) number of integer is not the same as the first (error condition).
Now code has the m (number of values per line) and n, the number of lines.
Form int x[n][m];
Parse the lines for values and save in x.

initialization of arrays while operating with mallocs

Given the following piece of code, I don't understand why do we have to initialize every single row of the matrix when we have already created enough space in the stack.
#include <stdio.h>
#include <stdlib.h>
main() {
int **w;
int i, j;
int m, n;
printf("Number of rows in the matrix: ");
scanf("%d", &m);
printf("Number of columns in the matrix: ");
scanf("%d", &n);
w = (int **)malloc(m * n * sizeof(int));
for (i = 0; i < m; i++)
w[i] = (int *)malloc(n * sizeof(int));
for (i = 0; i < m; i++)
for (j = 0; j < n; j++) {
printf("Element [%d][%d]: ", i + 1, j + 1);
scanf("%d", &w[i][j]);
}
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("Element [%d][%d]: %d\n", i + 1, j + 1, w[i][j]);
}
There are many issues in your code:
space is not allocated on the stack, but from the heap.
in both cases, memory allocated for the objects is uninitialized, which means it is not initialized to anything in particular and can have any value whatsoever. Relying on any particular contents is undefined behavior.
the matrix dimensions and all the matrix elements are read from standard input with scanf(). Yet you do not check for scanf() failure to convert integers from the characters read from stdin, so any invalid or missing input is going to cause undefined behavior at some point in the program.
your matrix is actually structured as an array of pointers to arrays of int, which is fine, but inconsistent with the size arguments used to allocate the first array: w = (int **)malloc(m * n * sizeof(int)); should be
w = malloc(m * sizeof(*w));
you could easily get objects pre-initialized to 0 by using calloc() instead of malloc():
for (i = 0; i < m; i++)
w[i] = calloc(n, sizeof(int));
you should also check for malloc() failure and exit with an appropriate diagnostic message.
main() is an obsolete prototype for the main function. You should either use int main(), int main(void) or int main(int argc, char *argv[])...
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int get_int(void) {
int n;
if (scanf("%d", &n) != 1) {
printf("invalid input\n");
exit(EXIT_FAILURE);
}
return n;
}
void xalloc(size_t size) {
void *p = calloc(size, 1);
if (p == NULL) {
printf("out of memory for %zu bytes\n", size);
exit(EXIT_FAILURE);
}
return p;
}
int main() {
int **w;
int i, j;
int m, n;
printf("Number of rows in the matrix: ");
m = get_int();
printf("Number of columns in the matrix: ");
n = get_int();
w = xalloc(m * sizeof(*w));
for (i = 0; i < m; i++) {
w[i] = xalloc(n * sizeof(int));
}
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
printf("Element [%d][%d]: ", i + 1, j + 1);
w[i][j] = get_int();
}
}
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
printf("Element [%d][%d]: %d\n", i + 1, j + 1, w[i][j]);
}
}
for (i = 0; i < m; i++) {
free(w[i]);
}
free(w);
return 0;
}

Second 'for' loop being ignored after first 'for' loop in program that calculate the scalar product in c

I am trying to scan two vector input from the keyboard, and then create a function that will return the scalar product of the two vectors. However when I run the program, as soon as it scans the first vector in the first for loop, the program ends and the scalar product is 0. I don't understand why it doesn't let me scan the second vector. This is my code:
#include <stdio.h>
#include <stdlib.h>
double scalarproduct(double *v, double *w, int n){
double vw[n];
for(int i = 0; i < n; i++){
vw[i] = (v[i] * w[i]);
}
double scalprod = 0;
for(int i = 0; i < n; i++){
scalprod += vw[i];
}
return scalprod;
}
int main(){
int n;
scanf("%d", &n);
double *v;
v = (double *) malloc(sizeof(double) * n);
double *w;
w = (double *) malloc(sizeof(double) * n);
for(int i = 0; i < 0; i++){
scanf("%lf", &v[i]);
}
for (int i = 0; i < n; i++){
scanf("%lf", &w[i]);
}
printf("Scalar product=%lf\n", scalarproduct(v,w,n));
return 0;
}
This is what the input should look like:
3
1.1
2.5
3.0
1.0
1.0
1.0
However it only lets me input until 3.0, and then the program skips the second for loop to the print statement. How can i fix this?
The first for loop has a typo: for(int i = 0; i < 0; i++) it stops immediately.
It should be:
for (int i = 0; i < n; i++) {
Note also these remarks:
you should check the return values of scanf()
you should check for memory allocation failure
you do not need to store the individual products into a local array, which might be very long and pose problems.
you should free allocated memory.
Here is a corrected and simplified version:
#include <stdio.h>
#include <stdlib.h>
double scalarproduct(double *v, double *w, int n) {
double scalprod = 0;
for (int i = 0; i < n; i++) {
scalprod += v[i] * w[i]
}
return scalprod;
}
int main() {
int n;
if (scanf("%d", &n) == 1 && n > 0) {
double *v = (double *)malloc(sizeof(double) * n);
double *w = (double *)malloc(sizeof(double) * n);
if (v == NULL || w == NULL) {
printf("cannot allocate memory\n");
return 1;
}
for (int i = 0; i < n; i++) {
if (scanf("%lf", &v[i]) != 1) {
printf("invalid input\n");
return 1;
}
}
for (int i = 0; i < n; i++) {
if (scanf("%lf", &w[i]) != 1) {
printf("invalid input\n");
return 1;
}
}
printf("Scalar product=%f\n", scalarproduct(v, w, n));
free(v);
free(w);
}
return 0;
}

Code doesn't read input file correctly

My code doesn't seem to be able to read the input file correctly. It somehow only reads the first line of my matrix and then it inputs the second line under "right hand side" instead of making another line for the matrix under "coefficient matrix". Additionally, it prints the third line under "Initial Guesses" rather than the third line of the matrix.
I'm assuming the error is somewhere in the code that I have posted below but let me know if you believe the code below is correct and somewhere else in my code is where this problem is originating from.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define MAX_DIM 100
#define MAX_ITER 500
#define TOLERANCE 1.e-6
void gauss_seidel(double **a, double *b, double *x, int n);
void print_screen_A_b_x(double **a, double *b, double *x, int n);
void main()
{
int i, j, *ptr, n;
int violation_counter, answer;
int violation_rows[MAX_DIM];
double sum;
double **a;
double *b, *x;
FILE *input_Ptr; //pointer to input file
//Open the input file
input_Ptr = fopen ( "my_input.txt", "r" );
if (input_Ptr == NULL) {
puts("\nInput file was not opened succesfully.\n");
exit(-1);
}
//read size of the problem
fscanf(input_Ptr, "%d", &n);
//dynamic memory allocation
a = (double **) malloc (n * sizeof(double *));
for (i = 0; i < n; i++) {
a[i] = (double *) malloc (n * sizeof(double));
}
b = (double *) malloc (n * sizeof(double));
x = (double *) malloc (n * sizeof(double));
/* read in data */
//n = MAX_DIM + 1;
//while (n > MAX_DIM) {
//fscanf(input_Ptr, "%d", &n);
//}
printf("\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
fscanf(input_Ptr, "%lf", &a[i][j]);
}
for (i = 0; i < n; i++) {
fscanf(input_Ptr, "%lf", &b[i]);
}
for (i = 0; i < n; i++) {
fscanf(input_Ptr, "%lf", &x[i]);
}
printf("\n");
}
fclose(input_Ptr);
print_screen_A_b_x(a, b, x, n);
puts("Solution vector:");
for (i = 0; i < n; i++) {
printf("x[%d] = %10.5f \n", i, x[i]);
//free memory
for (i = 0; i < n; i++) {
free(a[i]);
}
free(a);
free(b);
free(x);
return 0;
}
/* test the convergence criterion */
violation_counter = 0;
for (i = 0; i < n; i++) {
sum = 0.0;
for (j = 0; j < n; j++)
if (i != j)
sum = sum + fabs(a[i][j]);
if (fabs(a[i][i]) < sum) {
violation_rows[violation_counter] = i;
violation_counter = violation_counter + 1;
}
if (a[i][i] == 0.0) {
printf("Found diagonal element equal to zero;
rearrange equations; exiting ...\n");
exit(0);
}
}
if (violation_counter > 0) {
printf("The Gauss-Seidel convergence criterion is violated in %d rows out of %d\n", violation_counter, n);
printf("Specifically, it was violated in rows:\n");
for (i = 0; i < violation_counter; i++)
printf("%d ", violation_rows[i]);
printf("\n");
printf("Enter 1 if you want to continue; any other number to abort : ");
scanf("%d", &answer);
if (answer != 1)
exit(1);
printf("Check results carefully\n\n");
}
/* initialize the solution vector -- initial guesses */
for (i = 0; i < n; i++) {
printf("Enter an initial guess for x[%d] of the solution vector : ", i);
scanf("%lf", &x[i]);
}
/* solve the system */
gauss_seidel(a, b, x, n);
/* output solution */
for (i = 0; i < n; i++)
printf("x[%d]=%f\n", i, x[i]);
printf("\n");
}
/* function to solve a system using Gauss-Seidel */
void gauss_seidel(double **a, double *b, double *x, int n)
{
double maxerror = 1.0e-7;
double iteration_error;
double e, sum, temp;
int i, j;
while (maxerror > 1.e-6) {
iteration_error = 0.0;
for (i = 0; i < n; i++) {
sum = 0.0;
for (j = 0; j < n; j++) {
if (i != j)
sum = sum + (a[i][j] * x[j]);
}
}
temp = (a[i][n] - sum) / a[i][i];
e = fabs((temp - x[i]) / x[i]);
x[i] = temp;
if (e > iteration_error)
iteration_error = e;
}
maxerror = iteration_error;
}
void print_screen_A_b_x(double **a, double *b, double *x, int n)
{
int i, j;
printf("\n Coefficient matrix:\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%10.2f", a[i][j]);
}
printf("\n");
}
printf("\n Right hand side vector:\n");
for (i = 0; i < n; i++) {
printf("%10.2f \n", b[i]);
}
printf("\n Initial guess:\n");
for (i = 0; i < n; i++) {
printf("%10.5f \n", x[i]);
}
return;
}
Add \r\n in your post loop if statement.
You show us:
void gauss_seidel(double a[][MAX_DIM], double b[], double x[], int n)
and:
void print_screen_A_b_x(double **a, double *b, double *x, int n)
You cannot pass the same object as the first argument to both functions; they are (radically) different types, even though you use double subscripts with both. Since you've not shown how the matrix is actually defined, there isn't anything more we can do to help you.
Your compiler should be shrieking at you about one (or both) calls. Heed your compiler. It knows more about C than you do at the moment. It won't object unless there's a serious problem. If by some mischance your compiler was not complaining, then you need to either turn on compilation warnings (and work with C11, or perhaps C99, as the version of the standard — definitely not C90) or get a better compiler.
Analysis of one update
One version of the updated code in the question has input code like this:
// read size of the problem
fscanf(input_Ptr, "%d", &n);
// dynamic memory allocation
a = (double **)malloc(n * sizeof(double *));
for (i = 0; i < n; i++)
{
a[i] = (double *)malloc(n * sizeof(double));
}
b = (double *)malloc(n * sizeof(double));
x = (double *)malloc(n * sizeof(double));
printf("\n");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
fscanf(input_Ptr, "%lf", &a[i][j]);
}
for (i = 0; i < n; i++)
{
fscanf(input_Ptr, "%lf", &b[i]);
}
for (i = 0; i < n; i++)
{
fscanf(input_Ptr, "%lf", &x[i]);
}
printf("\n");
}
The good news is that except for the absence of error checking, the memory allocation looks OK.
The bad news is that under most plausible inferences of what the data looks like, the main input loops are completely wrong. Assuming the value in n is N, the first iteration of the input loop reads N values into a[0] (which is fine), and then reads N values into b (which is fine as far as it goes), and then reads N values into x (which is also fine as far as it goes). The value of i is now n; when it is incremented by the outer loop, i is bigger than n, so the outer loop terminates, but you've only read one row of the main matrix.
Most likely, you should be using:
// read size of the problem
if (fscanf(input_Ptr, "%d", &n) != 1)
…report error and skedaddle…
// Check n for plausibility
if (n < 1 || n > 1000)
…report implausibility and skedaddle…
// dynamic memory allocation
…as before, except you should error check all the allocations…
printf("\n");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if (fscanf(input_Ptr, "%lf", &a[i][j]) != 1)
…report error and skedaddle…
}
}
for (i = 0; i < n; i++)
{
if (fscanf(input_Ptr, "%lf", &b[i]) != 1)
…report error and skedaddle…
}
for (i = 0; i < n; i++)
{
if (fscanf(input_Ptr, "%lf", &x[i]) != 1)
…report error and skedaddle…
}
The fact that you don't check for errors means you don't know when things go wrong. You can't afford not to know when things go wrong, so you can't afford not to check for errors.
skedaddle |skɪˈdad(ə)l|
verb [ no obj. ] informal —
depart quickly or hurriedly; run away.

Comparing arrays in a function

My function countCopies doesn't work even though it gets the right inputs. All it should do is taking an array of integers as an input and then searching through this array for duplicates of the second input x.
int main() {
char intArray[100]; //The integer array can only hold 100 integers
int i, x, j;
printf("Please enter a couple of integers and when you're done enter end. ");
i = 0;
while (scanf("%d", &intArray[i++]) == 1)
/*empty loop*/;
scanf("%*s");
printf("Enter x:");
scanf("%d", &x);
printf("Copies = %d\n", countCopies(intArray, i, x));
}
int countCopies(int a[], int n, int x) {
int count = 0;
int j = 0;
for (j = 0; j < n - 1; j++) {
if (a[j] == x) {
count++;
}
}
return count;
}
The for loop is incorrect: you should change the test to j < n.
The idiomatic for loop in C: for (j = 0; j < n; j++) ... iterates exactly n times, j taking values 0 to n-1 inclusively, which are correspond to exactly all valid positions in an array of n elements.
Note that the array has the wrong element type: it should be int, not char. You should also check for array bounds in the first loop and for conversion success of the last scanf.
Here is a corrected version:
#include <stdio.h>
int countCopies(int a[], int n, int x);
int main(void) {
int intArray[100]; //The integer array can only hold 100 integers
int i, x;
printf("Please enter a series of integers, end the list with the word end.\n");
for (i = 0; i < sizeof(intArray) / sizeof(*intArray); i++) {
if (scanf("%d", &intArray[i]) != 1)
break;
}
if (scanf("%d", &x) == 1) {
printf("too many numbers\n");
return 1;
}
scanf("%*s"); /* skip the end word. Note that any word is OK */
printf("Enter x:");
if (scanf("%d", &x) == 1) {
printf("Copies = %d\n", countCopies(intArray, i, x));
}
return 0;
}
int countCopies(int a[], int n, int x) {
int j, count = 0;
for (j = 0; j < n; j++) {
if (a[j] == x) {
count++;
}
}
return count;
}
To expand on chqrlie's answer,
The code for (i = 0; i < n; i++) {/* do stuff */} executes in the following order:
The variable i is set to zero.
The conditional i < n is tested. If true, the code in /* do stuff */ is executed, otherwise, the loop is exited.
The increment i++ is applied.
Go back to 2.
That means that on the loop iteration when i gets incremented to n, the for loop breaks before the code inside the loop gets executed, so if you're accessing an array with n elements, the last element that gets accessed has the index n - 1. Hence the C loop paradigm that chqrlie mentioned.

Resources