Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

Zadanie


Rekomendowane odpowiedzi

Opublikowano
Program wczytuje z 2 plików macierze i wykonuje ich mnożenie w pamięci, a wynik zapisuje do nowego pliku. Macierze muszą być ładowane do struktur dynamicznych.

 

Jestem ciekawy waszych propozycji. Zadanie do zrealizowania w c. 

Odrazu mówię - rozwiązałem, nie proszę o pomoc. 

Opublikowano
#define _CRT_SECURE_NO_WARNINGS

#include <Windows.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <math.h>

#define ZRODLO1 "Zrodlowa1.txt"
#define ZRODLO2 "Zrodlowa2.txt"
#define WYNIK "Wynikowa.txt"

int g_Wiersze1, g_Kolumny1, g_Wiersze2, g_Kolumny2;

struct Matrix{
	int Kolumny, Wiersze;
	int** Macierz;
};


int Char2Int(char c){ return c - 48; }
int String2int(char* c){
	int ret = 0;
	int len = strlen(c);
	for (int i = 0; c[i]; i++){
		len--;
		ret += Char2Int(c[i])*pow(10.000, len);
	}
	return ret;
}


//Funkcja generuje macierz do pliku. Nazwy raczej same sie tlumacza
void vGenerujMacierz(const char* NazwaPliku, int Kolumny, int Wiersze, int Maks){
	FILE* temp;
	temp = fopen(NazwaPliku, "w+");
	for (int i = 0; i < Kolumny; i++){
		for (int j = 0; j < Wiersze; j++){
			int t = rand() % (Maks + 1);
			fprintf(temp, "%d\t", t);
		}
		fprintf(temp, "\r\n");
	}
	fclose(temp);
}



Matrix OdczytajMacierz(FILE* pPlik){
	Matrix Mx;
	int Wiersze = 0, Kolumny = 0;
	int** Macierz = (int**)malloc(sizeof(int*));
	Macierz[Wiersze] = (int*)malloc(sizeof(int)*Wiersze + 1);
	char Odczytana;
	do{
		char* Komorka = NULL;
		for (int i = 0;; i++){
			Odczytana = getc(pPlik);
			if (!(Odczytana >= '0' && Odczytana <= '9'))
				break;
			//ciag dalszy komorki
			Komorka = (char*)realloc(Komorka, sizeof(char)*(i + 2));
			Komorka[i] = Odczytana;
			Komorka[i + 1] = 0;
		}
		if (Odczytana == '\t'){
			//koniec komorki
			Kolumny++;
			Macierz[Wiersze] = (int*)realloc(Macierz[Wiersze], Kolumny*sizeof(int));
			Macierz[Wiersze][Kolumny - 1] = String2int(Komorka);
		}
		else if (Odczytana == '\r'){
			//koniec wiersza
			Wiersze++;
			Mx.Kolumny = Kolumny;
			Kolumny = 0;
			Macierz[Wiersze] = (int*)malloc(sizeof(int)*Wiersze + 1);
		}

	} while (Odczytana != EOF);
	Mx.Wiersze = Wiersze;
	Mx.Macierz = Macierz;
	return Mx;
}

void PrintujMacierz(int** Macierz, int Kolumny, int Wiersze){
	printf("\n");
	for (int i = 0; i < Wiersze; i++){
		for (int j = 0; j < Kolumny; j++){
			printf("%d\t", Macierz[i][j]);
		}
		printf("\n");
	}
}

Matrix PomnozMacierze(Matrix Pierwsza, Matrix Druga){
	Matrix Ret;
	Ret.Kolumny = Druga.Kolumny;
	Ret.Wiersze = Pierwsza.Wiersze;
	int** Macierz = (int**)malloc(Pierwsza.Wiersze*sizeof(int*));
	if (Pierwsza.Wiersze != Druga.Kolumny){
		printf("Mnozenie niewykonalne.\n");
		Ret.Kolumny = 0; Ret.Wiersze = 0;
		return Ret;
	}
	for (int i = 0; i < Pierwsza.Wiersze; i++){
		Macierz[i] = (int*)malloc(Druga.Kolumny*sizeof(int));
	}
	int i, j, k;
	for (i = 0; i < Pierwsza.Wiersze; i++)
		for (j = 0; j < Druga.Kolumny; j++)
			Macierz[i][j] = 0;
	for (i = 0; i < Pierwsza.Wiersze; i++)
		for (j = 0; j < Pierwsza.Wiersze; j++)
			for (k = 0; k < Druga.Kolumny; k++)
				Macierz[i][j] = Macierz[i][j] + Pierwsza.Macierz[i][k] * Druga.Macierz[k][j];
	Ret.Macierz = Macierz;
	return Ret;
}

void DrukujMacierzDoPliku(FILE* pPlik, Matrix Macierz){
	for (int i = 0; i < Macierz.Wiersze; i++){
		for (int j = 0; j < Macierz.Kolumny; j++){
			fprintf(pPlik, "%d\t", Macierz.Macierz[i][j]);
		}fprintf(pPlik, "\r\n");
	}
	fclose(pPlik);
}

