I'm trying to develop a C program that calculates the resistor values by inputting the colour bands marked on the resistor.
Ignoring the resistor tolerance.
e.g.
Enter the colours of the resistor’s three bands, beginning
with the band nearest the end. Type the colours in lowercase
letters only, NO CAPS
Band 1 => green
Band 2 => black
Band 3 => yellow
Resistance value: 500 000 -ohms
Do you want to decode another resistor (Y/N)?
=> Y
- Displaying the required format of the resistor value. For example, if the resistor value is "500000 -ohms", the format is required to be "500 000 -ohms". A space has to be put between every 3 digits.
- Displaying a single invalid colour. For example, if 'brown', 'vilet', and 'red' are inputted as the resistor colours, the program generates the following message:
Invalid colour: vilet
Here only 'vilet' is the only invalid colour.- Displaying more than one invalid colour. For example, if 'pink', 'silver', and 'red' are inputted as the resistor colours, the program should generate the following message in a single line:
Invalid colours: pink, silver
Here are two invalid colours 'pink' and 'silver'. Note the 'colours'.
Now I'm having a difficult time with getting the formatting for the total resistance (#1). And for #2 & #3 if and only if the first input (band 1) is invalid the program will run. If the second band or third band are invalid without the first band being invalid, the program will stop execution.
Here is the code that I've been working on:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
// resister bands
enum resistor_band_items {BLACK, BROWN, RED, ORANGE, YELLOW, GREEN, BLUE, VIOLET, GRAY, WHITE, UNKNOWN};
struct items
{
char *name;
enum resistor_band_items id;
} item_list[] = {
{"black", BLACK},
{"brown", BROWN},
{"red", RED},
{"orange", ORANGE},
{"yellow", YELLOW},
{"green", GREEN},
{"blue", BLUE},
{"violet", VIOLET},
{"gray", GRAY},
{"white", WHITE}
};
char answer[10], status[1] = "Y"; //answer => user input
char bands[3][10]; //string for resistor bands
//variables to hold the band values
int colour[3];
//function prototype
int inputVal (int *a, char b[3][10]);
double calResistance (int a, int b, int c);
void print_number (double number);
int main(void)
{
int i, invalid; //counter
double resistor_value; //total resistance value
enum resistor_band_items mid;
struct items *choice = NULL;
while (strcmp(status, "Y") == 0)
{
//print the question to the user
printf("Enter the colours of the resistor's three bands,\nbeginning with the band nearest to the end.\nType the coloues in lowercase letters only, NO CAPS.\n");
for (int j = 0; j<3; j++)
{
printf("Band %d => ", j + 1);
gets(answer);
for (i = 0, choice = NULL; i < sizeof item_list/sizeof(struct items); ++i)
{
if (strcmp(answer, item_list[i].name) == 0)
{
choice = item_list + i;
break;
}
}
mid = choice ? choice ->id : UNKNOWN;
colour[j] = mid;
strcpy(bands[j], answer);
}
invalid = inputVal (colour, bands);
if (invalid == 0)
{
//calculate resistor value
resistor_value = calResistance(colour[0], colour[1],colour[2]);
// print resistor value to user
printf("%.0f\n", resistor_value);
print_number(resistor_value);
}
printf("Do you want to decode another resistor (Y/N)?\n");
gets(status);
if (strcmp(status, "Y") == 0);
else break;
}
return 0;
}
int inputVal (int *a, char b[3][10])
{
int counter = 0, index[3];
for (int i = 0; i < 3; ++i)
{
if (a[i] == 10)
{
index[i] = i;
//printf("%s%s", b[i], " ");
counter++;
}
}
if (counter == 0)
{
return 0;
}
else if (counter == 1)
{
printf("Invalid colour: %s\n", b[index[0]]);
}
else if (counter == 2)
{
printf("Invalid colours:");
printf(" %s", b[index[0]]);
printf(",");
printf(" %s\n", b[index[1]]);
}
else
{
printf("Invalid colours:");
printf(" %s", b[index[0]]);
printf(",");
printf(" %s", b[index[1]]);
printf(",");
printf(" %s\n", b[index[2]]);
}
return 1;
}
double calResistance (int a, int b, int c)
{
double results;
unsigned power = 10;
while (b >= power)
{
power *= 10;
}
results = a * power + b;
results = results * pow(10, c);
return results;
}
void print_number (double number)
{
double n = number, *x;
int c = 0;
int j = 1;
while (n != 0 && n > 1)
{
n /= 10.0;
c += 1;
}
x = malloc (c * sizeof(double));
printf("%d\n", c);
for (int i = 0; i <= c; i++)
{
double digit = fmod (number, 10.0);
x[i] = digit;
number /= 10.0;
}
printf("Resistance value: \n\n");
for (int i = c - 1; i >= 0; i--)
{
printf("#%d = %.0f\n",i, x[i]);
}
printf("\n\n\n");
for (int i = c - 1; i >= 0; i--)
{
if (j == 3 || j == 7 || j == 11 || j == 15)
{
printf(" ");
}
else
{
printf("%.0f", x[i]);
}
j++;
}
printf(" -ohms\n");
//free(x);
}
I've edited the print_number function so it prints a space every 3rd digit. (It works with most combinations)
void print_number (double number)
{
double n = number, *x;
int c = 0;
int j = 1;
while (n != 0 && n > 1)
{
n /= 10.0;
c += 1;
}
x = malloc (c * sizeof(double));
printf("c = %d\n", c);
for (int i = 0; i < c; i++)
{
double digit = fmod (number, 10.0);
x[i] = digit;
number /= 10.0;
}
printf("Resistance value: \n");
for (int i = c; i >= 0; i--)
{
printf("#%d = %.0f\n",i, x[i]);
}
printf("\n\n");
printf("remainder of c = %d\n\n",c%3);
if (c % 3 == 2)
{
for (int i = c; i >= 0; i--)
{
if (j == 4 || j == 7 || j == 11 || j == 15)
{
printf(" ");
i++;
}
else
{
printf("%.0f", x[i]);
}
j++;
}
printf(" -ohms\n");
}
else
{
for (int i = c - 1 ; i >= 0; i--)
{
//printf("%.0f", x[i]);
if (c % 3 == 0)
{
if (j == 4 || j == 8 || j == 12 || j == 16)
{
printf(" ");
i++;
}
else
{
printf("%.0f", x[i]);
}
}
else if (c % 3 == 1)
{
if (j == 2 || j == 6 || j == 10 || j == 14)
{
printf(" ");
i++;
}
else
{
printf("%.0f", x[i]);
}
}
j++;
}
printf(" -ohms\n");
//free(x);
}
}
Rev 2
Here the modified code from the answers.
The reason I'm not using argc
and argv
is that the client has a restricted formatting that needs to be followd (Which drives me mad!)
here is the code:
//importing required header files
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
// resister bands
enum resistor_band_items {BLACK, BROWN, RED, ORANGE, YELLOW, GREEN,
BLUE, VIOLET, GRAY, WHITE, UNKNOWN};
//constants for min/max colour arguments and max colour char
enum {MINC = 3, MAXC = 4, MAXCC = 8};
struct items
{
char *name;
enum resistor_band_items id;
} item_list[] = {
{"black", BLACK},
{"brown", BROWN},
{"red", RED},
{"orange", ORANGE},
{"yellow", YELLOW},
{"green", GREEN},
{"blue", BLUE},
{"violet", VIOLET},
{"gray", GRAY},
{"white", WHITE}
};
//resistor multiplier values
int multiplier[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000};
char answer[3][10]; // User input
int colour_val[3]; //stores the band value
#define nItems (sizeof item_list/sizeof *item_list)
//function prototyps
int srchItems (char *ccode); //a search for index values
char *strcpy2lower (char *dest, char *src); //converts to lower case
int scmp (char *a, char *b); //simple string comarison
char *sepnumber (char *s, long val);
int invalid (char answer[3][10]);
//main function
int main(int argc, char const *argv[])
{
int i; // counter
char status = 'Y';// Keeps the program running when user inputs 'Y'
long resistor_value = 0; //Total resistance
int r, err, mult; //holds the significant figure, Error, Multiplier
char resistor_value_string[20] = "";//formatted output
while (status == 'Y') //The program runs under this
{
//print the question to the user
printf("Enter the colours of the resistor's three bands,\nbeginning with the band nearest to the end.\nType the coloues in lowercase letters only, NO CAPS.\n");
for (i = 0; i < MINC; ++i)
{
printf("Band %d => ", i + 1); // print headers for each band
scanf(" %s", &answer[i]); // get the user input
}
for (i = 0; i < MINC - 1; ++i) //converts colours into index
{
if ((r = srchItems (answer[i])) > -1)
{
// from significant figure
resistor_value = (resistor_value * 10) + r;
}
else
{
invalid(answer);
err = 2;
}
}
if (err > 1)
{
printf("Do you want to decode anothe resistor (Y/N)?\n");
scanf (" %c", &status);
if (status == 'Y');
else break;
}
else
{
mult = srchItems (answer[i]); // get multiplier index
resistor_value *= multiplier[mult]; // Calculate final value
sepnumber (resistor_value_string, resistor_value);
printf("Resistor value: ");
/*for (int i = 0; i < (strlen(resistor_value_string) ); ++i)
{
printf("%c", resistor_value_string[i]);
}
*/
puts (resistor_value_string);
//printf(" -ohm\n");
//memset (resistor_value_string, 0, 50);
printf("Do you want to decode anothe resistor (Y/N)?\n");
scanf (" %c", &status);
if (status == 'Y');
else break;
/*Debug
for (int i = 0; i < MINC; ++i)
{
printf("item_list[%d] = %s\n", i, answer[i]);
}
printf("Total resistance = %ld\n", resistor_value);
//end of debug */
}
}
return 0;
}
int srchItems (char *ccode)
{
int i;
char lccode [MAXCC] = "";
strcpy2lower (lccode, ccode); // converts everything to lower case
for (int i = 0; i < (int)nItems; ++i)
if (*lccode == *(item_list[i].name))
if (!scmp(item_list[i].name, lccode))
return i;
return -1;
}
char *strcpy2lower (char *dest, char *src)
{
if (!src || !dest) return NULL;
char *d = dest;
for (; *src; src++, d++)
if ('A' <= *src && *src <= 'Z')
*d = *src | (1 << 5);
else
*d = *src;
*d = 0;
return dest;
}
int scmp (char *a, char *b)
{
if (!a && !b) return 0;
if ( a && !b) return 1;
if (!a && b) return -1;
for (; *a && *b && *a == *b; a++, b++) {}
return *a - *b;
}
/** separate long value every 3rd char into 's' */
char *sepnumber (char *s, long val)
{
char numstr[3 * MAXCC] = "";
char *p = numstr;
size_t idx = 0, len = 0;
sprintf (numstr, "%ld", val);
for (; *p; p++) {}
len = p - numstr;
p = s + 3 * MAXCC - 2;
while (len--) {
if (idx++ == 3) {
idx = 1;
*p-- = ' ';
}
*p = numstr[len];
if (len) p--;
}
for (idx = 0; *p; p++, idx++) s[idx] = *p; /* copy to s */
s[idx] = *p; /* nul-terminate */
return s;
}
int invalid (char answer[3][10])
{
int r, counter = 0, incorrect[3], i;
for (i = 0; i < MINC; ++i)
{
if ((r = srchItems (answer[i])) == -1)
{
incorrect[i] = r;
counter++;
}
}
if (counter == 1)
{
printf("%s","Invalid colour: " );
printf("%s ", answer[i]);
printf("\n");
}
i = 0;
}
This rev works well for the first loop, but it calculates the wrong resistor value on the second loop onwards. It will print the invalid entries with a little difficulty! After an invalid colour is inputted the program will not calculate any resistor values.
out put examples:
$ ./RQ1.exe
Enter the colours of the resistor's three bands,
beginning with the band nearest to the end.
Type the coloues in lowercase letters only, NO CAPS.
Band 1 => red
Band 2 => orange
Band 3 => green
Resistor value: 2 300 000
Do you want to decode anothe resistor (Y/N)?
Y
Enter the colours of the resistor's three bands,
beginning with the band nearest to the end.
Type the coloues in lowercase letters only, NO CAPS.
Band 1 => green
Band 2 => black
Band 3 => yellow
Resistor value: -2 101 970 656
Do you want to decode anothe resistor (Y/N)?
Y
Enter the colours of the resistor's three bands,
beginning with the band nearest to the end.
Type the coloues in lowercase letters only, NO CAPS.
Band 1 => read
Band 2 => gren
Band 3 => blu
Do you want to decode anothe resistor (Y/N)?
Y
Enter the colours of the resistor's three bands,
beginning with the band nearest to the end.
Type the coloues in lowercase letters only, NO CAPS.
Band 1 => red
Band 2 => orange
Band 3 => green
Do you want to decode anothe resistor (Y/N)?
N
Final Rev,
I think this is it:) beside the fact that it still has problem displaying the invalid inputs.
A really big tanks to David C. Rankin for helping out so much.
#include <stdio.h>
#include <string.h>
#define nItems (sizeof item_list/sizeof *item_list)
char status = 'Y';
//
enum {MINC = 3, MAXCC = 10};
// resister bands
enum resistor_band_items {BLACK, BROWN, RED, ORANGE, YELLOW, GREEN,
BLUE, VIOLET, GRAY, WHITE, UNKNOWN};
struct items
{
char *name;
enum resistor_band_items id;
} item_list[] = {
{"black", BLACK},
{"brown", BROWN},
{"red", RED},
{"orange", ORANGE},
{"yellow", YELLOW},
{"green", GREEN},
{"blue", BLUE},
{"violet", VIOLET},
{"gray", GRAY},
{"white", WHITE}
};
unsigned int multiplier[] = {1, 10, 100, 1000, 10000, 100000, 1000000,
10000000, 100000000, 1000000000};
int srchItems (char *ccode); //a search for index values
char *strcpy2lower (char *dest, char *src); //converts to lower case
int scmp (char *a, char *b); //simple string comarison
char *sepnumber (char *s, long val); //puts space every 3rd digit
int main(void)
{
int i, error = 0, mult;
char input[MINC][MAXCC]; //user input
char invalid[MINC][MAXCC]; // invalid enteries
int colour_val[MINC]; //stores the band value
long total_resistance = 0;
char resistor_value_string[20] = "";//formatted output
do
{
//prompt user
printf("%s\n%s\n%s\n",
"Enter the colours of the resistor's three bands,",
"beginning with the band nearest to the end.",
"Type the colours in lowercase letters only, NO CAPS.");
for (i = 0; i < MINC; ++i)
{
printf("Band %d => ", i + 1); // print headers for each band
scanf(" %s", &input[i]); // get the user input
// converts user input to index of colours
colour_val[i] = srchItems(input[i]);
}
for (i = 0; i < MINC; ++i)
{
if (colour_val[i] == -1)
{
strcpy(invalid[i], input[i]);
error++;
}
}
if (error > 0)
{
if (error == 1)
{
printf("Invalid colour: %s\n", invalid[0]);
}
else if (error == 2)
{
printf("Invalid colours: %s, %s\n", invalid[0], invalid[1]);
}
else
{
printf("Invalid colours: %s, %s, %s\n",
invalid[0], invalid[1], invalid[2]);
}
}
else
{
//
for (i = 0; i < MINC - 1; ++i)
{
total_resistance = (total_resistance * 10) + colour_val[i];
}
mult = colour_val[2];
total_resistance *= multiplier[mult];
sepnumber (resistor_value_string, total_resistance);
printf("Resistance value: %s -Ohms\n", resistor_value_string);
//debug
for (i = 0; i < MINC; ++i)
{
//printf("Input ==> %s\t", input[i]);
//printf("index ==> %d\n", colour_val[i]);
}
//end debug
}
error = 0;
total_resistance = 0;
for (i = 0; i < MINC; ++i)
{
colour_val[i] = 0;
}
//ask user if they want to continue
printf("Do you want to decode another resistor?\n");
scanf(" %c", &status);
if (status == 'Y');
else break;
} while (status == 'Y');
return 0;
}
int srchItems (char *ccode)
{
int i;
char lccode [MAXCC] = "";
strcpy2lower (lccode, ccode); // converts everything to lower case
for (int i = 0; i < (int)nItems; ++i)
if (*lccode == *(item_list[i].name))
if (!scmp(item_list[i].name, lccode))
return i;
return -1;
}
char *strcpy2lower (char *dest, char *src)
{
if (!src || !dest) return NULL;
char *d = dest;
for (; *src; src++, d++)
if ('A' <= *src && *src <= 'Z')
*d = *src | (1 << 5);
else
*d = *src;
*d = 0;
return dest;
}
int scmp (char *a, char *b)
{
if (!a && !b) return 0;
if ( a && !b) return 1;
if (!a && b) return -1;
for (; *a && *b && *a == *b; a++, b++) {}
return *a - *b;
}
/** separate long value every 3rd char into 's' */
char *sepnumber (char *s, long val)
{
char numstr[3 * MAXCC] = "";
char *p = numstr;
size_t idx = 0, len = 0;
sprintf (numstr, "%ld", val);
for (; *p; p++) {}
len = p - numstr;
//printf("%d\n", len);
p = s + 3 * MAXCC - 2;
while (len--) {
if (idx++ == 3) {
idx = 1;
*p-- = ' ';
}
*p = numstr[len];
if (len) p--;
}
for (idx = 0; *p; p++, idx++) s[idx] = *p; /* copy to s */
s[idx] = *p; /* nul-terminate */
return s;
}
Output example
$ ./Q1_token.exe
Enter the colours of the resistor's three bands,
beginning with the band nearest to the end.
Type the colours in lowercase letters only, NO CAPS.
Band 1 => green
Band 2 => black
Band 3 => yellow
Resistance value: 500 000 -Ohms
Do you want to decode another resistor?
Y
Enter the colours of the resistor's three bands,
beginning with the band nearest to the end.
Type the colours in lowercase letters only, NO CAPS.
Band 1 => red
Band 2 => orange
Band 3 => green
Resistance value: 2 300 000 -Ohms
Do you want to decode another resistor?
Y
Enter the colours of the resistor's three bands,
beginning with the band nearest to the end.
Type the coloues in lowercase letters only, NO CAPS.
Band 1 => pink
Band 2 => silver
Band 3 => red
Invalid colours: pink, silver
Do you want to decode another resistor?
Y
Enter the colours of the resistor's three bands,
beginning with the band nearest to the end.
Type the colours in lowercase letters only, NO CAPS.
Band 1 => vilot
Band 2 => brown
Band 3 => read
Invalid colours: vilot, silver
Do you want to decode another resistor?
N