Z racji, że jest to mój pierwszy post na forum, to z tego miejsca chciałbym przywitać jego użytkowników.
Po zapoznaniu się z tematem odnośnie zakładanie tematów, postaram się jak najjaśniej przedstawić naturę problemu jaki napotkałem, oraz wkleić tu cały kod i część problematyczną. Program został napisany w Visual Studio 2017.
Założenie programu: Plik wykonywalny.exe mam odpalić poprzez konsolę "cmd" z dwoma argumentami, którymi są nazwy plików .txt, w których znajdują się wcześniej wpisane macierze (czyli w jednym jest jakaś macierz np. 2x3, a w drugim 3x2). Po odpaleniu program ma zapisać wynik mnożenia do trzeciego pliku i oczyścić zaalokowaną pamięć.
Źródłu problemu: Odpalając program jak podałem wyżej wszystkie te operacje wykonują się, jednakże wynik mnożenia jest błędny (macierz 2x3 z samymi dwójkami * macierz 3x2 z samymi dwójkami = macierz 2x2 z samymi ósemkami, a powinny być dwunastki; jeżeli użyje liczb >2 to wtedy dostaje liczby 7 cyfrowe na zmiane na minusie). Czyli, że program wykonuje operacje, ale błędnie.
Moje rozumowanie: Patrząc na kod programu od tyłu i na wszystkie użyte tu pętle FOR, to liczenie macierzy powinno być dobre. Spędziłem nad tym sporo czasu wczoraj, ale wciąż nie byłem w stanie uzyskać poprawnych wyników. Poniżej zamieszcze linijke kodu, która wydaje mi się być przyczyną problemu.
int ** Utworz( int a, int b )
{
int ** tab;
int i, j;
tab =( int ** ) malloc( sizeof( int * ) * a );
for( i = 0; i < a; i++ )
{
tab[ i ] =( int * ) malloc( sizeof( int ) * b );
}
return tab;
}
void Zwolnij( int ** A, int a )
{
for( int i = 0; i < a; i++ )
free( A[ i ] );
free( A );
}
Jest to funkcja, która przygotowuje macierz do mnożenia. Sugerowałem się wypowiedziami zagranicznych użytkowników gdy ją tworzyłem, ale według mnie to ona jest przyczyną.
Cały kod:
#include "stdafx.h"
#include <stdlib.h>
int ** Utworz( int a, int b )
{
int ** tab;
int i, j;
tab =( int ** ) malloc( sizeof( int * ) * a );
for( i = 0; i < a; i++ )
{
tab[ i ] =( int * ) malloc( sizeof( int ) * b );
}
return tab;
}
void Zwolnij( int ** A, int a )
{
for( int i = 0; i < a; i++ )
free( A[ i ] );
free( A );
}
int main( int argc, char * argv[] )
{
int ** A, ** B, ** C, a, b, c, d, s = 0;
FILE * x;
x = fopen( argv[ 1 ], "r" );
fscanf( x, "%d%d", & a, & b );
A = Utworz( a, b );
for( int i = 0; i < a; i++ )
{
for( int j = 0; j < b; j++ )
{
fscanf( x, "%d", & A[ i ][ j ] );
}
}
FILE * y;
y = fopen( argv[ 2 ], "r" );
fscanf( y, "%d%d", & c, & d );
B = Utworz( c, d );
for( int i = 0; i < c; i++ )
{
for( int j = 0; j < d; j++ )
{
fscanf( y, "%d", & B[ i ][ j ] );
}
}
C = Utworz( a, d );
for( int i = 0; i < a; i++ )
{
for( int j = 0; j < d; j++ )
{
for( int k = 0; k < b; k++ )
{
s = s + A[ i ][ k ] * B[ k ][ j ];
}
C[ i ][ j ] = s;
s = 0;
}
}
FILE * z;
z = fopen( "C.txt", "w" );
for( int i = 0; i < a; i++ )
{
for( int j = 0; j < d; j++ )
fprintf( z, "%d\t", C[ i ][ j ] );
fprintf( z, "\n" );
}
fclose( x );
fclose( y );
fclose( z );
Zwolnij( A, a );
Zwolnij( B, c );
Zwolnij( C, a );
printf( "Operacja zakonczona pomyslnie!\n" );
system( "PAUSE" );
return 0;
}
Jeżeli ktoś miałby jakieś pomysły to śmiało pisać, jednakże wolałbym uniknąć sytuacji, gdy miałbym się z kimś kłócić, albo ktoś miałby mnie zrugać z powodu np. braku sprawdzenia (NULL == 0), bo naprawdę zdaje sobie sprawy, że nie ma go w kodzie.
To tyle, pozdrawiam raz jeszcze :)
PS. Po zmianie argv[1-2] na odpowiednio "a.txt" i "b.txt" w funkcjach fopen(), program wywala błąd biblioteki <stdio.h>. Dla jasności wkleje poniżej błąd kompilacji z tej operacji.
#if defined _NO_CRT_STDIO_INLINE
;
#else
{
return __stdio_common_vfscanf( //tu jest blad xxx
_CRT_INTERNAL_LOCAL_SCANF_OPTIONS,
_Stream, _Format, _Locale, _ArgList);
}
#endif
PS2. Poradziłem sobie z problemem ze zmianą argv na a.txt i b.txt, ale program wciąż wykonuje złe obliczenia.