以色带为输入计算电阻值

Calculating the resistor value with its color bands as input

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

忽略电阻公差。

例如

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. 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,当且仅当第一个输入(band 1)无效时,程序才会 运行。如果第一个波段无效而第二个波段或第三个波段无效,则程序将停止执行。

这是我一直在处理的代码:

#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 个数字打印一个 space。 (它适用于大多数组合)

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

修订版 2

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

代码如下:

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

此版本在第一个循环中运行良好,但在第二个循环中计算出错误的电阻值。 它会有点困难地打印无效条目! 输入无效颜色后,程序将不会计算任何电阻值。

输出示例:

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

最终版本,

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

非常感谢 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;
}

输出示例

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

我觉得你的数字打印代码太复杂了。看下面的代码:

int num = 2345666;
printf("%d\n", num);

int triad[10];
int i = 0;
do
{
    triad[i++] = num % 1000;
    num /= 1000;
}while(num);

for(i--; i >= 0; i--)
    printf("%d ", triad[i]);
printf("\n");

它又快又脏。打磨一下。

用于确定电阻值有效数字的代码比需要的要复杂得多。由于您声明了结构 item_list 的全局数组,因此要形成有效数字,您需要做的就是使用 item_list 作为查找 - table 来查找 band-color 的索引进入。对于每个后续颜色(第 2 个 [和第 5 个波段的第 3 个]),您只需在添加索引之前将当前电阻值乘以 10

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

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 函数之上 return 给定颜色 item_list 中的索引(作为程序的参数输入,例如 argv[1]argv[2], ...) 您可以编写一个简单的 srchitems 在执行查找之前将所有输入转换为小写:

/** 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)如果您有任何问题,请告诉我。

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

示例Use/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 : 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

无效的颜色会产生个别错误:

$ ./bin/resistor pink silver green

color bands determining significant figures:

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

每 3 个字符拆分数字

而不是依赖数字计算 test/separate 你的数字的相当复杂的方法,为什么不直接将你的 number 转换为字符串(没有小数位)然后简单地向后工作从最后将字符复制到新字符串并每第 3 个字符添加一个 space?它使事情变得容易得多。 (即使您出于某些闻所未闻的原因使用 double - 假设您最终会纳入容忍度)它与这种方法确实没有区别。试试以下方法:

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 */
}

注意,如果你想让数组在main 出于格式原因(在这种情况下,您甚至可以将 print_number 更改为 return char *。)如果可行,请告诉我。如果你不能那样做,那么我会研究你的数字逻辑,但这需要服用阿司匹林并且可能会在早上 :)

示例print_number输出

           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'

实际实施示例

这是我在代码中实现它的方式。本质上,您只需将 sepstr declaration/initialization 移动到 main 中,然后将其作为数组传递给您的 print_number (下面是我的 sepnumber)。

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

循环输入时重新初始化值

鉴于你对问题的描述,我强烈怀疑你遇到的问题是由于在每个循环结束时没有 resetting/reinitializing rval = 0; (你的 resistor_value)一些相似的值)。始终检查哪些值可能是附加值等,并记住在每个循环开始时重置这些值。在大多数情况下,另一种处理此问题的方法是在循环范围内声明变量,以便在每次迭代时自动重新初始化它们。

为循环使用块作用域,您的 main 应类似于以下内容:

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

示例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

我想你可以通过这个提示找到你的错误。