以色带为输入计算电阻值 [英] Calculating the resistor value with its color bands as input

查看:135
本文介绍了以色带为输入计算电阻值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试开发一个C程序,通过输入标记在电阻上的色带来计算电阻值。

I'm trying to develop a C program that calculates the resistor values by inputting the colour bands marked on the resistor.

忽略电阻容差。

例如

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 





  1. 显示所需格式的电阻值。例如,如果电阻值为 500000 -ohms,则要求格式为
    500 000 -ohms。每3位之间必须有一个空格。

  2. 显示一种无效的颜色。例如,如果输入棕色,紫色和红色作为电阻颜色,则程序
    会生成以下消息:无效颜色:紫色在这里,只有
    '紫红色'是唯一的无效颜色。

  3. 显示多个无效颜色。例如,如果输入粉红色,银色和红色作为电阻颜色,则程序
    应该在一行中生成以下消息:
    Invalid颜色:粉红色,银色这是两个无效的颜色粉红色和
    银色。注意颜色。

  1. 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.
  2. 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.
  3. 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'.


现在我在获取格式方面遇到了困难总电阻(#1)。对于#2& #3当且仅当第一个输入(频段1)无效时,程序才会运行。如果第二个频段或第三个频段无效而第一个频段无效,则程序将停止执行。

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);
}

我已经编辑了print_number函数,因此它每3位输出一个空格。 (适用于大多数组合)

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



这里是答案中修改后的代码。
我不使用 argc argv 的原因是客户端需要使用受限格式要遵循(这使我发疯!)

Rev 2

Here the modified code from the answers. The reason I'm not using argcand argvis that the client has a restricted formatting that needs to be followd (Which drives me mad!)

这里是代码:

    //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.

$ ./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,



我认为是这样:)除了显示无效输入仍然有问题外。

Final Rev,

I think this is it:) beside the fact that it still has problem displaying the invalid inputs.

David C. Rankin 的帮助很大。

#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


推荐答案

用于确定有效位数的代码电阻值中的数字比所需的要复杂得多。由于您声明了struct item_list 的全局数组,因此要形成有效数字,您所需要做的就是使用 item_list 作为查找表,以查找所输入色带的索引。对于随后的每种颜色(第二个(对于5波段,为第二个),在添加索引之前,您只需将当前电阻值乘以 10 即可。

Your code for determining the significant figures in your resistor value is quite a bit more complex than needed. Since you declare the global array of struct item_list, all you need to do to form the significant figure is to use item_list as a lookup-table to find the index for the band-color entered. For each subsequent color (2nd [and 3rd for 5-band]), you simply multiply the current resistor value by 10 before adding the index.

例如,使用 item_list 索引变量 r 和电阻值 rval (包括对无效颜色的检查),您的代码可以简化为:

For example with the item_list index variable r and the resistor value rval (including your check for an invalid color), your code could be reduced to:

int multiplier[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 };
...
    int err = 0, i, mult, r;
    long rval = 0;

    printf ("\ncolor bands determining significant figures:\n\n");
    for (i = 1; i < argc - 1; i++) { /* convert colors to index */
        if ((r = srchitems (argv[i])) != -1) {
            rval = rval * 10 + r;    /* form significant figure */
            prnitem (r);
        }
        else {
            fprintf (stderr, "error: invalid color '%s'\n", argv[i]);
            err = 1;
        }
    }
    if (err) return 1;
    mult = srchitems (argv[i]);     /* get multiplier index  */
    rval *= multiplier[mult];       /* calculare final value */
    printf ("\nmultiplier:\n\n");
    prnitem (mult);
    printf ("\nresistor value : %ld -ohms\n\n", rval);

    return 0;

在您的 srchitems 函数上方,仅返回索引在 item_list 中给定颜色(作为程序的参数输入,例如 argv [1] argv [2] ,...)您可以编写一个简单的 srchitems ,将所有输入转换为小写,然后将查找形式转换为小写:

Above your srchitems function simply returns the index in item_list given a color (entered as arguments to the program, e.g. argv[1], argv[2], ...) You can write a simple srchitems that converts all input to lowercase before preforming the lookup as:

/** search item_list for color code 'ccode', return index
 *  returns array index on success, -1 otherwise.
 */
int srchitems (char *ccode)
{
    int i;
    char lccode[MAXCC] = "";       /* array to hold lowercase color */

    strcpy2lower (lccode, ccode);  /* convert string to lowercase */

    for (i = 0; i < (int)nitems; i++)    /* lookup index */
        if (*lccode == *(item_list[i].name))
            if (!scmp (item_list[i].name, lccode))
                return i;

    return -1;   /* return -1 on error */
}

如果将其余部分一起解决难题,您可以执行以下类似操作。我留给您根据需要格式化输出。您可以将简单的字符串比较函数 scmp 替换为 strcmp (并包括 string.h )如果您有任何疑问,请告诉我。

If you put the remaining pieces of the puzzle together, you could do something similar to the following. I leave it to you to format the output as needed. You can replace the simple string comparison function scmp with strcmp (and include string.h) Let me know if you have any questions.

#include <stdio.h>

/* resister bands */
enum resistor_band_items { BLACK, BROWN, RED, ORANGE, YELLOW, GREEN, 
                        BLUE, VIOLET, GRAY, WHITE, UNKNOWN };
/* constants for min/max color arguments and max color chars */
enum { MINC = 3, MAXC = 4, MAXCC = 8 };

struct items    /* could be simple array of strings */
{
    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 };

#define nitems (sizeof item_list/sizeof *item_list)

int srchitems (char *ccode);
char *strcpy2lower (char *dest, char *src);
int scmp (char *a, char *b);
void prnitem (int i);

int main (int argc, char **argv) {

    if (argc < MAXC || MAXC + 1 < argc) { /* check 3 or 4 arguments */
        fprintf (stderr, "error: invalid input, usage: %s c1 c2 c3 [c4]\n"
                         "usage: enter color codes for 4 or 5-band resistor\n"
                         "       (tolerance ignored, enter 4 colors max)\n",
                        argv[0]);
        return 1;
    }

    int err = 0, i, mult, r;
    long rval = 0;

    printf ("\ncolor bands determining significant figures:\n\n");
    for (i = 1; i < argc - 1; i++) { /* convert colors to index */
        if ((r = srchitems (argv[i])) != -1) {
            rval = rval * 10 + r;    /* form significant figure */
            prnitem (r);
        }
        else {
            fprintf (stderr, "error: invalid color '%s'\n", argv[i]);
            err = 1;
        }
    }
    if (err) return 1;
    mult = srchitems (argv[i]);     /* get multiplier index  */
    rval *= multiplier[mult];       /* calculare final value */
    printf ("\nmultiplier:\n\n");
    prnitem (mult);
    printf ("\nresistor value : %ld -ohms\n\n", rval);

    return 0;
}

/** search item_list for color code 'ccode', return index
 *  returns array index on success, -1 otherwise.
 */
int srchitems (char *ccode)
{
    int i;
    char lccode[MAXCC] = "";

    strcpy2lower (lccode, ccode);

    for (i = 0; i < (int)nitems; i++)
        if (*lccode == *(item_list[i].name))
            if (!scmp (item_list[i].name, lccode))
                return i;

    return -1;
}

/** copy and convert string to lowercase.
 *  returns copy of string with all chars converted to lowercase.
 *  ('dest' must be of sufficient size of hold 'src')
 */
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;
}

