Bug While Reading In User Input In C

I am reading in numbers, but it stores the data from the last set.

Page 1 of 1

4 Replies - 1111 Views - Last Post: 04 October 2010 - 03:02 PM Rate Topic: -----

#1 noctolater   User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 72
  • Joined: 29-April 09

Bug While Reading In User Input In C

Posted 04 October 2010 - 07:29 AM

I had to write a program that takes in user input of the form 'n1,n2' and returns a formatted list of numbers from n1 to n2 showing them in decimal, octal, hexadecimal, and binary. It also is supposed to handle 'n1,' as start at n1 and go until you run out of numbers and ',n2' as start at 0 and go until n2. Aside from a formatting bug that I haven't even gotten to yet, it all works great, except for this one other really annoying bug. If I type, say, '1,10' it will work fine. But if I type '1,' next, it only shows the results from '1,10' instead of going until I run out of numbers. I have been banging my head against a wall about this for three days, and cannot figure out what the problem is. Can anyone help me?

#include <stdio.h>
#include <string.h>
#include <limits.h>

// program variables.
char input[255];					/* place to store user input */
char helpString[5] = "help";		/* string used to compare against user input */
char quitString[5] = "quit";		/* string used to compare against user input */
int maxInt = INT_MAX;				/* highest value possible, 2147483647 */
int run = 1;						/* boolean expression to toggle program running (default on) */

/* This is a program that takes in a range of numbers and returns them formatted
   into a table that displays them in decimal, octal, hexadecimal, and binary form. */
int main() {
	// this will run until the user types quit.
	while(run) {
		printf("please type a command, or type \"help\" for a list of commands.\n");
		fgets(input, sizeof(input), stdin);
		// lower case the input to deal with capital letters
		strlwr(input);
		// this removes the \n from the end of the input
		input[strlen(input) - 1] = '\0';
		// if the input is all numbers and only 1 comma
		if (isNumbers(input)) {
			int first;
			int last;
			// if the input starts with a comma -----This is where the bug is -----
			if (input[0] == ',') {
				first = 0;
				sscanf(input, ",%i", &last);
				formatNumbers(first, last);
			// if the input ends with a comma
			} else if (input[strlen(input) - 2] == ',') {
				last = INT_MAX;
				sscanf(input, "%i,", &first);
				formatNumbers(first, last);
			// otherwise, the input is two numbers separated by a comma
			} else {
				sscanf(input, "%i,%i", &first, &last);
				formatNumbers(first, last);
			}
		// otherwise, the input is not numbers and only one comma
		} else {
			// if the input matches the command help
			if (strcmp(input, helpString) == 0) {
				printHelp();
			// if the input matches the command quit
			} else if (strcmp(input, quitString) == 0) {
				run = 0;
			// otherwise, the input is not valid.
			} else {
				printf("invalid command, ");
			}
		}
	}
	return 0;
}



And here's the rest of the program in case you need to see it.

/* isNumbers checks to see if the input from the user is only numbers and a single comma */
int isNumbers(char *input) {
	int commaCounter = 0;		/* number of commas in the string */
	int length = strlen(input);	/* length of the string */
	char current;				/* current character in the for loop */
	int i = 0;					/* for loop counter */
	for (i = 0; i < length; i++) {
		// set current to the current character in the string for the loop.
		current = input[i];
		// if the current character is between 0 and 9
		if ((current >= '0') && (current <= '9')) {
			// do nothing.
		// if the current character is a comma.
		} else if (current == ',') {
			// if there have been no commas.
			if (commaCounter == 0) {
				commaCounter++;
			// otherwise, too many commas.
			} else {
				return 0;
			}
		// if the current character is the end of string character
		} else if (current == '\0') {
			// it must be valid text.
			return 1;
		// if the current character is anything else
		} else {
			// it is not valid.
			return 0;
		}
	}
}

/* printHelp prints the list of commands for the user */
void printHelp() {
	printf("Command: Action:\n");
	printf("help     displays this help message.\n");
	printf("quit     quits the program.\n");
	printf("n1,n2    prints the numbers from n1 to n2 formatted.\n");
	printf("n1,      prints the numbers from n1 to MAXINT formatted.\n");
	printf(",n2      prints the numbers from 0 to n2 formatted.\n");
}

/* formatNumbers takes in a range of numbers, from first to last, and prints those numbers
   formatted with the correct spacing in decimal, octal, hexadecimal, and binary form. */
