Mnożenie liczb z dwóch tablic - nieprawidłowe wyniki

0

Witam,
Na wstępie chciałbym ostrzec, że pierwszy raz szukam pomocy na forum w takiej sprawie, dlatego mogę popełnić jakieś głupie błędy. Chciałbym poprosić o zerknięcie na mój kod w C (standart C99). Moim zadaniem do wykonania jest opracowanie funkcji obliczających iloczyn dwóch liczb zapisanych w tablicach i następnie wykorzystać je w programie do obliczenia 100! i 1000!. Oto kod:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int* dotablicy(int x, int* licznik2)
{
	int licznik = 1;
	int d = 0;
	int y = x;
	int potega = 0;
	while (y>0)
	{
		potega = pow(10,licznik);
		d = (y % potega);
		y -= d;
		licznik++;
		
	}
	int *wynik;
	wynik = (int *)malloc(licznik*sizeof(int));
	licznik = 1;
	while (x>0)
	{
		potega = pow(10,licznik);
		d = x % potega;
		x -= d;
		d /=pow(10,licznik-1);
		wynik[licznik-1] = d;
		licznik++;	
	}
	wynik[licznik-1] = -1;
	licznik -=2;
	*licznik2 = licznik;
	return wynik;
}

int* mnozenie(const int x[],int y[])
{
	int licznik3 = 0;
	for (int i = 0; x[i]>=0; ++i)
		licznik3++;
	int xrozmiar = licznik3;
	licznik3 = 0;
	for (int i = 0; y[i]>=0; ++i)
		licznik3++;
	int yrozmiar = licznik3;

	int *wynik;
	wynik = (int *)malloc((xrozmiar+yrozmiar)*sizeof(int));
	for (int i = 0; i <= (xrozmiar+yrozmiar); ++i)
	{
		wynik[i] = 0;
		//printf("%d\n",wynik[i] );
	}
	if (xrozmiar > yrozmiar)
	{
		for (int i = 0; x[i]>= 0; ++i)
			for (int j = 0; y[j] >= 0; ++j)
				wynik[j+i] += x[i]*y[j];
	}
	else
	{
		for (int i = 0; y[i] >= 0; ++i)
			for (int j = 0; x[j] >= 0; ++j)
				wynik[j+i] += (x[j]*y[i]);
	}
	int dzielnik = 0;
	for (int i = 0; i <= (xrozmiar+yrozmiar); ++i)
	{
		if (wynik[i]>9)
		{
			dzielnik = wynik[i] / 10;
			wynik[i]-= 10*dzielnik;
			wynik[i+1] = wynik[i+1] + dzielnik;
		}
	}
	wynik[xrozmiar+yrozmiar] = -1;
	printf("%d\n", (xrozmiar+yrozmiar) );
	return wynik;
}

int main()
{	
	int licznik = 1;
	int *silnia;
	silnia = dotablicy(1,&licznik);
	licznik = 1;
	silnia = mnozenie(silnia,dotablicy(2,&licznik));
	for (int i = 3; i < 10; ++i)
	{
		licznik = 1;
		silnia = mnozenie(silnia,dotablicy(i,&licznik));
	}
	int i = 0;
	while(silnia[i]>=0)
	{
		printf("%d",silnia[i] );
		if (i%3==2)
			printf(" ");
		i++;
	}
	printf("\n");
	free (silnia);
	return 0;
}

Program dobrze radzi sobie z mnożeniem, nawet liczb wysokich ale przy 11! ma już spore problemy. Wydaje mi się, że nie wykrywa końca tablicy (oznaczonego -1) i dodaje do śmieci. Nie wiem też czemu cała tablica nie jest zerowana. Najbardziej mi zależy na funkcji mnożenia, bo wydaje mi się ze konwersja do tablicy i main działają ok. Jeśli popełniam jakąś herezje to będę wdzięczny za jej wytknięcie. Z góry dziękuję za wszystkie uwagi i ewentualną pomoc.

2

Niestety program nie zachęca do analizy.

  1. Nazwy zmiennych powinny mieć sens. x, y, d, licznik1, licznik2, licznik3 nie mają.

  2. Istnieje prostszy sposób na wyliczenie ile cyfr ma liczba:

floor(log10(x)) + 1
  1. Jak nie wiesz dlaczego program daje błędne wyniki to wstaw printfy w różne miejsca i sprawdź. Np.
printf("Koniec tablicy: %d\n", licznik-1);
wynik[licznik-1] = -1;
  1. Masz dużo wycieków pamięci (pomyśl ile razy zrobiłeś malloc, a ile razy free).
0

Dzięki za odpowiedź, teraz już będę wiedział na co uważać, jeśli szukam pomocy. Odnośnie zarządzania pamięcią, to jeśli chcę tylko w razie potrzeby powiększać pamięć zarezerwowaną dla danego wskaźnika to mogę używać malloc przy każdym wywołaniu czy istnieje lepszy sposób?

1

Problem jest ciekawy ale wygląda na to ze błędów jest sporo oprócz tych podanych przez twonka.
Debugowałeś to? :)
-w main:
po co wywoływać

 silnia = mnożenie(silnia,dotablicy(2,&licznik)); 

nie możesz zacząć pętli od 2 zamiast od 3?
-brakuje mi tu funkcji np. silnia(int) zamiast kodu bezpośrednio w main:)
-potem w mnożenie, po co ta duplikacja:

  if (xrozmiar > yrozmiar)
    {
        for (int i = 0; x[i]>= 0; ++i)
            for (int j = 0; y[j] >= 0; ++j)
                wynik[j+i] += x[i]*y[j];
    }
    else
    {
        for (int i = 0; y[i] >= 0; ++i)
            for (int j = 0; x[j] >= 0; ++j)
                wynik[j+i] += (x[j]*y[i]);
    }

-mógłbyś zrobić testy swoich funkcji, czy zapisywanie do tabeli działa dla 1,2 albo 3 cyfrowych liczby, tak samo mnożenie, dla kilku wybranych powiedzmy n-cyfrowe * m cyfrowych kombinacji, łatwiej byłoby zlokalizować gdzie robisz błąd wtedy.
-to ciągłe mallocowanie możesz zastąpić jednym, na silnie potrzebna Ci będzie jedna tablica o wielkości sum(log(1..n)) => http://en.wikipedia.org/wiki/Factorial#Rate_of_growth_and_approximations_for_large_n

0

Dzięki wszystkim za pomoc, fajnie że jest takie forum w którym zamiast odesłać cię do Google, ktoś faktycznie się interesuje. Po dłuższych testach biorąc pod uwagę wasze poprawki odkryłem, że funkcja nie działa przy swoim czwartym wywołaniu. Wcześniejsze testy pokazywały mi, że może to być spowodowane śmieciami w pamięci, czyli złym zasięgiem rezerwacji. Po zmianie liniki

wynik = (int *)malloc((xrozmiar+yrozmiar)*sizeof(int));

na wynik = (int *)malloc((xrozmiar+yrozmiar+2)*sizeof(int));

 program działa poprawnie, liczy 100! i 1000! zwracając poprawne wyniki i nie gubiąc się w końcach tablicy. Jeszcze raz dziękuję wszystkim za pomoc i zainsteresowanie, postaram się pisać czytelniejsze programy, żeby w razie czego dało mi się pomóc. Pozdrawiam.

1 użytkowników online, w tym zalogowanych: 0, gości: 1