CRC - Oblicz CRC SPOJ

0

Witam. Napisałem program rozwiązujący zadanie z CRC. (zadanie: http://pl.spoj.com/problems/CRC/) Kompiluje się poprawnie pod Windowsem i Linuxem. Dla danych podanych w zadaniu wyniki są poprawne. Jednak gdy wrzucę program do sprawdzenia ciągle wywala błąd "Segmentation fault". Program odpalałem z gdb i żadnych błędów nie wypluł.
Oto kod:

 #include<stdio.h>
#include<string.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#define N strlen(wielomianBIN)

	char wiadomosc[200], wiadomoscBIN[500], cs[200], wielomian[200], wielomianBIN[200], wielomian2[200];
	int a, e, c;
	int j = 0;
	int i, digits, l = 0;

	typedef	struct str
	{
		char wynik[200];
	} struktura;

	void inttobin(int n) {
		int b = n;
		for (digits = 0; b > 0; b >>= 1) {
			digits++;
		}
		int k = 0;
		for (i = digits - 1; i >= 0; --i) {
			wielomianBIN[i] = n & (1 << k) ? '1' : '0';
			k++;
		}
	}

	void bintohex(struktura *lista) {
		for (i = 0; i < l; i++)
		{
			printf("%X\n", strtol(lista[i].wynik, NULL, 2));
		}
			
	}

	void chartobin(char msg[200]) {
		int j = 0;
		for (i = 0; i < strlen(msg); i++)
		{
			int litera;
			litera = msg[i];
			for (c = 7; c >= 0; c--)
			{
				int k = litera >> c;

				if (k & 1) {
					wiadomoscBIN[j] = '1';
					j++;
				}
				else {
					wiadomoscBIN[j] = '0';
					j++;
				}
			}
		}
	}

	void usun_zera(char msg[200], int liczba) {
		char msg2[200];
		memset(msg2, 0, 200);
		int j = 0;
		int czy_1 = 0;
		for (i = 0; i<liczba; i++) {
			if (msg[i] == '0') {
				if (czy_1 == 1) {
					msg2[j] = (char)msg[i];
					j++;
				}
				else {
					continue;
				}

			}
			else {
				msg2[j] = (char)msg[i];
				j++;
				czy_1 = 1;
			}
		}
		strcpy(wielomianBIN, msg2);
	}

	int sprawdz() {
		int x = strlen(wiadomoscBIN);
		int y = strlen(wielomianBIN);
		for (i = 0; i < x; i++)
		{
			if (wiadomoscBIN[i] == '0' || wiadomoscBIN[i] == '1')
				continue;
			else
				return 1;
		}
		for (i = 0; i < y; i++)
		{
			if (wielomianBIN[i] == '0' || wielomianBIN[i] == '1')
				continue;
			else
				return 1;
		}

		return 0;
	}

	void zamien() {
		for (c = 1; c < N; c++) {
			if (cs[c] == wielomianBIN[c]) {
				cs[c] = '0';
			}
			else
			{
				cs[c] = '1';
			}
		}
	}

	void crc(struktura *lista) {
		for (e = 0; e < N; e++) {
			cs[e] = wiadomoscBIN[e];
		}
		do {
			if (cs[0] == '1')
				zamien();
			for (c = 0; c< N - 1; c++)
				cs[c] = cs[c + 1];
			cs[c] = wiadomoscBIN[e++];
		} while (e <= a + N - 1);
		strcpy(lista[l].wynik, cs);
		l++;
	}

	int main()
	{
		int ile = 0;
		scanf("%d", &ile);

		struktura *lista;
		lista = (struktura*)malloc(sizeof(struktura)*ile);
		int z;
		for (z = 0; z < ile; z++)
		{
			memset(wiadomosc, 0, 200);
			memset(wiadomoscBIN, 0, 200);
			memset(wielomian, 0, 200);
			memset(cs, 0, 200);
			memset(wielomianBIN, 0, 200);
			memset(wielomian2, 0, 200);

			scanf("%s %s", wielomian, wiadomosc);
			int n = (int)strtol(wielomian, NULL, 16); //hex to int
			inttobin(n);
			chartobin(wiadomosc);

			a = strlen(wiadomoscBIN);
			for (e = a; e < a + N - 1; e++) {
				wiadomoscBIN[e] = '0';
			}
			crc(lista);
		}
		bintohex(lista);
		free(lista);
		return 0;
	}
3

Czytanie ze zrozumieniem lvl szkoła podstawowa.

Każdy test składa się z liczby zapisanej szesnastkowo (co najwyżej 8 cyfr), reprezentującej wielomian p(x) oraz, po spacji, łańcucha znaków (bez białych znaków, max. 10 000 znaków) dla którego ma być obliczone CRC.

A teraz patrzymy w kod a tam: char wiadomosc[200]

Już nawet nie mówie o tym jak genialnie policzyłeś że wiadomość na 200 bajtów można zamienić na formę binarną mającą 500 bitów. Mnożenie lvl szkoła podstawowa mówi że 200*8 bitów = 1600 bitów, więc twoja tablica `wiadomoscBin'' jest ponad 3 razy za krótka, nawet gdyby faktycznie długość wiadomości miała max 200 znaków a nie 10000...

0

strasznie przekombinowałeś.
Po co te tablice? Ten wialomian ma współczynniki równe 1 lub 0. Każde kolejne dzielenie to wykonanie bitowej operacji XOR, wiec trzymanie tego w tablicy nie ma sensu.
Ja po prostu do opisy wielomianu użyłem unsigned int i to wystarczy (dlatego właśnie w zadaniu jest napisane, że wielomian w postaci szesnastkowej ma nie więcej niż 8 znaków, czyli nie więcej niż 32 bity).
u mnie wygląda to mniej wiecej tak:

int main() {
    int i, n;
    scanf("%d", n);

    for (i=0; i<n; ++i) {
        unsigned int p;
        scanf(" %x ", &p);
        struct CRCData crcData;
        CRCStart(&crcData, p);
        int ch;
        while ( (ch = getchar()) != EOF && !isspace(ch) ) {
              CRCUpdate(&crcData, ch);
        }
        printf("%X\n", CRCFinalResult(&crcData));
    }
    return 0;
}

Gdzie każda funkcja CRC* to maksymalnie 10 linii kodu. Dane są przetwarzane strumieniowo, więc wielkość danych wejściowych nie ma znaczenia.
Spróbuj takiego podejścia.

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