使用 sscanf 时检查 null/empty 浮点值
Checking for null/empty float values when using sscanf
以下程序尝试使用 fgets
逐行读取输入文件,并使用 sscanf
将每个 comma delimited
浮点值保存到结构数组中(这方面的代码工作正常)。问题在于程序还应检测浮点值何时为 missing/empty,并为其分配浮点值 1.500
,然后将其保存到结构数组中。
编辑: 这应该是使用 VS2017 编译的,所以 Windows。
*注意:请注意,在发布此问题之前已经研究了以下问题:
How to check if a string returned by scanf is null
How to get scanf to continue with empty scanset
输入文件示例(第二行缺失值):
0.123f, 0.234f, 0.345f, 0.456f, 0.567f
1.987f, , 7.376f, 2.356f, 5.122f
9.111f, 1.234f, 7.091f, 6.672f, 9.887f
所需的输出(检测到第二行中的缺失值并将其设置为 1.500):
0.123 0.234 0.345 0.456 0.567
1.987 1.500 7.376 2.356 5.122
9.111 1.234 7.091 6.672 9.887
到目前为止,第一次尝试尝试将所有 5 个浮点数(每个都带有 'f' 后缀)扫描成字符串,然后使用 [= 检查这些字符串是 null/empty 还是零长度18=] 和 strlen
,最后涉及尝试对每个变量再次使用 sscanf
以将每个变量读入结构数组。
第二次尝试使用 if (sscanf(line, "%ff", &data[i].x) == NULL) { // ...some alert and assign 1.500}
检查 sscanf
是否成功,但也没有成功。第三次尝试,如下所示:
#include "stdio.h"
int main() {
typedef struct {
float x, y, vx, vy, mass;
}DATA;
FILE *file = fopen("null_detector.txt", "r");
if (file == NULL)
{
printf(stderr, "ERROR: file not opened.\n");
return EXIT_FAILURE;
}
int N= 3;
DATA* data = malloc(Nbodies * sizeof * data); // Array allocation
char line[256];
int i;
int inc = 1;
for (i = 0; i < Nbodies; i += inc)
{
fgets(line, sizeof(line), file);
// **Some info:
// Scan 5 float variables per line (this part works fine)
sscanf(line, "%ff, %ff, %ff, %ff, %ff",
&data[i].x, &data[i].y, &data[i].vx, &data[i].vy, &data[i].mass); // %ff accounts for 'f' suffix
// Now check if any of above vars are empty/NULL.
// NOTE: aware that these vars CANNOT be compared to NULL,
// but has been included to try and provide clarity for end goal
if (data[i].x == NULL)
{
//.. assign 1.500 to data[i].x
}
if (data[i].y == NULL)
{
//... same as above etc
}
// ...Repeat IF statements for all 5 vars
}
//Print the contents of array of structs to check for correct output
for (i = 0; i < Nbodies; i++)
{
printf("%.3f %.3f %.3f %.3f %.3f\n", data[i].x, data[i].y, data[i].vx, data[i].vy, data[i].mass);
}
return 0;
}
总结:
有谁知道如何将这个程序修改为:
- 在使用
fgets
读取文件的每一行时检测缺失的浮点值
- 用浮点值替换缺失的浮点值
1.500
- 将这些值写入结构数组,就像成功的非缺失值一样?
- 如代码中所述,我知道 struct float 变量无法与
NULL
进行比较。我将此比较包含在代码中只是为了让最终目标更加清晰。
您可以使用 strsep
分隔每一行。
str = strsep(&line, ",")
使用一个函数设置数据的值:
void set_data(DATA *dt, int count, float f) {
switch(count) {
case 0: dt->x = f; break;
case 1: dt->y = f; break;
case 2: dt->vx = f; break;
case 3: dt->vy = f; break;
case 4: dt->mass = f; break;
}
}
完整代码:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
float x, y, vx, vy, mass;
}DATA;
void set_data(DATA *dt, int count, float f) {
switch(count) {
case 0: dt->x = f; break;
case 1: dt->y = f; break;
case 2: dt->vx = f; break;
case 3: dt->vy = f; break;
case 4: dt->mass = f; break;
}
}
int main() {
FILE *file = fopen("text.txt", "r");
if (file == NULL)
{
printf( "ERROR: file not opened.\n");
return EXIT_FAILURE;
}
int N= 3;
DATA* data = malloc(N * sizeof(data)); // Array allocation
char *line;
int i;
int inc = 1;
size_t n = 0;
for (i = 0; i < N; i += inc)
{
getline(&line, &n, file);
int count = 0;
char *str;
while((str = strsep(&line, ",")) != NULL) {
if (strcmp(str, " ") == 0) {
set_data(&data[i], count, 1.5);
} else {
set_data(&data[i], count, atof(str));
}
// printf("count = %d\n", count);
// printf("token: %s\n", str);
count++;
}
}
//Print the contents of array of structs to check for correct output
for (i = 0; i < N; i++)
{
printf("%.3f %.3f %.3f %.3f %.3f\n", data[i].x, data[i].y, data[i].vx, data[i].vy, data[i].mass);
}
return 0;
}
输入:
#cat text.txt
0.123f, 0.234f, 0.345f, 0.456f, 0.567f
1.987f, , 7.376f, 2.356f, 5.122f
9.111f, 1.234f, 7.091f, 6.672f, 9.887
输出:
0.123 0.234 0.345 0.456 0.567
1.987 1.500 7.376 2.356 5.122
9.111 1.234 7.091 6.672 9.887
当没有输入值时,如果逗号之间至少有一个space,也可以只用sscanf
实现。
#include <stdio.h>
int main(void) {
char *str[] = {"0.123f, 0.234f, 0.345f, 0.456f, 0.567f",
"1.987f, , 7.376f, 2.356f, 5.122f",
"9.111f, 1.234f, 7.091f, 6.672f, 9.887f"};
float float_arr[3][5];
char temp[5][7];
for (unsigned i = 0; i < 3; i++) {
if (5 != sscanf(str[i], "%6[^,],%6[^,],%6[^,],%6[^,],%6[^,]",
temp[0], temp[1], temp[2], temp[3], temp[4]))
return printf("Error\n"), 1;
for (unsigned j = 0; j < 5; j++)
if (1 != sscanf(temp[j], "%ff", &float_arr[i][j]))
float_arr[i][j] = 1.500f;
}
// printing the result
for (unsigned i = 0; i < 3; i++) {
for (unsigned j = 0; j < 5; j++)
printf("%ff ", float_arr[i][j]);
printf("\n");
}
return 0;
}
输出
0.123000f 0.234000f 0.345000f 0.456000f 0.567000f
1.987000f 1.500000f 7.376000f 2.356000f 5.122000f
9.111000f 1.234000f 7.091000f 6.672000f 9.887000f
以下程序尝试使用 fgets
逐行读取输入文件,并使用 sscanf
将每个 comma delimited
浮点值保存到结构数组中(这方面的代码工作正常)。问题在于程序还应检测浮点值何时为 missing/empty,并为其分配浮点值 1.500
,然后将其保存到结构数组中。
编辑: 这应该是使用 VS2017 编译的,所以 Windows。
*注意:请注意,在发布此问题之前已经研究了以下问题:
How to check if a string returned by scanf is null
How to get scanf to continue with empty scanset
输入文件示例(第二行缺失值):
0.123f, 0.234f, 0.345f, 0.456f, 0.567f
1.987f, , 7.376f, 2.356f, 5.122f
9.111f, 1.234f, 7.091f, 6.672f, 9.887f
所需的输出(检测到第二行中的缺失值并将其设置为 1.500):
0.123 0.234 0.345 0.456 0.567
1.987 1.500 7.376 2.356 5.122
9.111 1.234 7.091 6.672 9.887
到目前为止,第一次尝试尝试将所有 5 个浮点数(每个都带有 'f' 后缀)扫描成字符串,然后使用 [= 检查这些字符串是 null/empty 还是零长度18=] 和 strlen
,最后涉及尝试对每个变量再次使用 sscanf
以将每个变量读入结构数组。
第二次尝试使用 if (sscanf(line, "%ff", &data[i].x) == NULL) { // ...some alert and assign 1.500}
检查 sscanf
是否成功,但也没有成功。第三次尝试,如下所示:
#include "stdio.h"
int main() {
typedef struct {
float x, y, vx, vy, mass;
}DATA;
FILE *file = fopen("null_detector.txt", "r");
if (file == NULL)
{
printf(stderr, "ERROR: file not opened.\n");
return EXIT_FAILURE;
}
int N= 3;
DATA* data = malloc(Nbodies * sizeof * data); // Array allocation
char line[256];
int i;
int inc = 1;
for (i = 0; i < Nbodies; i += inc)
{
fgets(line, sizeof(line), file);
// **Some info:
// Scan 5 float variables per line (this part works fine)
sscanf(line, "%ff, %ff, %ff, %ff, %ff",
&data[i].x, &data[i].y, &data[i].vx, &data[i].vy, &data[i].mass); // %ff accounts for 'f' suffix
// Now check if any of above vars are empty/NULL.
// NOTE: aware that these vars CANNOT be compared to NULL,
// but has been included to try and provide clarity for end goal
if (data[i].x == NULL)
{
//.. assign 1.500 to data[i].x
}
if (data[i].y == NULL)
{
//... same as above etc
}
// ...Repeat IF statements for all 5 vars
}
//Print the contents of array of structs to check for correct output
for (i = 0; i < Nbodies; i++)
{
printf("%.3f %.3f %.3f %.3f %.3f\n", data[i].x, data[i].y, data[i].vx, data[i].vy, data[i].mass);
}
return 0;
}
总结:
有谁知道如何将这个程序修改为:
- 在使用
fgets
读取文件的每一行时检测缺失的浮点值
- 用浮点值替换缺失的浮点值
1.500
- 将这些值写入结构数组,就像成功的非缺失值一样?
- 如代码中所述,我知道 struct float 变量无法与
NULL
进行比较。我将此比较包含在代码中只是为了让最终目标更加清晰。
您可以使用 strsep
分隔每一行。
str = strsep(&line, ",")
使用一个函数设置数据的值:
void set_data(DATA *dt, int count, float f) {
switch(count) {
case 0: dt->x = f; break;
case 1: dt->y = f; break;
case 2: dt->vx = f; break;
case 3: dt->vy = f; break;
case 4: dt->mass = f; break;
}
}
完整代码:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
float x, y, vx, vy, mass;
}DATA;
void set_data(DATA *dt, int count, float f) {
switch(count) {
case 0: dt->x = f; break;
case 1: dt->y = f; break;
case 2: dt->vx = f; break;
case 3: dt->vy = f; break;
case 4: dt->mass = f; break;
}
}
int main() {
FILE *file = fopen("text.txt", "r");
if (file == NULL)
{
printf( "ERROR: file not opened.\n");
return EXIT_FAILURE;
}
int N= 3;
DATA* data = malloc(N * sizeof(data)); // Array allocation
char *line;
int i;
int inc = 1;
size_t n = 0;
for (i = 0; i < N; i += inc)
{
getline(&line, &n, file);
int count = 0;
char *str;
while((str = strsep(&line, ",")) != NULL) {
if (strcmp(str, " ") == 0) {
set_data(&data[i], count, 1.5);
} else {
set_data(&data[i], count, atof(str));
}
// printf("count = %d\n", count);
// printf("token: %s\n", str);
count++;
}
}
//Print the contents of array of structs to check for correct output
for (i = 0; i < N; i++)
{
printf("%.3f %.3f %.3f %.3f %.3f\n", data[i].x, data[i].y, data[i].vx, data[i].vy, data[i].mass);
}
return 0;
}
输入:
#cat text.txt
0.123f, 0.234f, 0.345f, 0.456f, 0.567f
1.987f, , 7.376f, 2.356f, 5.122f
9.111f, 1.234f, 7.091f, 6.672f, 9.887
输出:
0.123 0.234 0.345 0.456 0.567
1.987 1.500 7.376 2.356 5.122
9.111 1.234 7.091 6.672 9.887
当没有输入值时,如果逗号之间至少有一个space,也可以只用sscanf
实现。
#include <stdio.h>
int main(void) {
char *str[] = {"0.123f, 0.234f, 0.345f, 0.456f, 0.567f",
"1.987f, , 7.376f, 2.356f, 5.122f",
"9.111f, 1.234f, 7.091f, 6.672f, 9.887f"};
float float_arr[3][5];
char temp[5][7];
for (unsigned i = 0; i < 3; i++) {
if (5 != sscanf(str[i], "%6[^,],%6[^,],%6[^,],%6[^,],%6[^,]",
temp[0], temp[1], temp[2], temp[3], temp[4]))
return printf("Error\n"), 1;
for (unsigned j = 0; j < 5; j++)
if (1 != sscanf(temp[j], "%ff", &float_arr[i][j]))
float_arr[i][j] = 1.500f;
}
// printing the result
for (unsigned i = 0; i < 3; i++) {
for (unsigned j = 0; j < 5; j++)
printf("%ff ", float_arr[i][j]);
printf("\n");
}
return 0;
}
输出
0.123000f 0.234000f 0.345000f 0.456000f 0.567000f
1.987000f 1.500000f 7.376000f 2.356000f 5.122000f
9.111000f 1.234000f 7.091000f 6.672000f 9.887000f