gpt4 book ai didi

c - C,读取文件,解释文件,将解释输出到新文件中

转载 作者:行者123 更新时间:2023-11-30 15:22:13 25 4
gpt4 key购买 nike

数周以来,我一直在努力学习如何使用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;
}
}
}

最佳答案

由于我不完全了解您的颜色映射代码方案,因此我认为以下内容将对您的项目有所帮助。为了下面的代码,我让A-J在电阻器图表上提供0-9的映射,以向您展示一种将代码映射到电阻器值的方法。 (如果输入代码包含'K'或更高版本,则会将其踢出-您可以填写该逻辑)

注意:以下代码仅提供了有效数字色带的映射(4频段的带/字符1和2,5频段电阻的为1、2和3)。有效数字值乘以乘数(4频段中的频段3和5频段电阻器中的频段4)得出一个电阻值。 (公差被忽略)。

在任何项目中需要做的第一件事之一就是掌握要处理的值的范围,以便选择哪种数据类型将足以保留值,同时又不会不必要地浪费内存。查看您的输入,您将读取最多5个字符的字符串。请注意,以文件'\n'结尾的行也是fgets会尝试读取的字符,并且您需要在末尾保留null-terminating字符'\0'的空间。因此,用于读取输入文件的最小字符串大小为7。 (尽管您可以省去最少的费用,但还是明智的做法是添加几个其他字符,以防您将代码移植到dos上并要处理'\r\n'行尾,或者文件中有一个或两个杂散字符) 。原因选择在9-10范围内。现在,无需在整个代码中对10进行硬编码,而是在文件的开头使用一次#define来设置此值一次。 (例如,#define LMAX 10-“最大行数”不使用分号)。如果需要,您将来可以轻松调整该值。

同样的逻辑适用于其余变量。根据经验,如果范围同时包含正值和负值,请选择intlong。如果这些值始终为正,请选择size_tunsigned等。这有助于快速使用参考:

 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


选择类型并选择变量名称后,请记住始终将变量初始化为一个值!尝试从统一变量中读取内容是“未定义行为”,并且是新手C程序员的祸根。

接下来,您需要获取有关程序的信息。您需要输入和输出文件名。您始终可以提示输入并读取变量,但是将代码需要运行的信息作为程序的参数传递给它很容易且通常被接受。 (即通过 argv[1], argv[2], ...),只需使用 int main (int argc, char **argv),您就有一个字符串数组,这些字符串是 argv中代码的参数(argv [0]始终是用于运行程序的程序名称)。当您将参数传入/传出代码或传递给代码中的函数时,请验证/验证输入。

对于电阻器程序(和任何程序),您可以在开始啄食之前仔细考虑需要执行的代码,从而使自己的生活更轻松。输入,处理和输出。 (例如,获取文件名,打开输入/输出文件,获取字符串输入,验证,去除尾随的换行符,读取单个带区字符,读取乘数,将有效数字转换为数字,将乘数转换为数字,乘以获取电阻值等)。 )预先进行此操作可节省大量时间。它提供了一个路线图供您遵循,并且使您可以识别相似/重复的任务,以分解为多个功能以供重复使用。

您已经打开了文件,已经读取了文件(谁知道 308的来源),并且您开始尝试一种转换方法,但是车轮掉下来的地方差不多。在您的函数中,您了解到需要查看每个字符并将该字符值映射到数字,但是您迷上了需要什么 numeric(十进制)值和什么需要是 character值? (这也需要学习和密切关注)

从字符串输入获取电阻值并不难。如果您将输入字符的数量限制为 5(最大5频段),则您知道对于4频段和5频段电阻器,重要的数字频段将是 0 < (length-2)之间的字符。使用 switch statement的方法很好,但是有一些技巧可以帮助您。

对于乘数,您将知道它始终是字符串中倒数第二个字符(带)。 (在 string[length-2]处)

代替使用 switch进行有效数字转换,而是查看 [ASCII Table and Descriptions]。请注意,字符 'A'的ASCII值为 65,而 'J'的值为 74。您可以使用字符值之间的差异,通过将差异添加到字符 '0'(48)来将字母转换为字符数字。 (即 'G'(71) - 'A'(65) = 6- '0'(48) + 6 = 54 [字符 '6'])您希望转换后的字符串中的每个值都具有数字的字符值。 (例如,不是十进制值 6)。注意与您的 switch语句所做的细微差别。 (它是为 cval[x]分配小数而不是字符值,要修正它,您必须引用数字)。除非您要手动将数字转换(在您的情况下为 cval数组)转换为数字,否则所有转换例程 atoi, strtol, etc..都希望接收到一个充满字符值的字符串,而不是十进制字符串。

要找到乘数,您可以做几乎相同的事情,除了这次您确实想要十进制值,因为您将直接使用该值而无需调用转换例程。在这里,您可以通过简单地获取字符之间的差并将 10提升为该幂来找到乘数位值。 (不需要数学库,将执行一个快速循环。)为 1的乘数变量选择一个初始值,可以在将波段转换为值后快速计算乘数。一个简单的循环即可将乘数乘以带指示的次数10。

有了所有的刺戳,结果比我原先想的要长得多,我整理了一个简短的例子来说明要点。 (注意:我使用 ccode收集字符数字,然后调用转换为数字 cval的值-与您的命名相反)。另外请注意,程序唯一需要的参数是输入文件。如果未提供输出文件,它将仅将输出与错误消息一起转储到屏幕上。 (方便开发)

看一下代码。花时间了解每个部分的工作方式(这是您要付出的代价),并记住可能有解决这一问题的各种不同的正确方法。只要它们是正确的,没有别的权利比另一个正确。

您已经选择了追求C的正确选择。没有其他高级语言可以提供C所具有的灵活性和控制力。但是,有了这种灵活性和控制能力,就有责任学习如何正确使用它。这里有很多好人可以帮助您:

#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调试器,则需要这样做。 (必须了解 gdb)。

输出量

$ ./bin/resistors dat/resifile.txt dat/resfile.txt
resistor_val() error: argument contains chars outside [A-J] : '604'.
resistor_val() error: argument contains chars outside [A-J] : 'KIJDJ'.
resistor_val() error: argument contains chars outside [A-J] : 'EKCC'.
resistor_val() error: argument contains chars outside [A-J] : 'HABKC'.

$ cat dat/resfile.txt
*line[ 0] code: 604
line[ 1] code: CCIF rval: 2200000000
line[ 2] code: IJFCJ rval: 89500
line[ 3] code: CFHJ rval: 250000000
line[ 4] code: BJFG rval: 1900000
*line[ 5] code: KIJDJ
*line[ 6] code: EKCC
*line[ 7] code: HABKC
line[ 8] code: JFID rval: 9500000000
line[ 9] code: ECHDA rval: 427000
line[ 10] code: IJHEB rval: 8970000

关于c - C,读取文件,解释文件,将解释输出到新文件中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29267958/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com