Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C] Mnożenie macierzy z predefiniowanych plików tekstowych do pliku

Ostatnio zmodyfikowano 2017-09-23 20:34
Autor Wiadomość
tonill
Temat założony przez niniejszego użytkownika
[C] Mnożenie macierzy z predefiniowanych plików tekstowych do pliku
» 2017-09-23 10:42:43
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.

C/C++
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:

C/C++
#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; //s to suma potrzebna do mnożenia
    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.
P-165145
Luq
» 2017-09-23 19:15:04
Wklej zawartość plików. Alokacja pamięci i jej zwalnianie jest ok.
P-165156
tonill
Temat założony przez niniejszego użytkownika
» 2017-09-23 19:48:06
Zawartość pierwszego pliku: 2 2 2
                            2 2 2

Zawartość drugiego pliku: 2 2
                          2 2
                          2 2

Powinno to dać macierz 12 12
                       12 12 , ale daje 8 8
                                        8 8



Edit: Jak dam więcej niż dwa to wychodzą nienaturalne liczby na przemian minus/plus.

 
P-165157
mateczek
» 2017-09-23 20:29:26
toć rozmiary tablic czytasz z pliku !!!! powinieneś mieć jeszcze rozmiary na początku
!!!
P-165158
tonill
Temat założony przez niniejszego użytkownika
» 2017-09-23 20:34:43
Mateczek, elegancko wyjaśnione. Boże zaś zapomniałem o tym na śmierć hahaha. Dzięki wielkie!!!
P-165159
« 1 »
  Strona 1 z 1