Reputation:
After digging deep into the internet I managed to read all the numbers in my csv to a matrix vector and also for the other single dimension vector from its related csv. The matrix csv file contains a matrix in the following format
91,86,94
12,54,88
79,58,66
The other input vector file contains the members of the one dimension vector as follows
14
20
22
So I expect the output Vector as a result of this multiplication to be for the first row as
91*14+86*20+94*22=5062
Instead of the above my C code is giving me an insane -1469150284
as the member of the first row of the resultant Vector, I suspected the initialization of the two dimension matrix at first but then even after using memset()
to set all elements in the array to 0, I still get the same incorrect values.
The complete code on how I read the csvs and how I load each number into the arrays and how I multiply is provided below, help me trace the bug that is causing the multiplication error
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
//define the three files for reading
FILE *matFile = fopen("test1_input_mat.csv", "r");
FILE *vecFile = fopen("test1_input_vec.csv", "r");
//we are writing to the below file
FILE *outFile = fopen("test1_out_vec.csv", "w");
//make sure the file exists
if (matFile == NULL) {
printf("%s","File does not exist");
//break and return an exit code to the operating system
return 99;
}
//define the dimensions of the matrix
int x = 3;
int y = 3;
//allocate memory to the matrix dynamically
int (*matrix_array)[x] = malloc(sizeof(int[x][y]));
//initialize all the members to zero
memset(matrix_array, 0, sizeof(matrix_array));
//read from the matFile and assign to the vector
char *r, l;
//create a buffer variable for the read file process
char buffer[255];
char line[255] = "";
char *replaced = NULL;
while (fgets(buffer, sizeof(buffer), matFile)) {
strncat(line, buffer, 255);
}
// printf("%s",line);
replaced = replaceWord(line, "\n", ",");
//printf("%s", replaced);
//now that we have the elements of the file in a line
//separated by commas
char delim[] = ",";
char *token;
//get the first token
token = strtok(replaced, delim);
//walk through other tokens
while (token != NULL) {
//parse this and add it to the array
int sub = atoi(token);
//assign the number to th array
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
matrix_array[i][j] = sub;
}
}
token = strtok(NULL, delim);
}
//allocate memory to one dimension array
int *vec = (int *)malloc(3 * sizeof(int));
//section below handles the parsing of numbers from the vector file
char vline[255] = "";
char vbuffer[255];
char concatenated[255];
char *replacing;
//read the vector file
while (fgets(vbuffer, 255, vecFile)) {
strncat(concatenated, vbuffer, sizeof(vbuffer));
}
//replace the new line characters with commas
replacing = replaceWord(concatenated, "\n", ",");
//now parse that into the one dimension vector
char *vtoken;
//get the first token
vtoken = strtok(replacing, delim);
//get the rest of the tokens
while (vtoken != NULL) {
int no = atoi(vtoken);
//append the numbers to the one dimension vector
for (int i = 0; i < 3; i++) {
vec[i] = no;
}
vtoken = strtok(NULL, delim);
}
//this is the section where we do the multiplication of the two
int *out_vec = (int *)malloc(3 * sizeof(int));
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//assign the product of the multiplication to the right index in the vector
out_vec[j] += matrix_array[i][j] * vec[j];
}
}
//write the integers in the second to the out file
char str[255];
char fin[255];
for (int i = 0; i < 3; i++) {
printf("%d\n", out_vec[i]);
}
//close the matFile
fclose(matFile);
}
//method to replace the newline characters with commas
This code helped me replace the new line characters with commas in the single line comprised of all lines in the file
//this method replaces a string in the target string with another string
char *replaceWord(const char *s, const char *oldW,
const char *newW)
{
char *result;
int i, cnt = 0;
int newWlen = strlen(newW);
int oldWlen = strlen(oldW);
// Counting the number of times old word
// occur in the string
for (i = 0; s[i] != '\0'; i++) {
if (strstr(&s[i], oldW) == &s[i]) {
cnt++;
// Jumping to index after the old word.
i += oldWlen - 1;
}
}
// Making new string of enough length
result = (char *)malloc(i + cnt * (newWlen - oldWlen) + 1);
i = 0;
while (*s) {
// compare the substring with the result
if (strstr(s, oldW) == s) {
strcpy(&result[i], newW);
i += newWlen;
s += oldWlen;
} else
result[i++] = *s++;
}
result[i] = '\0';
return result;
}
Upvotes: 1
Views: 99
Reputation: 13533
I have tried to simplify and clean up your code as much as possible.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROWS 3
#define COLS 3
int main(int argc, char* argv[])
{
FILE* matFile = fopen("test1_input_mat.csv", "r");
if (!matFile) {
puts("File does not exist");
return 99;
}
int (*matrix_array)[ROWS] = malloc(sizeof(int[ROWS][COLS]));
char buffer[255];
for (int row = 0; row < ROWS; row++) {
if (fgets(buffer, sizeof(buffer), matFile)) {
char *p = strtok(buffer, ",");
for (int col = 0; col < COLS; col++) {
if (!p) return 99;
matrix_array[row][col] = atoi(p);
p = strtok(NULL, ",");
}
}
}
fclose(matFile);
FILE* vecFile = fopen("test1_input_vec.csv", "r");
if (!vecFile) {
puts("File does not exist");
return 99;
}
int* vec = malloc(ROWS * sizeof(int));
for (int row = 0; row < ROWS; row++) {
if (fscanf(vecFile, "%d", &vec[row]) != 1) return 99;
}
fclose(vecFile);
int* out_vec = calloc(ROWS, sizeof(int));
for (int row = 0; row < ROWS; row++){
for (int col = 0; col < COLS; col++){
out_vec[row] += matrix_array[row][col] * vec[col];
}
}
for (int row = 0; row < ROWS; row++){
printf("%d\n", out_vec[row]);
}
free(matrix_array);
free(vec);
free(out_vec);
return 0;
}
One thing still to do is check the return values from malloc
and calloc
. Though it is unlikely in a small program like this, they can return NULL
Also, since you have hard-coded the size to be 3x3, there is no need for malloc/calloc
.
#define ROWS 3
#define COLS 3
...
int matrix_array[ROWS][COLS];
int vec[ROWS];
int out_vec[ROWS] = {0}
Upvotes: 1