So I coded traditional matrix multiplication in C (I'm a beginner to C), but for some reason my result isn't correct, although I don't see any glaring errors. My input file looks like:
3 2
2 2
2 2
2 2
2 3
1 1 1
1 1 1
The 3 2 and 2 3 in the first and fifth lines represent the number of rows and columns in the subsequent matrices. The result should be a 3x3 matrix, all 4s. However, this code returns
4197299 4 4
4 4 4
-1912599044 32621 572
I'm inclined to believe this might be due to the way I declared the matrices. Instead of using malloc, I scanned the row and column values from the input file and directly instantiated the required matrices. I'm very new to C, so the concept of dynamic memory allocation isn't 100% clear yet. I could be totally off the mark, but I'm not sure. What confuses me especially is that about half of the matrix returned correct values. Why is this the case? Below is my code.
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char** argv){
int i, j, k, row1, col1, row2, col2, temp;
if(argc != 2){
printf("error\n");
exit(1);
}
FILE *file = fopen(argv[1], "r");
if(file == NULL){
printf("error\n");
exit(1);
}
//MATRIX 1
fscanf(file, " %d\t%d", &row1, &col1);
int matrix1[row1][col1];
for(i = 0; i<row1; i++){
for(j=0; j<col1; j++){
fscanf(file, "%d", &temp);
matrix1[i][j] = temp;
}
}
//MATRIX TWO
fscanf(file, " %d\t%d", &row2, &col2);
int matrix2[row2][col2];
int product[row1][col2]; //DECLARING PRODUCT MATRIX
for(i = 0; i<row2; i++){
for(j=0; j<col2; j++){
fscanf(file, "%d", &temp);
matrix2[i][j] = temp;
}
}
for(i = 0; i<row1; i++){
for(j = 0; j<col2; j++){
for(k = 0; k<col1; k++){
product[i][j] += matrix1[i][k]*matrix2[k][j]; //MULTIPLICATION STEP
}
}
}
for(i = 0; i<row1; i++){
for(j = 0; j<col2; j++){
printf("%d\t", product[i][j]); //PRINTING THE PRODUCT
}
printf("\n");
}
return 0;
}
for(i = 0; i<row1; i++){
for(j = 0; j<col2; j++){
product[i][j] = 0; // should be zero before summing
for(k = 0; k<col1; k++){
product[i][j] += matrix1[i][k]*matrix2[k][j]; //MULTIPLICATION STEP
}
}
}
You don't initialize product, which means that its contents is indeterminate, then using it in calculations (with e.g. +=) results in undefined behavior.
You need to initialize the products matrix to all zeroes first.
Yeah, that way of declaring dynamic arrays doesn't necessarily work, in any version before or after C99, although what’s causing the problem is that you don’t initialize product. Try calloc( row1*col2, sizeof(int) ); This allocates all the elements and initializes them to 0.
Related
Suppose I have the following two columns in a data file name data.txt
1 2
3 4
5 6
7 8
9 10
Now, I want to store the first column in one array and the second column in another array by using fscanf. Can someone tell me how to do it?
void main()
{
float a[20] b[20];
int i;
FILE* read = fopen("data.txt","r");
for (int i = 0; i < 10; i++) {
fscanf(read, "%f", &a[i]);
}
for(int i = 0; i < 10; i++) {
printf("%f\n", a[i]);
}
}
The above code does not do the job. Is there any way to do it? I want to store first column in a[] and second in b[].
You should scan first element to a[], then second element to b[]. And so on.
for (int i = 0; i < 10; i++) {
fscanf(read, "%f", &a[i]);
fscanf(read, "%f", &b[i]);
}
I am trying to copy a 1D array of Strings into a 2D array of strings in C.
I was able to achieve this with integer
enter image description here
//Here is what I tried for integers.
int main()
{
int arr[3][3];
int arr2[9]={1,2,3,4,5,6,7,8,9};
int i,j,k=0;
for(i=0; i<3;i++){
for(j=0; j<3;i++){
arr[j][i] = arr2[i];
//rintf("%d\n",arr2[i]);
}
}
for(i=0; i<3; i++) {
for(j=0; j<3; j++)
printf("%2d ", arr[j][i]);
printf("\n");
}
return 0;
}
I changed my data to char and I tried to run the same code I got a segmentation error.
Here is what I have tried so far and it didnt work. error :Segmentation fault (core dumped)
#include<stdio.h>
#include<string.h>
int main()
{
char *d[3][3]; // Destination array
char *s[9]={"orange","apple","table","chair","cable","TV", "124","HI"}; // Source 1 Day array
int i,j,k=0;
for(i=0; i<3;i++){
for(j=0; j<3;i++){
strcpy(d[j][i], s[i]);
}
}
for(i=0; i<3; i++) {
for(j=0; j<3; j++)
printf("%s ", d[j][i]);
printf("\n");
}
return 0;
}
I have made some adjustment and now it print some weird strings
#include<stdio.h>
#include<string.h>
int main() {
char d[3][3] ={0}; // Destination array
char s[9][8]={"orange","apple","table","chair","cable","TV", "124","HI"}; // Source 1 Day array
int i,j,k=0;
for(i=0; i<3;i++){
for(j=0; j<3;j++){
d[j][i] = *s[i];
}
}
for(i=0; i<3; i++) {
for(j=0; j<3; j++)
printf("%s ", &d[j][i]);
printf("\n");
}
return 0;
}
enter image description here
This for loop
for(i=0; i<3;i++){
for(j=0; j<3;i++){
arr[j][i] = arr2[i];
//rintf("%d\n",arr2[i]);
}
}
is incorrect. In the inner loop there are used the same elements arr2[i] where i is changed from 0 to 2 inclusively.
You need to write
for(i=0; i<3;i++){
for(j=0; j<3;i++){
arr[j][i] = arr2[ 3 * i + j];
}
}
Another way to write loops is the following
for ( i = 0; i < 9; i++ )
{
arr[i / 3][i % 3] = arr2[i];
}
As for arrays of pointers of the type char * then the nested loops will look similarly
for(i=0; i<3;i++){
for(j=0; j<3;i++){
d[i][j] = s[ 3 * i + j];
}
}
provided that the array s is declared like
char * s[9]={"orange","apple","table","chair","cable","TV", "124","HI"};
And to output the result array you need to write
for(i=0; i<3; i++) {
for(j=0; j<3; j++)
printf("%s ", d[i][i]);
^^^^^^^
printf("\n");
}
As for your last program then it can look like
#include<stdio.h>
#include<string.h>
int main( void )
{
char d[3][3][8] ={0}; // Destination array
char s[9][8]={"orange","apple","table","chair","cable","TV", "124","HI"}; // Source 1 Day array
for( size_t i = 0; i < 3; i++ )
{
for ( size_t j = 0; j < 3;j++ )
{
strcpy( d[j][i], s[3 * i + j] );
}
}
for ( size_t i = 0; i < 3; i++ )
{
for ( size_t j = 0; j < 3; j++ )
{
printf( "%s ", d[i][j] );
}
putchar( '\n' );
}
return 0;
}
Some issues ...
d is unitialized so the pointers within point to random locations.
To fix, we need to use malloc to get space and then do strcpy. An easier way is to just use strdup. Or, just assign the s value directly.
Your j loop should increment j and not i.
Using s[i] will repeat after three elements. To fix, we can do: s[k++]
You are short one initializer for s (i.e. it is length 9 but you have only 8 strings).
Here is the refactored code:
#include <stdio.h>
#include <string.h>
int
main(void)
{
char *d[3][3]; // Destination array
char *s[9] = {
"orange", "apple", "table", "chair", "cable", "TV", "124", "HI",
#if 1
"raindrops"
#endif
}; // Source 1 Day array
int i, j, k = 0;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
// NOTE/BUG: we must allocate space for d[j][i]
#if 0
strcpy(d[j][i], s[i]);
#else
d[j][i] = strdup(s[k++]);
#endif
}
}
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++)
printf("%s ", d[j][i]);
printf("\n");
}
return 0;
}
Here is the output:
orange apple table
chair cable TV
124 HI raindrops
There's numerous big problems here.
You could have simply solved this with memcpy(arr, arr2, sizeof *arr2);
(Probably the least of your problems, but...) This is badly written performance-wise: for(j=0; j<3;i++){ arr[j][i] = arr2[i]; Multiple loops should always have the inner-most loop work with the inner-most array item, in this case it should have been arr[i][j], or you get needlessly bad data cache performance.
for(j=0; j<3;i++) How about j++.
char *d[3][3]; is an uninitialized 2D array of pointers, each pointing at la-la-land. So you can't copy jack into those addresses - pointers need to point at valid, allocated memory.
char d[3][3] is a 2D array of 3x3 characters, so it can't contain the data you wish to store there, let alone the mandatory null terminators required for strings to work.
char *s[9] = ... In case you meant the 9th item to be NULL, a so-called sentinel value, you should type out NULL explicitly or otherwise the reader can't tell if a NULL sentinel is intended or if you just sloppily added one by accident.
As you can tell from previous comments, the overall slopiness is a recurring major problem here. Take for example:
for(j=0; j<3; j++)
printf("%s ", &d[j][i]);
printf("\n");
Because of sloppy indention, we can't tell if the printf("\n"); was intended to sit inside the inner loop or not (it is not, despite the indention). You can't just type some almost correct stuff down in a hurry. You have to carefully type down actually correct code. There's various myths that great programmers are smart, great at math or abstract thinking etc - in reality, great programmers are careful and disciplined, taking some pride in their own craft.
The quick & dirty fix is to use the second example char* d[3][3] and then instead of strcpy use strdup (currently non-standard, soon to become standard):
for(size_t i=0; i<3; i++){
for(size_t j=0; j<3; j++){
d[i][j] = strdup(s[i]);
}
}
(And ideally also call free() for each item in d at the end.)
But the root problem here is that you need to go back and carefully study arrays, pointers and strings, in that order, before using them.
I have to read the number of rows and columns of a matrix from a txt file also its elements. the first row is the number of rows and columns followed by its numbers. For example this is a matrix with 2 rows and 3 columns containing 123 456 and a matrix with 3 rows and 2 columns.
2 3
1 2 3
4 5 6.
3 2
1 2
3 4
5 6
What I have to do is to read two matrix from the same text file and multiply them. I'm encountering some unknown problem.
When I write my code to test whether the matrix is populated correctly. I only get the first matrix printed and then the program stopped. Output: 1 2 3
4 5 6
Here's the part of the code. Thanks in advance.
int main(){
int **mat1,**mat2,**result;
int row1,col1,row2,col2;
int i,j,k;
FILE *file;
char fname[100];
printf("enter file name\n");
scanf("%s", &fname);
file=fopen(fname, "r");
fscanf(file, "%d %d", &row1,&col1);//row of first matrix
mat1=malloc(row1 * col1 * sizeof(int*));//create memory for first matrix
//reading data for first matrix
for(i=0; i<row1; i++)
{
for(j=0; j<col1; j++)
{
fscanf(file, "%d", &mat1[i][j]);
}
}
for(i=0; i<row1; i++)
{
for(j=0; j<col1; j++)
{
printf("%d\t",mat1[i][j]);
}
printf("\n");
}
fscanf(file,"%d %d", &row2, &col2);//row of second matrix
mat2=malloc(row2 * col2 * sizeof(int*));//create memory for second matrix
//reading data for second matrix
for(i=0; i<row2; i++)
{
for(j=0; j<col2; j++)
{
fscanf(file,"%d",&mat2[i][j]);
}
}
for(i=0; i<row2; i++) //check mat2
{
for(j=0; j<col2; j++)
{
printf("%d\t",mat2[i][j]);
}
printf("\n");
}
I think I fixed the problem, but I had to do quite a bit of debugging due to lots of segfaults, so I'll put the answer to the original question at the top and defer all the things I had to debug to the bottom.
fscanf(file, "%*[.]"); //this is to read the period in the file
fscanf(file,"%d %d", &row2, &col2);//row of second matrix
mat2=malloc(row2 * col2 * sizeof(int*));//create memory for second matrix
By adding that one line of code, it started working for me, but it only started working due to the debugging below.
Since the number of calls to malloc did not represent the number of nested ararys that were indexed, I had to change the declaration of the matrices, the way they were populated, and they way they are referenced.
int *mat1,*mat2;
This declaration is to make the next edits work.
//reading data for first matrix
for(i=0; i<row1; i++)
{
for(j=0; j<col1; j++)
{
fscanf(file, "%d", &(mat1[i*col1 + j]));
}
}
for(i=0; i<row1; i++)
{
for(j=0; j<col1; j++)
{
printf("%d\t",mat1[i*col1 + j]);
}
printf("\n");
}
And of course, for the second matrix;
//reading data for second matrix
for(i=0; i<row2; i++)
{
for(j=0; j<col2; j++)
{
fscanf(file,"%d",&(mat2[i*col2 + j]));
}
}
for(i=0; i<row2; i++) //check mat2
{
for(j=0; j<col2; j++)
{
printf("%d\t",(mat2[i*col2 + j]));
}
printf("\n");
}
Please keep in mind that if you are going to be referencing an array inside of an an array, then you need to malloc space for another array in each slot of the original array. I chose the unintuitive approach to matrix arithmetic, but the code can be augmented to easily allow for double array indexing to be used.
You have some problem with allocating a 2D arrays:
For example:
mat1=malloc(row1 * col1 * sizeof(int*));//create memory for first matrix
it should be
mat1=(int**)malloc(row1 * sizeof(int*));//create memory for first matrix
Then should allocate each row in mat1 in for loop with before scanf each cell in a matrix
for (i = 0; i < row1; i++)
{
mat1[i] = malloc(col1 * sizeof(int));
for (j = 0; j < col1; j++)
{
fscanf(file, "%d", &mat1[i][j]);
}
}
Then, do similar stuff for mat2
Here is my solution that based on original problem:
#include <stdio.h>
#include <stdlib.h>
int main() {
int **mat1, **mat2, **result;
int row1, col1, row2, col2;
int i, j, k;
FILE *file;
char fname[100];
printf("enter file name\n");
scanf("%s", &fname);
file = fopen(fname, "r");
fscanf(file, "%d %d", &row1, &col1);//row of first matrix
mat1 = (int **)malloc(row1 * sizeof(int*));//create memory for first matrix
//reading data for first matrix
for (i = 0; i < row1; i++)
{
mat1[i] = malloc(col1 * sizeof(int));
for (j = 0; j < col1; j++)
{
fscanf(file, "%d", &mat1[i][j]);
}
}
for (i = 0; i < row1; i++)
{
for (j = 0; j < col1; j++)
{
printf("%d\t", mat1[i][j]);
}
printf("\n");
}
fscanf(file, "%d %d", &row2, &col2);//row of second matrix
mat2 = (int **)malloc(row2 * sizeof(int*));//create memory for second matrix
//reading data for second matrix
for (i = 0; i < row2; i++)
{
mat2[i] = malloc(col2 * sizeof(int));
for (j = 0; j < col2; j++)
{
fscanf(file, "%d", &mat2[i][j]);
}
}
for (i = 0; i < row2; i++) //check mat2
{
for (j = 0; j < col2; j++)
{
printf("%d\t", mat2[i][j]);
}
printf("\n");
}
fclose(file);
return 0;
}
I have a program which so far is taking in 4 values 1st is the case, 2nd is basically how many columns, the 3rd value doesn't matter right now and the last value specifies rows.
For some reason when I enter 4 6 4 the program will out put the grid of 0's fine.
When I do 7 6 4, the first 3 columns in the first row contain large nonsense numbers.
When I do 4 6 7 it blatantly crashes.
When I do 8 6 4 the problem is in the first row first 4 columns.
I have no idea what the problem is but I think its somewhere in my 2nd calloc call.
#include <stdio.h>
#include <stdlib.h>
int** makeArray();
int permute();
int main()
{ int cases, slotsToFill, possibleColors,movesMade;
int i;
int j;
int** moves;
scanf("%d", &cases);
for( i = 0; i < cases; i++){
scanf("%d %d %d", &slotsToFill,&possibleColors,&movesMade);
moves = makeArray(movesMade,slotsToFill);
}
/*for(i = 0; i < movesMade; i++){
for(j = 0; j<slotsToFill; j++){
printf(" %d", moves[i][j]);
}
printf("\n");
}*/
system("pause");
return 0;
}
int** makeArray(int rows, int cols){
int** moves;
int i;
int j;
cols = cols + 2;
moves = calloc(rows,sizeof(int*));
if(moves != NULL){
for(i = 0; i < cols; i++){
moves[i] = calloc(cols, sizeof(int));
if(moves[i]== NULL){
printf("ALLOCATION FAILED\n");
break;
}
}
for(i = 0; i < rows; i++){
for(j = 0; j<cols; j++){
printf(" %d", moves[i][j]);
}
printf("\n");
}
}
return moves;
}
i have a file with several rows of 10 integers.
i want to copy those integers into several arrays, named line1, line2, line3 etc with numbers from each row in a corresponding array.
i am currently using
fscanf(items, "%d, %d, %d, %d, %d, %d, %d, %d, %d, %d", &line1[0], &line1[1], &line1[2], &line1[3], &line1[4], &line1[5], &line1[6], &line1[7], &line1[8], &line1[9]);
to assign the first 10 ints to an array named line1.
this is a really sloppy way to do it, and it doesn't tackle the other issue of assigning the rest of the values to other arrays.
any suggestions on how to assign 10 values to an array more neatly, and how to assign each row to a different array would be greatly appreciated!
thanks
Use a multidimensional array and nested loops:
#DEFINE COLS 10
#DEFINE ROWS 10
int i, j;
int line[ROWS][COLS];
for (i = 0; i < ROWS; ++i) {
for (j = 0; i < COLS - 1; ++j) {
fscanf(items, "%d, ", &line[i][j]);
}
fscanf(items, "%d", &line[i][COLS - 1]);
}
Edit:
The code above uses the same format string as the question (comma-separated values).
If space-separated values are ok, you can use a straight loop without the separate fscanf for the last item on each row:
#DEFINE COLS 10
#DEFINE ROWS 10
int i, j;
int line[ROWS][COLS];
for (i = 0; i < ROWS; ++i) {
for (j = 0; i < COLS; ++j) {
fscanf(items, "%d", &line[i][j]);
}
}
Side note:
If you want to write code that detects errors in the input file you need to check the return value from fscanf. Probably not required in a school project, but required in industrial-strength code.
If you know how many lines you have, say 100, you could just:
int arr[r][c];
for (i=0; i<r; i++) {
for (j=0; j<c-1; j++) {
fscanf(file, "%d, ", &arr[i][j]);
}
fscanf(file, "%d\n", &arr[i][j]);
}
You need to use loops.
#include <stdio.h>
for (size_t i = 0; i < 9; ++i)
fscanf("%d, ", &line1[i]);
fscanf("%d", &line[9]);
It would be even better to have a bidimensionnal array.
int a[NLINES][NCOLUMNS];
for (size_t i = 0; i < NLINES; ++i) {
for (size_t j = 0; j < NCOLUMNS - 1; ++j)
fscanf(fp, "%d, ", &a[i][j]);
fscanf(fp, "%d\n", &a[i][NCOLUMNS - 1]);
}