/** simple string comparison (like strcmp) */
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;
}

void prnitem (int i)
{
    printf (" item_list[%d]  name: %-6s  id: %d\n", 
            i, item_list[i].name, item_list[i].id);
}

Example Use/Output

Valid resistor colors (uppercase or lowercase characters are fine)

Valid resistor colors (uppercase or lowercase characters are fine)

$ ./bin/resistor green blue yellow

color bands determining significant figures:

 item_list[5]  name: green   id: 5
 item_list[6]  name: blue    id: 6

multiplier:

 item_list[4]  name: yellow  id: 4

resistor value : 560000 -ohms


$ ./bin/resistor Red Orange Violet Black

color bands determining significant figures:

 item_list[2]  name: red     id: 2
 item_list[3]  name: orange  id: 3
 item_list[7]  name: violet  id: 7

multiplier:

 item_list[0]  name: black   id: 0

resistor value : 237 -ohms

Invalid colors generate individual errors:

Invalid colors generate individual errors:

$ ./bin/resistor pink silver green

color bands determining significant figures:

error: invalid color 'pink'
error: invalid color 'silver'

Splitting Number Every 3rd char

Rather than a fairly complicated approach where you are relying on numeric calculations to test/separate your number, why not just convert your number to a string (without decimal places) and then simply work backwards from the end copying characters to a new string and add a space every 3rd character? It makes things a whole lot easier. (even though you are using a double for some unheard-of-reason -- assuming you will ultimately incorporate tolerance) It really makes no difference with this approach. Give the following a try:

Rather than a fairly complicated approach where you are relying on numeric calculations to test/separate your number, why not just convert your number to a string (without decimal places) and then simply work backwards from the end copying characters to a new string and add a space every 3rd character? It makes things a whole lot easier. (even though you are using a double for some unheard-of-reason -- assuming you will ultimately incorporate tolerance) It really makes no difference with this approach. Give the following a try:

void print_number (double number)
{
    char numstr[3 * MAXCC] = "", sepstr[3 * MAXCC] = "";
    char *p = NULL;
    size_t idx = 0, len = 0;

    sprintf (numstr, "%.0lf", number);  /* write double to string */
    len = strlen (numstr);              /* get length */
    p = sepstr + 3 * MAXCC - 2;         /* set p at last char in sepstr */

    while (len--) {         /* for each char in numstr */
        if (idx++ == 3) {   /* if 3 characters copied  */
            idx = 1;        /* reset index */
            *p-- = ' ';     /* write a space in sepstr */
        }
        *p = numstr[len];   /* write char in sepstr    */
        if (len) p--;       /* decrement p if not at 0 */
    }

    printf ("p : '%s'\n", p);  /* print the separate value */
}

