以色带为输入计算电阻值
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
- 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'.
现在我很难获得总阻力的格式 (#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
这里是答案中的修改代码。
我不使用 argc
和 argv
的原因是客户端有一个需要遵循的受限格式(这让我发疯!)
代码如下:
//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
我想你可以通过这个提示找到你的错误。
我正在尝试开发一个 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
- 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'.
现在我很难获得总阻力的格式 (#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
这里是答案中的修改代码。
我不使用 argc
和 argv
的原因是客户端有一个需要遵循的受限格式(这让我发疯!)
代码如下:
//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
我想你可以通过这个提示找到你的错误。