Trouble breaking out a loop (c)

Started by
3 comments, last by Zahlman 16 years, 9 months ago
Trying to do the following problem from 'practical c programming: 8.2 The total resistance of of n parallel resistors is: 1/R = 1/R1 + 1/R2 + ... + 1/Rn Write a program to compute the total resistance for any number of parallel resistors --- I tried to get an input to ask how many resistors there are to create an array but that didnt work. Heres the snippet for the code
[source lang = "c"]//read number of resistors
	printf("***Parallel Resistance Calculator***\n\nEnter the number of resistors: ");
	fgets(line, 5, stdin);
	sscanf(line, "%d", &n);
	
	//read resistor values
	int resistor[n];
	for (i = 0; i < n; ++i)
	{
		printf("\nEnter the value of resistor &d: ");
		fgets(value, 5, stdin);
		sscanf(value, "%d", &resistor);
	}

That produced an error in VC++ 2005 Exoress about wanting a constan in the array So I tried a large array and tried to break out of the loop when 0 was entered but this produced an error when I ran the program
[source lang = "c"]int main()
{
	char line[5], value[5];
	int i, j, n;
	float total, invert;

	printf("***Parallel Resistance Calculator***\n\n");
	
	//read resistor values
	int resistor[100];
	for (i = 0; i < 100; ++i)
	{
		printf("Enter the value of resistor %d: ", (i + 1));
		fgets(value, 5, stdin);
		sscanf(value, "%d", &resistor);
		
		if (resistor == '0')
		{
			total = 0.0;
			for (j = 0; j < n; ++j)
			{
				invert = 1 / resistor[j];
				total += invert;
			}
			return 0;
		}
	}
}
Any ideas here on either bits of the code. I tried using the break when 0 was entered with no luck either. Also can you exit the loop when you hit enter and dont enter a value?
Advertisement
Don't worry, your pretty close. There's a lot of ways to solve this problem and what I'm going to say isn't the best way, but it makes use of the concepts you demonstrated.

Basically you can used the array with a fixed size of 100 (like in your second code snippet) but only loop between 0 and n-1 (like in your second code snippet). If they only enter 5 values, just ignore the rest of the array.

Does that make sense?
Alternatively, you may use a compiler which supports C99 (and thus allows variable-size stack arrays), or allocate a temporary buffer using malloc and free if your book has already covered these.
You are looping until 'n' (in the nested loop), but n is not initialized to anything, so it contains garbage. You need to initialize it to zero, and then increment it for each value you read.

Also, you can just sum these values up as you loop, and break out of the loop when a zero is encountered (using the break keyword), instead of waiting for zero and doing the summation then.
Ok, I'm going to put aside for a moment the fact that you're working in an ancient language with few to no remaining redeeming features (especially for beginners), and try to impress upon you a couple of good ideas about programming, while also addressing the problems.

1) Problem: '0' is not zero. It's a 0 *character*, i.e. a char variable that contains a number, such that, when you feed it to printf, it gets interpreted as the *symbol* 0. That number, coincidentally, is 48, on pretty much all normal systems. It also happens that the symbols '1', '2', etc. get values 49, 50, etc. in sequence. (But you should NOT hard-code the number 48 into a program if you need, for some reason, to translate between the symbol-values and the digit-values; use '0' instead.)

2) Problem: a mathematical/logical one. The *inverse* of the total resistance is the sum of the inverses of the individual resistances. To get the final answer, you need to invert the sum again.

3) Problem: as pointed out - what's "n"? What you want to do is loop up until the number of resistors that was read in, but there's no logic to determine that anywhere. However, it will be clearer once we sort out...

4) Design: organize your code by separating out your tasks. First, read the data in a loop. Then have a second loop which calculates the value. In the first loop, we'll need to bail out of the loop when a zero is entered, but then proceed to the next loop (which will be immediately after in the code). We can accomplish this with a 'break' statement.

5) Problem: programming logic. When we write a division between two integers in C, we ask for integer division. The result will also be an integer; the remainder is discarded. This operation is actually very useful, but it's not what we want here.

Solution: As long as *either* term in the division (or both) is of a floating-point type, we'll get floating-point division. The easiest way to arrange this is to use a floating-point value for the "1" constant, i.e. "1.0".

6) style issue: Try to declare variables near first use. In C, a block's variables have to be declared at the top of the block, but we can still restrict variables to be used only in the blocks where we need them. This protects us from mistakes (accidentally reusing variables in ways we didn't intend). Also, we can *initialize* variables where we declare them: this makes sure that they *always* have a valid value for their entire "lifetime", which again helps avoid mistakes (using things before we assigned to them).

7) Problem: user interface. Don't forget to output the final result :)

int main() {	char value[5]; /* We don't use "line" or "n" any more... */	int i, j;	float total = 0.0; /* We don't need "invert" either, as shown... */	/* Can't put this after the printf statement. Your compiler is letting	   you get away with things, possibly because it thinks it's compiling	   C++ code. */	int resistor[100];	printf("***Parallel Resistance Calculator***\n\n");		/* read resistor values */	for (i = 0; i < 100; ++i)	{		printf("Enter the value of resistor %d: ", (i + 1));		fgets(value, 5, stdin);		sscanf(value, "%d", &resistor);				if (resistor == 0)		{			break;		}	}	/* Do the calculation. */	/* Once we "break" above, 'i' will hold the index where we stored the 0	   value (or, if we filled the array, it will be at 100).	   So we simply loop up to, and not including, that location. */	for (j = 0; j < i; ++j) {		total += 1.0 / resistor[j];	}	printf("The total resistance is %f\n", 1 / total);}


Of course, there are still problems - the code isn't *robust*; there are arbitrary limitations everywhere, and no error checking. What happens if the user types too much at once, or a number that's too big, or something that isn't a number at all? The answers may surprise and/or disgust you. And fixing these kinds of problems in C is quite tedious, too. Considering how much code (and discussion) we already have for something so simple, you can see why I put the warning I did at the top of the post.

But I will do you the favour of removing one of those problems.

8) Design issue: There's no reason we need to store all the resistor values separately and then calculate with all of them. We can keep a *running* total of the inverse-resistances instead.

That looks like:

int main() {	char value[5]; /* We don't use "line" or "n" any more... */	int i;	float total = 0.0; /* We don't need "invert" either, as shown... */	int current_resistor = 1;		printf("***Parallel Resistance Calculator***\n\n");		/* read resistor values, summing as we go. */	for (i = 0; ; ++i)	{		printf("Enter the value of resistor %d: ", (i + 1));		fgets(value, 5, stdin);		sscanf(value, "%d", &current_resistor);		if (current_resistor == 0) { /* can't add it in... */			break;		}		total += 1.0 / current_resistor; /* AFTER the break. */	}	printf("The total resistance is %f\n", 1 / total);}


Notice how we actually *simplified* things while removing our limitation.

But again, these things are much easier in other languages. In Python, for example, we could do:

def main():	print "***Parallel Resistance Calculator***\n\n"	total = 0.0	ID = 1	while True:		try: resistor = int(raw_input("Enter the value of resistor %d: " % ID))		except: print "That's not a number, try again."		if resistor == 0: break		total += 1.0 / resistor		ID += 1	print "The total resistance is %f\n" % (1 / total)


Note that this has added error handling :)

This topic is closed to new replies.

Advertisement