我使用fgetc()遇到了一个大问题,我无法弄清楚...我尝试解析一个文本文件,一切都编译但在执行时我得到了一个无限循环x或一个段错误(Code :: blocks ),我的文本文件是这样的:{“USD_EUR”:“0.8631364”,“EUR_USD”:“1.3964719”},16个汇率变化。我试着把我所有的浮动放在率[16] ......
void read(float change[4][4], char* myFile)
{
FILE* file = NULL;
file = fopen(myFile, "r+");
int value,i;
float rate[16];
char* str = "";
if (file != NULL)
{
do
{
value = fgetc(file);
printf("%c \n",value);
while(value > 48 && value < 57)
{
value = fgetc(file);
strcat(str, value);
//printf("%s \n", str);
}
rate[i] = atof(str);
i++;
str = "";
}while(value != EOF);// 125 = }
change[0][1] = rate[5];
change[0][2] = rate[0];
change[0][3] = rate[15];
change[1][0] = rate[6];
change[1][1] = rate[14];
change[1][2] = rate[7];
change[1][3] = rate[10];
change[2][0] = rate[8];
change[2][1] = rate[2];
change[2][2] = rate[12];
change[2][3] = rate[4];
change[3][0] = rate[3];
change[3][1] = rate[13];
change[3][2] = rate[11];
change[3][3] = rate[9];
fclose(file);
}
else
{
printf("Unable to read the file!\n");
}
}
我也尝试使用EOF,但我只有数字之前的字符,然后退出循环ex:{“USD_EUR”:“
答案 0 :(得分:1)
问题1:
char* str = "";
将str
声明为指向静态字符串的指针。这会在内存中创建一个文字""
,并为其指出str
,这不是您可以安全更改的任何内容。你想要像
char str[30] = "";
问题2和3:
strcat(str, value);
尝试追加str
,这是不安全或正确的。此外,作为客座说明,您正在尝试strcat(char *, int)
,这不是正确的用法。 strcat(char *, char *)
是正确的。注意 - 这个不意味着你应该strcat(str, (char *) &value);
- 你需要理解字符串在C中如何实现为char
数组,特别是关于零终止。
问题4:
str = "";
请参阅上面的user3629249评论。给出适当的声明,
str[0] = '\0';
是对的。
问题5:
再次,归功于user3629249,
在'更改'中,正在跳过位置更改[0] [0]。
答案 1 :(得分:1)
我建议你只使用fscanf
。
E.g
FILE *file;
int i = 0, status;
float value;
float rate[16];
file = fopen(myFile, "r");
if(file == NULL){
printf("Unable to read the file!\n");
return ;
}
while((status=fscanf(file, "%f", &value))!=EOF){
if(status==1){
rate[i++] = value;
if(i==16)//full
break;
} else {
fgetc(file);//one character drop
}
}
fclose(file);
答案 2 :(得分:1)
除了其他答案中提供的解决方案之外,当面对一系列凌乱的输入阅读时,使用{{1}提供的面向行的输入函数可能更容易(例如libc
或fgets
)。通常(并非总是)将数据一次一行地读取到缓冲区中,可以使用getline
提供的其他工具(例如libc
,strtok
等)更灵活地解析数据。 ..)
对于其他数据,面向字符的输入是更好的选择。在您的情况下,这些行与许多strsep
,'"'
,':'
和' '
进行隔行扫描。这使得构造','
格式字符串以在单个调用中读取两种汇率或使用任何字符串解析工具(如fscanf
)变得困难。所以这真是一个艰难的要求。我同意,BluePixyes&#39;在strtok
调用中解析单个float
的解决方案是一个很好的解决方案。 面向行的替代方法是一次读取一行,然后使用fscanf
转换行中找到的浮点值。 strtof
提供的唯一优势是对转换的错误检查,允许您验证良好的浮点转换。这是面向行的解决方案的一种方法:
strtof
示例输入:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
int main () {
FILE* file = NULL; /* aways initialize variables */
float rate[16] = {0.0}; /* market rates 1st & 2nd */
char myFile[50] = {0}; /* input filename */
char line[128] = {0}; /* input line buffer */
char *p = NULL; /* pointer to parse line */
char *ep = NULL; /* pointer to parse line */
size_t idx = 0; /* index for rate array values */
size_t it = 0; /* general index iterator */
/* prompt for filename */
printf ("\n Please enter filename to read rates from: ");
scanf ("%[^\n]%*c", myFile);
/* open & validate file */
file = fopen (myFile, "r");
if (!file) {
fprintf(stderr, "error: Unable to read the file!\n");
return 1;
}
/* using line-oriented input to read line, then parse */
while (fgets (line, 127, file) != NULL)
{
if (idx == 16) {
fprintf (stderr, "warning: array full.\n");
break;
}
p = line; /* parse line for floats */
while (*p) { /* find first digit or end */
while (*p && (*p < 48 || *p > 57) ) p++;
if (!*p) break; /* validate not null */
rate[idx++] = strtof (p, &ep); /* get float, set end-ptr */
if (errno != 0 || p == ep) /* validate conversion */
fprintf (stderr, "discarding: rate[%zd] invalid read\n", --idx);
p = ep; /* set ptr to end-ptr */
}
}
fclose (file);
printf ("\n The exchange rates read from file:\n\n");
for (it = 0; it < idx; it++)
printf (" rate[%2zd] = %9.7f\n", it, rate[it]);
printf ("\n");
return 0;
}
<强>输出:强>
$ cat dat/rates.txt
"USD_EUR": "0.8631364", "EUR_USD": "1.3964719"
"USD_AGT": "0.9175622", "EUR_USD": "1.0975372"
"USD_BRZ": "0.8318743", "EUR_USD": "1.1713074"
"USD_COL": "0.9573478", "EUR_USD": "1.0537964"
"USD_GIA": "0.7904234", "EUR_USD": "1.5393454"
注意:检查您的$ ./bin/read_xchgrates
Please enter filename to read rates from: dat/rates.txt
The exchange rates read from file:
rate[ 0] = 0.8631364
rate[ 1] = 1.3964719
rate[ 2] = 0.9175622
rate[ 3] = 1.0975372
rate[ 4] = 0.8318743
rate[ 5] = 1.1713074
rate[ 6] = 0.9573478
rate[ 7] = 1.0537964
rate[ 8] = 0.7904234
rate[ 9] = 1.5393454
手册页,了解您的编译器可能需要的任何其他strtof
。
答案 3 :(得分:0)
代码具有以下顺序:
fgetc会产生&#39; U&#39;
这不是0 ... 9范围内的值, 所以直接尝试将str转换为rate [i]
(其中&#39; i&#39;尚未初始化为已知值)
由于没有数字保存在str点, rate []的某些未知偏移量设置为0 (这是未定义的行为)
然后是未知的价值&#39;我&#39;得到增加 和以下行:str =&#34;&#34;执行对字符串没有影响 (除非每个文字位于.const部分的不同位置)
并重复外循环。
最后,输入1 ... 8范围内的字符
然后,在内循环中,第一个数字是SKIPPED 另读一个字符。
从您的示例中,下一个字符是&#39;。&#39; 这可能导致内循环退出
然而, 行:strcat(str,value); 应该导致seg故障事件 由于尝试写入可执行文件的.const部分