void formatNumbers(int first, int last) {
	char decValue[20];	/* the string representation of the number in decimal form */
	char octValue[20];	/* the string representation of the number in octal form */
	char hexValue[20];	/* the string representation of the number in hexadecimal form */
	char binValue[50];	/* the string representation of the number in binary form */
	char binValueClear[50];
	char baseLengthString[20] = "\t\t\t";		/* string representation of three tab marks */
	int baseLength = strlen(baseLengthString);	/* this allows us to format for different tab sizes */
	sprintf(hexValue, "%x", last);	/* assign the number in hex form to find the length of the binary */
	int length = strlen(hexValue) * 4;	/* multiply times 4 because each hex number is 4 binary numbers */
	int i;	/* counter variable for for loop below */

	printf("Decimal\t\tOctal\t\tHexadecimal\tBinary\n");
	for (i = last; i >= first; i--) {
		/* first create a string representing each value for the table. */
		sprintf(decValue, "%i", i);
		sprintf(octValue, "%o", i);
		sprintf(hexValue, "%x", i);
		convertToBinary(i, binValue);

		/* then format the values to go into the table. */
		// ---TODO--- figure out why the formatting values are off.
		/* while the length of the decimal value is less than three tabs */
		while (strlen(decValue) < baseLength) {
			strcat(decValue, "\t"); /* add another tab */
		}
		/* while the length of the octal value is less than three tabs */
		while (strlen(octValue) < baseLength) {
			strcat(octValue, "\t"); /* add another tab */
		}
		// format hexadecimal form
		/* while the length of the hexadecimal value is less than three tabs */
		while (strlen(hexValue) < baseLength) {
			strcat(hexValue, "\t"); /* add another tab */
		}
		// format binary form ---TODO--- broken currently
		/* while the length of the binary value is less than the highest binary value */
//		while(strlen(binValue) < length) {
//			strcat("0000", binValue); /* add leading 0's */
//		}
		printf("%s%s%s%s\n", decValue, octValue, hexValue, binValue);
		// ---TODO--- figure out why the @ symbol appears before the first binValue
		strcpy (binValue, binValueClear);
	}
}

/* convertToBinary is a lookup table that takes in a number, converts it
   to hexadecimal, and then converts it to binary.  This works because
   every hexadecimal digit represents 4 binary digits. */
void convertToBinary(int input, char* binValue) {
	char hexValue[20];			/* the string to hold the hexadecimal value */
	sprintf(hexValue, "%x", input);	/* assign the hexadecimal value */
	int length = strlen(hexValue);	/*length of the hexadecimal value */
	int i;						/* counter for for loop below */
	for (i = 0; i < length; i++) {
		/* starting from the left, convert each hex digit into binary */
		switch (hexValue[i]) {
			case '0': strcat(binValue, "0000");
				break;
			case '1': strcat(binValue, "0001");
				break;
			case '2': strcat(binValue, "0010");
				break;
			case '3': strcat(binValue, "0011");
				break;
			case '4': strcat(binValue, "0100");
				break;
			case '5': strcat(binValue, "0101");
				break;
			case '6': strcat(binValue, "0110");
				break;
			case '7': strcat(binValue, "0111");
				break;
			case '8': strcat(binValue, "1000");
				break;
			case '9': strcat(binValue, "1001");
				break;
			case 'a': strcat(binValue, "1010");
				break;
			case 'b': strcat(binValue, "1011");
				break;
			case 'c': strcat(binValue, "1100");
				break;
			case 'd': strcat(binValue, "1101");
				break;
			case 'e': strcat(binValue, "1110");
				break;
			case 'f': strcat(binValue, "1111");
				break;
			default: // do nothing.
				break;
		}
	}
}



Is This A Good Question/Topic? 0
  • +

Replies To: Bug While Reading In User Input In C

#2 Banfa   User is offline

  • D.I.C Head
  • member icon

Reputation: 83
  • View blog
  • Posts: 109
  • Joined: 07-June 10

Re: Bug While Reading In User Input In C

Posted 04 October 2010 - 07:57 AM

Look at line 33, what is strlen(input) going to return if input is "1,"? Given that what is the value of input[strlen(input) - 2]?

If you are not sure how you code is getting somewhere it is always worth putting in extra output statements (printf, cout etc) temporarily just to track its execution path.

This post has been edited by Banfa: 04 October 2010 - 07:58 AM

Was This Post Helpful? 2
  • +
  • -

#3 JackOfAllTrades   User is offline

  • Saucy!
  • member icon

Reputation: 6246
  • View blog
  • Posts: 24,014
  • Joined: 23-August 08

Re: Bug While Reading In User Input In C

Posted 04 October 2010 - 08:00 AM

else if (current == ',') {
    // if there have been no commas.
    if (commaCounter == 0) {
        commaCounter++;
    // otherwise, too many commas.
    } else {
        return 0;
    }
// if the current character is the end of string character
}


Why go through the loop again if you've found a comma? Why not just:
else if (current == ',') {
    return 0;
}

Was This Post Helpful? 0
  • +
  • -

#4 noctolater   User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 72
  • Joined: 29-April 09

Re: Bug While Reading In User Input In C

Posted 04 October 2010 - 11:20 AM

Banfa - Thank you so much for that. I always make stupid mistakes like that in Java, and I guess C will be no different for me :P I will definitely start to put in some debug code in my future programs, I am just so used to Java telling you when you make stupid mistakes that I need to learn how to look for them.

JackOfAllTrades - I need to have at least one comma in the string for it to be considered valid numbers. I then need to keep iterating through the loop to check for more commas. I may be misunderstanding your advice, but to me it would make it exit the loop after it found the first comma, which I need. If so, please clarify so that I can improve my code, as I am always willing to listen to advice from others :P
Was This Post Helpful? 0
  • +
  • -

#5 JackOfAllTrades   User is offline

  • Saucy!
  • member icon

Reputation: 6246
  • View blog
  • Posts: 24,014
  • Joined: 23-August 08

Re: Bug While Reading In User Input In C

Posted 04 October 2010 - 03:02 PM

Oh, OK. I didn't realize you needed a comma and should have noticed that in the comment. Sorry about that.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1