Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

larswik

macrumors 68000
Original poster
Sep 8, 2006
1,552
11
Hey, I am learning about pointers in C and to further understand I wrote my own test code. What I am trying to do is have the console ask for a letter and then pass that argument to a function that evaluates it using a switch. When it finds the matching case an integer value is assigned to the local variable 'CritNum'. This value is then pointed back to Main to the integer variable named 'cNumber' (I hope I did not screw up my explanation terminology to much, i am learning).

Anyway, I was surprised after writing it I got no errors on my first try!!! But that joy was short lived since the program stalls after asking the first question? I am thinking the code fails in my Function but I can't see where after looking at it for an hour. If it gave me errors I could try to fix it but nothing. Any help would be appreciated.

Code:
#include <stdio.h>

void crit(char crit, int *cNumberPTR);

int main (int argc, const char * argv[]) {
	
	char letter;
	int cNumber;
	
	printf("Enter a letter from A-I:");
	scanf("%c", letter);
	
	crit(letter, &cNumber);
	
	printf("The letter %c is the number is %d", letter,cNumber);

    return 0;
}
void crit(char crit, int *cNumberPTR) {
	
	int CritNum;
	
	switch (crit) {
		case 'a':
			CritNum = 10;
		case 'A':
			CritNum = 10;
			break;
		case 'b':
			CritNum = 20;
		case 'B':
			CritNum = 20;
			break;
		case 'c':
			CritNum = 30;
			break;
		case 'C':
			CritNum = 30;
		case 'd':
			CritNum = 50;
		case 'D':
			CritNum = 50;
			break;
		case 'e':
			CritNum = 70;
		case 'E':
			CritNum = 70;
			break;
		case 'f':
			CritNum = 80;
		case 'F':
			CritNum = 80;
			break;
		case 'g':
			CritNum = 90;
		case 'G':
			CritNum = 90;
			break;
		case 'h':
			CritNum = 100;
		case 'H':
			CritNum = 100;
			break;
		case 'i':
			CritNum = 120;
		case 'I':
			CritNum = 120;
			break;
		default:
			CritNum = 0;
			break;
	}
			
			*cNumberPTR = CritNum;
}
 
Code:
gcc -o myprog test.c
test.c: In function âmainâ:
test.c:11: warning: format â%câ expects type âchar *â, but argument 2 has type âintâ

Fix:

Code:
        scanf("%c", [B]&[/B]letter);

Result:

Code:
choas-computer-3:c choas$ gcc -o myprog test.c
choas-computer-3:c choas$ ./myprog
Enter a letter from A-I:D
The letter D is the number is 50
 
OMG! Thank you!!! I can't believe I over looked that little tiny &. That kept me looking for hours and I was sure the problem was in the Function and it was not.

Thank you very much chOas!

-Lars
 
It compiled and ran in the console. I wish it would have given me an error when I pressed build, I would have caught it then.

Thanks again.

-Lars
 
Just for kicks:
Code:
#include <stdio.h>

void crit(char crit, int *cNumberPTR);

int main (int argc, const char * argv[]) {
	
	char letter;
	int cNumber;
	
	printf("Enter a letter from A-I:");
	scanf("%c", &letter);
	
	crit(letter, &cNumber);
	
	printf("The letter %c is the number is %d\n", letter,cNumber);

    return 0;
}

void crit(char crit, int *cNumberPTR) {
	int letterToNumberMap[] = {10,20,30,50,70,80,90,100,120};
	int offset = 0;
	*cNumberPTR = 0;
	if(crit < 'A' || (crit > 'I' && crit < 'a') || crit > 'i') {
		printf("Invalid crit character, %c, entered.\n",crit);
		return;
	}
	if(crit >= 'a') {
		offset = crit - 'a';
	} else {
		offset = crit - 'A';
	}
	*cNumberPTR = letterToNumberMap[offset];
}

If you're really wanting to reduce crit's length:
Code:
void crit(char crit, int *cNumberPTR) {
	int letterToNumberMap[] = {10,20,30,50,70,80,90,100,120};
	*cNumberPTR = 0;
	if(crit < 'A' || (crit > 'I' && crit < 'a') || crit > 'i') return;
	*cNumberPTR = crit >= 'a'?letterToNumberMap[crit-'a']:letterToNumberMap[crit-'A'];
}

-Lee

Edit: While I'm here...
Code:
switch (crit) {
		case 'a':
		case 'A':
			CritNum = 10;
			break;
		case 'b':
		case 'B':
			CritNum = 20;
			break;
		case 'c':
		case 'C':
			CritNum = 30;
			break;
		case 'd':
		case 'D':
			CritNum = 50;
			break;
		case 'e':
		case 'E':
			CritNum = 70;
			break;
		case 'f':
		case 'F':
			CritNum = 80;
			break;
		case 'g':
		case 'G':
			CritNum = 90;
			break;
		case 'h':
		case 'H':
			CritNum = 100;
			break;
		case 'i':
		case 'I':
			CritNum = 120;
			break;
		default:
			CritNum = 0;
			break;
	}

I think a fold of your lower/uppercases would be better, but if you want to do a switch with fall-through between cases it might be better to do it like that. The compiler might have optimized away the double assignments, and assignments are cheap anyway, but you were always setting CritNum twice. And there was the reversed c/C cases as RiskyMr pointed out.
 
Last edited:
It compiled and ran in the console. I wish it would have given me an error when I pressed build, I would have caught it then.

Thanks again.

-Lars
Clicking Build in Xcode will not give you an error. It will only give you a warning. You may not have noticed it, even if it was there.

In general, I prefer to always enable the Build Setting "Treat Warnings as Errors". You can find it in the Build Settings panel by searching for Treat Warnings.

The only times I disable this setting is after I've seen and understood every warning, and I want to do something quickly. Turning it on when it's off is a good way to find mistakes you may have missed, yet which are still mistakes.
 
Lee210 - Thanks for that alternative code. I did not even think about that.

Chown33 - I will implement that warning to error you recommended.

Thanks guys!

-Lars
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.