int main(){
	FILE *fZrodlowy1, *fZrodlowy2, *fDocelowy;
	printf("Podaj wymiar pierwszej macierzy do wygenerowania: \n");
	scanf("%d", &g_Kolumny1);
	scanf("%d", &g_Wiersze1);

	printf("Podaj wymiar drugiej macierzy do wygenerowania: \n");
	scanf("%d", &g_Kolumny2);
	scanf("%d", &g_Wiersze2);


	//Generujemy 2 pliki zrodlowe
	vGenerujMacierz(ZRODLO1, g_Kolumny1, g_Wiersze1, 7);
	vGenerujMacierz(ZRODLO2, g_Kolumny2, g_Wiersze2, 7);

	//Otwieramy pliki
	fZrodlowy1 = fopen(ZRODLO1, "r+");
	fZrodlowy2 = fopen(ZRODLO2, "r+");
	//Tworzymy plik wynikowy
	fDocelowy = fopen(WYNIK, "w+");
	//fprintf(fDocelowy, "COKOLWIEK");
	Matrix Odczytana1 = OdczytajMacierz(fZrodlowy1);
	Matrix Odczytana2 = OdczytajMacierz(fZrodlowy2);

	PrintujMacierz(Odczytana1.Macierz, g_Wiersze1 ,g_Kolumny1 );
	PrintujMacierz(Odczytana2.Macierz, g_Wiersze2, g_Kolumny2);

	Matrix Wynikowa = PomnozMacierze(Odczytana1, Odczytana2);
	if (Wynikowa.Kolumny != 0 && Wynikowa.Wiersze != 0){
		PrintujMacierz(Wynikowa.Macierz, g_Kolumny1, g_Wiersze2);
		DrukujMacierzDoPliku(fDocelowy, Wynikowa);
	}

	fclose(fZrodlowy1);
	fclose(fZrodlowy2);
	fclose(fDocelowy);

	system("pause");
}

Proszę, ale mam już inny pomysł jak to rozwiązać

Opublikowano

Testowałeś z nie kwadratowymi macierzami?

W kodzie zakładasz, że macierze wejściowe jak i wyjściowa są kwadratowe.

To, że macierz wyjściowa musi być kwadratowa wynika z tego, że pomyliłeś kolumny z wierszami w warunku. (Pewnie nie jest to drobne przeoczenie, bo dalszy kod korzysta z tego założenia.)

 

Daruję już sobie ocenę kodu bo to nie od tego temat.

Opublikowano

Testowałeś z nie kwadratowymi macierzami?

W kodzie zakładasz, że macierze wejściowe jak i wyjściowa są kwadratowe.

To, że macierz wyjściowa musi być kwadratowa wynika z tego, że pomyliłeś kolumny z wierszami w warunku. (Pewnie nie jest to drobne przeoczenie, bo dalszy kod korzysta z tego założenia.)

 

Daruję już sobie ocenę kodu bo to nie od tego temat.

 

w sumie chodziło mi właśnie o ocenę kodu. Teraz jak na to patrze to rozwiązałbym to inaczej, zczytałbym plik jako jeden długi ciąg znaków, po ilości karetek i tabulatorów wyznaczył wymiary tablicy, potem usuwam wszystkie znaki nie będące liczbami itd. 

Opublikowano

Jeśli chodzi ci o ocenę kodu to:

 

1. Lepiej zamiast #definów w twoim przypadku przypisać te stringi to zmiennych char* w funkcjach gdzie ich używasz.

2. Nie korzystaj ze zmiennych globalnych jeśli nie musisz. Te 4 zmienne globalne, które zadeklarowałeś równie dobrze mogą być zadeklarowane jako zmienne lokalne w funkcji main.

3. Nie korzystaj z notacji węgierskiej bo w dzisiejszych czasach kiedy można łatwo zobaczyć typ w IDE tylko zaciemnia kod.

3.1. Staraj się używać jednakowej konwencji nazewnictwa w całym projekcie. Polecam poszukać na necie popularnych konwencji.

3.2. Nie mieszaj angielskiego z polskim w nazwach. Korzystaj z tylko jednego.

4. Napisz sobie funkcję do alokowania macierzy o danych wymiarach.

5. Staraj się używać pre zamiast postinkrementacji jeśli postinkrementacja nie jest konieczna.

6. Popraw algorytm mnożenia macierzy.

7. Nie pauzuj konsoli w programach konsolowych jeśli nie jest to konieczne dla jego działania. Programy konsolowe są robione jak sama nazwa wskazuje pod konsolę, a kiedy są uruchamiane z jej poziomu to konsola się nie zamyka po wykonaniu programu.

8. W funkcji string2int zamiast korzystać z funkcji pow z każdym obrotem pętli możesz utworzyć zmienną, którą będziesz mnożył *10 z każdym obrotem pętli.

9. Używaj literów znakowych.

int Char2Int(char c){ return c - 48; }

zamień na czytelniejsze

int Char2Int(char c){ return c - '0'; }

10. Nie jestem pewien, ale w C tak zadeklarowana struktura ma typ 'struct Macierz' a nie samo 'Macierz'. Więc twój kod nie jest poprawnym kodem C. Powinieneś postawić

typedef struct Macierz Macierz;

Przed deklaracją struktury, aby powiedzieć kompilatorowi, że to co zna jako 'struct Macierz' ma też znać jako 'Macierz'.

11. Zamiast to funkcji przekazywać kolejno int** macierz, int kolumny, int wiersze etc to po prostu przekaż całą strukturę.

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...