我一直在努力学习如何用C语言进行数周的编程,但我现在处于一种无法让自己脱身的地步。我的程序应该读取四个和五个带电阻器颜色代码(即AGIE)的文件,其中每个字母代表电阻带颜色,然后使用标准电阻器带解释图打印电阻器的值和上限和下限容差限制。
截至目前,我认为我正好在我的文件中阅读;但是,我的功能没有产生任何结果,我不知道去哪里试图破译4或5个频段。
示例输入为:(其中604是文件中电阻代码的数量)
604
CCIF
IJFCJ
CFHJ
BJFG
KIJDJ
EKCC
HABKC
JFID
ECHDA
IJHEB
任何建议都会非常感激。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void FourBR(char ccode[], long cval[], double rval);
void FiveBR(char ccode[], long cval[], double rval);
int main()
{
//DECLARE VARIABLES AND POINTERS//
char str[604];
char ccode[6];
long cval[6];
int num, i;
double resistorval, rval;
FILE *fpin;
FILE *fpoutpt;
//OPEN FILE//
fpin=fopen("G:\\EGR 107\\EEHW4(AGraff)\\resistorInput.txt", "r");
fpoutpt=fopen("G:\\EGR 107\\EE\\EEHW4(AGraff)\\resistorOutput.txt", "w");
//ERROR CHECK//
if(fpin==NULL)
{
printf("Error reading file.\n");
exit (0);
}
fscanf(fpin, "%d", &num);
printf("# of Resistors: %d\n", num);
while((fgets (str, 604, fpin))!= NULL) {
FourBR(ccode, cval, rval);
FiveBR(ccode, cval, rval);
fclose(fpin);
return 0;
}
void FourBR(char ccode[], long cval[], double rval)
{
int i, j, k, mult;
for(i=0; i<=6; i++) {
switch (ccode [0]) {
case('A'):
cval[0]=0;
case('B'):
cval[0]=1;
case('C'):
cval[0]=2;
case('D'):
cval[0]=3;
case('E'):
cval[0]=4;
case('F'):
cval[0]=5;
case('G'):
cval[0]=6;
case('H'):
cval[0]=7;
case('I'):
cval[0]=8;
case('J'):
cval[0]=9;
}
}
for(j=0; j<=6; j++)
{
switch (ccode[1])
{
case 'A':
cval[1]=0;
case('B'):
cval[1]=1;
case('C'):
cval[1]=2;
case('D'):
cval[1]=3;
case('E'):
cval[1]=4;
case('F'):
cval[1]=5;
case('G'):
cval[1]=6;
case('H'):
cval[1]=7;
case('I'):
cval[1]=8;
case('J'):
cval[1]=9;
}
}
for (mult=0; mult<=6; mult++)
{
switch (ccode[2])
{
case('A'):
cval[2]=1;
case('B'):
cval[2]=10;
case('C'):
cval[2]=100;
case('D'):
cval[2]=1000;
case('E'):
cval[2]=10*pow(10,3);
case('F'):
cval[2]=10*pow(10,4);
case('G'):
cval[2]=10*pow(10,5);
case('H'):
cval[2]=10*pow(10,6);
case('I'):
break;
case('J'):
break;
case('K'):
cval[2]=0.1;
case('L'):
cval[2]=0.01;
}
}
for (k=0; k<=6; k++) {
switch (ccode[3]) {
case 'A':
break;
case('B'):
cval[3]=0.01;
case('C'):
cval[3]=0.02;
case('D'):
break;
case('E'):
break;
case('F'):
cval[3]=0.005;
case('G'):
cval[3]=0.0025;
case('H'):
cval[3]=0.001;
case('I'):
cval[3]=0.0005;
case('J'):
break;
case('K'):
cval[3]=0.05;
case('L'):
cval[3]=0.1;
}
}
}
答案 0 :(得分:1)
有一点需要注意,我并不完全了解您的颜色映射代码方案,我认为以下内容可以帮助您完成项目。出于以下代码的目的,我让A-J
在电阻图上提供0-9
的映射,以向您展示将代码映射到电阻值的方法。 (如果输入代码包含'K'
或更高,则它被踢出 - 您可以填写该逻辑)
注意:以下代码仅提供有效数字色带的映射(4频段的频段/字符1和2,以及5频段电阻的1和2和3) )。有效数值乘以乘数(4频段中的频段3和5频段电阻中的频段4)以得到相应的值。 (忽略容差)。
在任何项目中你需要做的第一件事就是掌握你将要处理的值范围,以便选择哪种数据类型能够充分保存值,同时不会浪费内存。查看输入,您将读取最多5个字符的字符串。 注意,以文件'\n'
结尾的行也是fgets
尝试阅读的字符,和您需要{{}的空间1}} charcter null-terminating
在最后。因此,用于读取输入文件的最小字符串大小为'\0'
。 (虽然你可以使用最小值,但是如果你将代码移植到dos并且有7
行结尾来处理,或者有一个或两个流浪的字符串,那么添加一些额外的字符是明智的。文件)。一个合理的选择是在'\r\n'
范围内。现在,不要在代码中对9-10
进行硬编码,而是使用10
在文件开头设置一次此值。 (例如#define
- 您的&#39;行最多&#39;)没有分号。如果需要,您可以在将来轻松调整值。
同样的逻辑适用于其余的变量。根据经验,如果范围包括正值和负值,请选择#define LMAX 10
或int
。如果值始终为正数,请选择long
或size_t
等。这有助于快速提供参考:
unsigned
选择类型并选择变量名称后,请记住始终将变量初始化为值!尝试从单位变量中读取未定义行为,并且开始C程序员的祸根。
接下来,您需要获取/退出程序的信息。在您的情况下,您需要输入和输出文件名。您可以随时提示并阅读变量,但是传递代码运行所需的信息(作为程序的参数)要容易得多,而且通常被接受。 (即通过 data type sizes for x86_64:
sizeof (char) : 1
sizeof (char*) : 8 (all pointers)
sizeof (short) : 2
sizeof (int) : 4
sizeof (long) : 8
sizeof (long long) : 8
data type storage sizes for x86_64:
char - signed : -128 to 127
char - unsigned : 0 to 255
short - signed : -32768 to 32767
short - unsigned : 0 to 65535
int - signed : -2147483648 to 2147483647
int - unsigned** : 0 to 4294967295
(l)long - signed : -9.2234e+18 to 9.2234e+18
(l)long - unsigned : 0 to 1.8447e+19 18446744073709551613
** size_t is an unsigned int for practical purposes
)简单地使用argv[1], argv[2], ...
,你有一个字符串数组,它们是int main (int argc, char **argv)
中代码的参数(argv [0]始终是用于运行的程序名称该程序)。当您将代码传入/传出代码或代码中的函数时,验证/验证输入。
对于你的电阻器程序(以及任何程序),在开始啄食之前,通过思考你需要代码做什么,你可以让自己更轻松。输入,处理和输出。 (即,获取文件名,打开输入/输出文件,获取字符串输入,验证,剥离尾随换行符,读取单个带字符,读取乘数,将有效数字转换为数字,将乘数转换为数字,乘以获取电阻值等。预先这样做可以节省大量时间。它提供了一个您可以遵循的路线图,它允许您识别相似/重复的任务,以便分解为重复使用的功能。
你已经打开了文件,你已经阅读了文件(谁知道argv
来自哪里),你开始修改转换方法,但这几乎就是轮子脱落的地方。在你的函数中,你理解你需要查看每个字符并将字符值映射到一个数字,但是你需要一个308
(十进制)值以及需要{{1值? (这只需要学习并密切关注)
从字符串输入中获取电阻值并不太困难。如果您将输入字符的数量限制为numeric
(最多5个频段),那么您就知道,对于4和4,您的重要数字频段将是character
之间的字符。 5频段电阻。使用5
的方法很好,但有一些技巧可以提供帮助。
对于乘数,您知道字符串中的最后一个字符(波段)始终是。 (在0 < (length-2)
)
不要使用switch statement
进行重要的数字转换,而是查看[ASCII Table and Descriptions]。请注意,字符string[length-2]
的ASCII值为switch
,'A'
的值为65
。您可以使用字符值之间的差异将字母转换为字符数字,方法是将差异添加到字符'J'
。 (即74
- '0'(48)
[字符'G'(71) - 'A'(65) = 6
])您希望转换后的字符串中的每个值都具有数字的字符值。 (例如不小数值'0'(48) + 6 = 54
)。请注意与'6'
语句所做的细微差别。 (它将小数,而不是字符值分配给6
- 来修复它,你必须引用你的数字)。除非您要手动将(在您的情况下为switch
数组)转换为数字,否则所有转换例程cval[x]
都希望收到一个字符串>> 的字符串转换,而不是一串小数。
要找到乘数,你可以做几乎相同的事情,除了这次做想要小数值,你会直接使用该值而无需调用转换例程。在这里,您可以通过简单地获取字符之间的差异并将cval
提升到该幂来找到乘数的位置值。 (不需要数学库,快速循环可以)选择atoi, strtol, etc..
乘数变量的初始值,可以在将波段转换为某个值后快速计算乘数。一个简单的循环,将乘数值乘以10表示的频段就足够了。
所有那些比我原先想象的要长得多的笨蛋,我总结了一个快速的例子来说明这些要点。 (注意:我使用10
收集字符数字,然后我将值转换为数字1
- 这与您的命名相反)另请注意,只有必需的程序参数是输入文件。如果未给出输出文件,它只会将输出与错误消息一起转储到屏幕。 (方便发展)
看看代码。花点时间了解每个部分正在做什么(这是你需要付出的代价),并记住可能有一种不同的正确方法可以解决这个问题。只要它们是正确的,就没有其他权利。
你已经做出了追求C的正确选择。没有其他高级语言可以提供C所具有的灵活性和控制力。但是,通过这种灵活性和控制水平,有责任学习如何正确使用它。这里有很多好人可以提供帮助:
ccode
<强>编译强>
cval
您可以删除#include <stdio.h>
#include <stdlib.h> /* for strtol */
#include <string.h> /* for strlen */
#include <errno.h> /* for errno */
#define LMAX 10
unsigned long resistor_val (char *s, unsigned char len);
int main (int argc, char **argv)
{
if (argc < 2 ) {
fprintf (stderr, "Error: insufficient input, usage: %s infile [outfile]\n", argv[0]);
return 1;
}
char str[LMAX] = {0}; /* input buffer (LMAX-1 chars) */
FILE *ifp = NULL; /* input file pointer */
FILE *ofp = NULL; /* output file pointer (stdout) */
size_t idx = 0; /* line index / counter */
size_t nchr = 0; /* number of chars in str */
unsigned long rval = 0; /* resistor value from ccode */
/* open/validate input file */
if (!(ifp = fopen (argv[1], "r"))) {
fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
exit (EXIT_FAILURE);
}
/* open/validate output file (default: stdout) */
if (argc > 2) {
if (!(ofp = fopen (argv[2], "w"))) {
fprintf (stderr, "error: file open failed '%s'\n", argv[2]);
exit (EXIT_FAILURE);
}
}
else
ofp = stdout;
/* read loop - read each line in the input file */
while (fgets (str, LMAX, ifp) != NULL)
{
/* get the length of each string read */
nchr = strlen (str);
/* strip CR & LF from each line */
while (nchr > 0 && (str[nchr-1] == '\r' || str[nchr-1] == '\n'))
str [--nchr] = 0;
/* call resistor_val function, output results (or line if error) */
if ((rval = resistor_val (str, nchr)))
fprintf (ofp, " line[%3zu] code: %-5s rval: %lu\n", idx, str, rval);
else
fprintf (ofp, "*line[%3zu] code: %-5s\n", idx, str);
idx++;
}
/* close input/output files */
if (ifp) fclose (ifp);
if (ofp != stdout) fclose (ofp);
return 0;
}
/* read resistor colors presuming 4 or 5 band resistor
where the last band indicates 'tolerence', and the
band before it is the 'multiplier'. On success return
the ohm value for the resistor before any tolerence
or reliability factors are applied, 0 otherwise.
presumes code values of [A-J] only!
*/
unsigned long resistor_val (char *s, unsigned char len)
{
char ccode[LMAX] = {0}; /* array to hold numbers */
unsigned long cval = 0; /* converted ccode value */
unsigned char idx = 0; /* ccode index / counter */
unsigned char it = 0; /* loop iterator */
unsigned long mult = 1; /* multiplier for resistor */
/* validate input string and length */
for (it = 0; it < len; it++)
if ((s[it] < 'A' || s[it] > 'J') {
fprintf (stderr, "%s() error: argument contains chars outside [A-J] : '%s'.\n",
__func__, s);
return 0;
}
if (len > 5) {
fprintf (stderr, "%s() error: input exceeds 5 characters\n", __func__);
return 0;
}
/* set the numeric value for each resistor value character */
for (idx = 0; idx < len - 2; idx++)
ccode[idx] = '0' + s[idx] - 'A';
/* set the multiplier for the resistor */
for (it = 0; it < s[len - 2] - 'A'; it++)
mult *= 10;
/* convert ccode to a number */
errno = 0;
cval = strtoul (ccode, NULL, 10);
if (errno) {
fprintf (stderr, "%s() error: invalid cval conversion.\n", __func__);
return 0;
}
/* return multiplier times cval */
return mult * cval;
}
(生成调试信息)以进行最终编译,但如果您要使用gcc -Wall -Wextra -g -o resistors resistors.c
调试器则需要它。 (了解-g
是必须的)。
<强>输出强>
gdb