Pamięć jest jak światło, a ja jestem jak kret.

0

Witam serdecznie. Napisałem program w C, którego kod wklejam poniżej. Program przeprowadza wybory ogłaszając zwycięzców na podstawie kryterium A (kandydat wybrany w najmniejszej ilości sąsiedzkich miast) lub B (największej), a na końcu wypisując koszt ich kampanii mierzony ilością przejętych miast. Język ten jest dla mnie jednak stosunkowo nowy i dopuściłem się jakiś strasznych zbrodni przeciwko pamięci, których kompilator nie chcę mi wybaczyć, a sam nie jestem w stanie znaleźć ich i zadośćuczynić. Podczas sprawdzania warunku if (tempTownListElement->town->takenByA == counter2) VisualStudio nie widzi wartości wewnętrznych zmiennych, a gcc zwraca wesołe segmentation fault. Gdzie popełniłem błąd?

#include <stdio.h>
#include <stdlib.h>
#define getc_unlocked _fgetc_nolock

typedef struct Town Town;
typedef struct TownList TownList;
typedef struct TownListElement TownListElement;
typedef struct Candidate Candidate;

struct Town
{
	int takenByA;
	int takenByB;
	int futureWinnerA;
	int futureWinnerB;
	TownList* neighbourTownList;
};

struct TownList
{
	TownListElement* firstElement;
	int elementCount;
};

struct TownListElement
{
	Town* town;
	TownListElement* nextTown;
};

void townListAdd(TownList* list, Town* town)
{
	if (list == 0){
		TownList* newList = malloc(sizeof(*newList));
		newList->firstElement = malloc(sizeof(TownListElement));
		newList->firstElement->town = town;
		newList->firstElement->nextTown = 0;
		newList->elementCount = 0;
		list = newList;
	}
	else{
		TownListElement* newElement = malloc(sizeof(*newElement));
		newElement->town = town;
		newElement->nextTown = list->firstElement;
		list->firstElement = newElement;
	}
	list->elementCount++;
}

struct Candidate
{
	int costA;
	int costB;
};

int main()
{
	register int character = getc_unlocked(stdin);
	register int number = 0;
	register int counter1;
	register int counter2;
	
	int townCount;
	Town* townsArray;
	int tempTownConnection1;
	int tempTownConnection2;
	int candidateCount;
	Candidate* candidateArray;
	int takenTownsCount = 0;
	int candidateOccurenceA;
	int candidateOccurenceB;
	int maxOccurence;
	int minOccurence;
	TownListElement* tempTownListElement;

	while (character > 47){
		number = (number << 1) + (number << 3) + character - 48;
		character = getc_unlocked(stdin);
	}
	townCount = number;
	townsArray = malloc(townCount*sizeof(*townsArray));

	for (counter1 = 0; counter1 < townCount; counter1++){
		townsArray[counter1].takenByA = -1;
		townsArray[counter1].takenByB = -1;
		townsArray[counter1].futureWinnerA = -1;
		townsArray[counter1].futureWinnerB = -1;
		townsArray[counter1].neighbourTownList = 0;
	}

	while (1){
		character = getc_unlocked(stdin);
		if (character == '-'){
			getc_unlocked(stdin);
			getc_unlocked(stdin);
			getc_unlocked(stdin);
			getc_unlocked(stdin);
			getc_unlocked(stdin);
			break;
		}
		number = 0;
		while (character > 47){
			number = (number << 1) + (number << 3) + character - 48;
			character = getc_unlocked(stdin);
		}
		tempTownConnection1 = number;

		character = getc_unlocked(stdin);
		number = 0;
		while (character > 47){
			number = (number << 1) + (number << 3) + character - 48;
			character = getc_unlocked(stdin);
		}
		tempTownConnection2 = number;

		townListAdd(&townsArray[tempTownConnection1].neighbourTownList, &townsArray[tempTownConnection2]);
		townListAdd(&townsArray[tempTownConnection2].neighbourTownList, &townsArray[tempTownConnection1]);
	}

	character = getc_unlocked(stdin);
	number = 0;
	while (character > 47){
		number = (number << 1) + (number << 3) + character - 48;
		character = getc_unlocked(stdin);
	}
	candidateCount = number;
	candidateArray = malloc(candidateCount*sizeof(*candidateArray));

	for (counter1 = 0; counter1 < candidateCount; counter1++){
		character = getc_unlocked(stdin);
		number = 0;
		while (character > 47){
			number = (number << 1) + (number << 3) + character - 48;
			character = getc_unlocked(stdin);
		}
		townsArray[number].takenByA = counter1;
		townsArray[number].takenByB = counter1;
		candidateArray[counter1].costA=1;
		candidateArray[counter1].costB=1;
		takenTownsCount++;
	}

	while (takenTownsCount != townCount){

		for (counter1 = 0; counter1 < townCount; counter1++){
			minOccurence = 10000000;
			maxOccurence = 0;
			for (counter2 = 0; counter2 < candidateCount; counter2++){
				tempTownListElement = townsArray[counter1].neighbourTownList->firstElement;
				candidateOccurenceA = 0;
				candidateOccurenceB = 0;
				while (tempTownListElement){
					if (tempTownListElement->town->takenByA == counter2){
						candidateOccurenceA++;
					}
					if (tempTownListElement->town->takenByB == counter2){
						candidateOccurenceB++;
					}
					tempTownListElement = tempTownListElement->nextTown;
				}
				if (candidateOccurenceA <= minOccurence){
					minOccurence = candidateOccurenceA;
					townsArray[counter1].futureWinnerA = counter2;
				}
				if (candidateOccurenceB >= maxOccurence){
					if (candidateOccurenceB != maxOccurence){
						townsArray[counter1].futureWinnerB = counter2;
					}
					maxOccurence = candidateOccurenceB;
				}
			}
		}

		for (counter1 = 0; counter1 < townCount; counter1++){
			townsArray[counter1].takenByA = townsArray[counter1].futureWinnerA;
			if (townsArray[counter1].takenByA != -1){
				candidateArray[townsArray[counter1].takenByA].costA = townsArray[counter1].takenByA;
			}
			townsArray[counter1].takenByB = townsArray[counter1].futureWinnerB;
			if (townsArray[counter1].takenByB != -1){
				candidateArray[townsArray[counter1].takenByB].costB = townsArray[counter1].takenByB;
				takenTownsCount++;
			}
		}

	}

	for (counter1 = 0; counter1 < candidateCount; counter1++){
		printf("%d %d\n", candidateArray[counter1].costA, candidateArray[counter1].costB);
	}

}
0

Po pierwsze: warningi nie są po to, żeby zaśmiecały IDE i wkurzały programiste. Napraw to.
Po drugie: może się mylę, ale z doświadczenia wynika, ze warto sprawdzic, czy
tempTownListElement->town->takenByA
coś z tego nie jest nullem.

0

nigdzie nie ustawiasz zmiennej
town
i jest nullem. A probujesz pozniej robic na nim -> no i nie dziala.

1

Błąd zrobiłeś wrzucając całą logikę aplikacji do main.

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