#include #include #include #include #include #define _STR(X) #X #define STR(X) _STR(X) #define MAX_FILE_PATH_LENGTH 256 #define MAX_MATRIX_SIZE 500 #define MAX_MATRIX_IN_FILE_SIZE (MAX_MATRIX_SIZE + 2) #define MAX_ITERATION_STEPS 100 typedef struct { int n; double** data; } Matrix; Matrix* createMatrix(void); void freeMatrix(Matrix* matrix); void createMatrixRows(Matrix* matrix, int rows); void printMatrix(Matrix* matrix); typedef struct { int n; double* data; } Vector; Vector* createVector(void); void initVector(Vector* vector, int size); void freeVector(Vector* vector); void printVector(Vector* vector); typedef enum { JACOBI = 0, GAUSS_SEIDEL = 1 } Method; void flushStdin(); bool load(const char* filename, Matrix* A, Vector* b, Vector* x); Vector* solve(Method method, Matrix* A, Vector* b, Vector* x, double e); int readMatrixLine(FILE* file, double* matrixLine, int maxCols); int main(int argc, char* argv[]) { char filePath[MAX_FILE_PATH_LENGTH]; if(argc >= 2) { strncpy(filePath, argv[1], MAX_FILE_PATH_LENGTH); } else { puts("Please enter the path of the file you'd like to open"); int result = scanf("%" STR(MAX_FILE_PATH_LENGTH) "[^\n]", filePath); if(result == EOF || result == 0 || filePath[0] == 0) { return 0; } if(result != 1) { puts("Couldn't read file path - stopping"); return 1; } flushStdin(); } Matrix* matrix = createMatrix(); Vector* b = createVector(); Vector* x = createVector(); int returnCode = 0; while(true) { if(load(filePath, matrix, b, x)) { puts("Data successfully loaded\nMatrix A:"); printMatrix(matrix); puts("Vector b:"); printVector(b); puts("Vector x:"); printVector(x); Vector* result = solve(JACOBI, matrix, b, x, 0.00001); free(result); break; } else { puts("Failed to load data from file.\nEnter new file path or press ctrl-c to exit"); int result = scanf("%" STR(MAX_FILE_PATH_LENGTH) "[^\n]", filePath); if(result == EOF || result == 0 || filePath[0] == 0) { goto end; } if(result != 1) { puts("Couldn't read file path - stopping"); returnCode = 1; goto end; } flushStdin(); } } end: freeMatrix(matrix); freeVector(b); freeVector(x); printf("\nReturning with code %i\n", returnCode); return returnCode; } bool load(const char* filename, Matrix* matrix, Vector* b, Vector* x) { FILE* file = fopen(filename, "r"); if(file == NULL) { printf("Failed to open file \"%s\"\n", filename); return false; } else { double* firstLineBuffer = malloc(sizeof(double) * (MAX_MATRIX_IN_FILE_SIZE)); int colsInFile = readMatrixLine(file, firstLineBuffer, MAX_MATRIX_IN_FILE_SIZE); if(colsInFile == -1) { puts("Unexpected input on line 0"); free(firstLineBuffer); goto failure; } else if(colsInFile == -2) { printf("Exceeded maximum matrix size of %i\n", MAX_MATRIX_SIZE); free(firstLineBuffer); goto failure; } else { // success int cols = colsInFile - 1; initVector(b, cols); initVector(x, cols); b->data[0] = firstLineBuffer[cols]; createMatrixRows(matrix, cols); matrix->data[0] = firstLineBuffer; int colsInLine; for(int i = 1; i < cols; i++) { matrix->data[i] = malloc(sizeof(double) * (colsInFile)); colsInLine = readMatrixLine(file, matrix->data[i], colsInFile); if(colsInLine < 0) { if(i == cols - 1) { printf("Optional parameters are being used\n"); // Matrix is one smaller than assumed cols--; b->n--; x->n--; matrix->n--; free(matrix->data[i]); x->data[0] = 0.4; // Copy b to x memcpy(x->data, b->data, b->n * sizeof(double)); // extract b for(int j = 0; j < cols; j++) { b->data[j] = matrix->data[j][cols]; } goto success; } else { printf("Line %i contains illegal formatting - please fix!\n", i + 1); goto failure; } } else if(colsInLine != colsInFile) { printf("Illegal line length found in line %i\n", i + 1); goto failure; } else { b->data[i] = matrix->data[i][cols]; } } // successful but with no optional parameter // initialize vector x with zeros memset(x->data, 0, cols * sizeof(double)); } } success: fclose(file); return true; failure: fclose(file); return false; } int readMatrixLine(FILE* file, double* matrixLine, int maxCols) { char nextChar = 0; int col = 0; double buffer; while(true) { if(fscanf(file, "%lf", &buffer) != 1) { return -1; } matrixLine[col] = buffer; col++; if(col > maxCols) { return -2; } nextChar = fgetc(file); if(nextChar == EOF || nextChar == '\n') break; } return col; } void flushStdin() { int c; while((c = getchar()) != '\n' && c != EOF && c != 0); } Vector* solve(Method method, Matrix* A, Vector* b, Vector* x, double e) { Vector* vectors = malloc(sizeof(Vector) * (MAX_ITERATION_STEPS + 1)); // MAX_ITERATION_STEPS enthält die maximal zulässige Anzahl an Iterationsschritten (100) // Die einzelnen Vektoren müssen noch mit initVector initialisiert werden // HIER kommt der Code hin ;) // on success // Sei x die Anzahl der durchgeführten Iterationschritte. Dann setzt vectors[x+1].n = 0. Damit weiß das folgende Programm wie viele Schritte getätigt wurden. return vectors; // on failure free(vectors); return NULL; } inline Matrix* createMatrix(void) { Matrix* matrix = malloc(sizeof(Matrix)); matrix->n = 0; return matrix; } inline void createMatrixRows(Matrix* matrix, int rows) { matrix->n = rows; matrix->data = malloc(sizeof(double*) * rows); } inline void freeMatrix(Matrix* matrix) { for(int i = 0; i < matrix->n; i++) { free(matrix->data[i]); } free(matrix->data); free(matrix); } void printMatrix(Matrix* matrix) { for(int i = 0; i < matrix->n; i++) { for(int j = 0; j < matrix->n; j++) { printf("%lf, ", matrix->data[i][j]); } puts(""); } } inline Vector* createVector(void) { Vector* vector = malloc(sizeof(Vector)); vector->n = 0; return vector; } inline void initVector(Vector* vector, int size) { vector->n = size; vector->data = malloc(sizeof(double) * size); } inline void freeVector(Vector* vector) { free(vector->data); free(vector); } void printVector(Vector* vector) { for(int i = 0; i < vector->n; i++) { printf("%lf, ", vector->data[i]); } puts(""); }