note, you can simply pass a character array to print_number and copy p to the array if you want to make the array available back in main for formatting reasons (you can even change print_number to return char * in that case.) Let me know if it works. If you can’t do it that way, then I’ll work through your numeric logic, but that will take aspirin and will probably be in the morning :)

note, you can simply pass a character array to print_number and copy p to the array if you want to make the array available back in main for formatting reasons (you can even change print_number to return char * in that case.) Let me know if it works. If you can't do it that way, then I'll work through your numeric logic, but that will take aspirin and will probably be in the morning :)

Example print_number Output

Example print_number Output

           5 => '5'
          55 => '55'
         555 => '555'
        5555 => '5 555'
       55555 => '55 555'
      555555 => '555 555'
     5555555 => '5 555 555'
    55555555 => '55 555 555'
   555555555 => '555 555 555'

Example of Actual Implementation

Here is the way I implemented it into my code. Essentially, you just move sepstr declaration/initialization into main and then pass it as an array to your print_number (my sepnumber below).

Here is the way I implemented it into my code. Essentially, you just move sepstr declaration/initialization into main and then pass it as an array to your print_number (my sepnumber below).

char *sepnumber (char *s, long val);
...
    long rval = 0;
    char rstr[3 * MAXCC] = "";
    ...
    printf ("\nresistor value : %s -ohms\n\n", sepnumber (rstr, rval));

    return 0;
}
...
/** 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;
}

Example/Output

$ ./bin/resistor green blue yellow

color bands determining significant figures:

 item_list[5]  name: green   id: 5
 item_list[6]  name: blue    id: 6

multiplier:

 item_list[4]  name: yellow  id: 4

resistor value : 560 000 -ohms


$ ./bin/resistor Red Orange Violet Brown

color bands determining significant figures:

 item_list[2]  name: red     id: 2
 item_list[3]  name: orange  id: 3
 item_list[7]  name: violet  id: 7

multiplier:

 item_list[1]  name: brown   id: 1

resistor value : 2 370 -ohms

Reinitialize Values When Looping for Input

Given your description of the problem, I strongly suspect the issue you are having is due to not resetting/reinitializing rval = 0; (your resistor_value) at the end of each loop (or some similar value). Always check which values may be additive, etc. and remember to reset those values at the beginning of each loop. Another way to handle this in most cases is to declare the variables within the scope of the loop so that they are automatically reinitialized each iteration.

Given your description of the problem, I strongly suspect the issue you are having is due to not resetting/reinitializing rval = 0; (your resistor_value) at the end of each loop (or some similar value). Always check which values may be additive, etc. and remember to reset those values at the beginning of each loop. Another way to handle this in most cases is to declare the variables within the scope of the loop so that they are automatically reinitialized each iteration.

Using block scope for the loop, your main should be similar to the following:

Using block scope for the loop, your main should be similar to the following:

int main (void) {

    for (;;) {                      /* loop for input */
        int err = 0, i, mult, r;    /* variables have block scope only */
        long rval = 0;
        char ccode[MAXCC] = "", rstr[3 * MAXCC] = "";

        printf ("\nEnter the colours of the resistor's three bands,\n"
                "beginning with the band nearest to the end.\n");
        for (i = 0; i < MINC; i++) { /* convert colors to index */
            printf ("Band %d => ", i + 1);
            if (scanf (" %7s", ccode) != 1) {
                fprintf (stderr, "error: invalid input or EOF.\n");
                return 1;
            }
            if ((r = srchitems (ccode)) != -1) {
                if (i < 2) {
                    rval = rval * 10 + r;    /* form significant figure */
                }
                else {
                    mult = srchitems (ccode);  /* get multiplier index  */
                    rval *= multiplier[mult];  /* calculare final value */
                }
            }
            else {
                fprintf (stderr, "error: invalid color '%s'\n", ccode);
                err = 1;
            }
        }
        if (err) return 1;
        printf ("Resistor value : %s -ohms\n", sepnumber (rstr, rval));
        printf ("\nDo you want to decode another resistor (y/n)? ");
        if (scanf (" %7s", ccode) != 1) {
            fprintf (stderr, "error: invalid input or EOF.\n");
            return 1;
        }
        if (*ccode != 'y' && *ccode != 'Y') break;
    }

    return 0;
}

Example Use/Output

$ ./bin/resistor2

Enter the colours of the resistor's three bands,
beginning with the band nearest to the end.
Band 1 => green
Band 2 => blue
Band 3 => yellow
Resistor value : 560 000 -ohms

Do you want to decode another resistor (y/n)? y

Enter the colours of the resistor's three bands,
beginning with the band nearest to the end.
Band 1 => red
Band 2 => orange
Band 3 => orange
Resistor value : 23 000 -ohms

Do you want to decode another resistor (y/n)? n

I suspect you can find your error with this hint.

I suspect you can find your error with this hint.

这篇关于以色带为输入计算电阻值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