Checking for null/empty float values when using sscanf

p.luck

The following program attempts to read an input file line by line using fgets, and save each comma delimited float value into an array of structs using sscanf (this aspect of the code works fine). The issue lies in that the program should also detect when a float value is missing/empty, and assign it the float value 1.500 which then is saved into the array of structs.

EDIT: This is supposed to be compiled using VS2017, so on Windows.

*Note: Please note that the following questions have been studied before posting this question:

How to check if a string returned by scanf is null

How to get scanf to continue with empty scanset

An example of the input file (missing value in the second row):

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

Desired output (missing value in second row is detected and set to 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

So far, the first attempt tried to scan all 5 floats (each with 'f' suffix) into strings and then check to see if those strings are null/empty or of zero length using strcmp and strlen, respectively, and finally involved trying to use sscanf again on each of those variables to read each into an array of structs.

The 2nd attempt included a check to see if the sscanf was successful by using if (sscanf(line, "%ff", &data[i].x) == NULL) { // ...some alert and assign 1.500}, which did not work either. The 3rd attempt, as seen below:

#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;
}

Summary:

Does anyone know how this program can be modified to:

  • detect missing float values in each line of the file upon reading them with fgets
  • replace missing float values with the float value 1.500
  • write these values to the array of structs, like the non-missing values successfully are doing?
  • As commented in the code, I am aware that the struct float variables cannot be compared to NULL. I have included this comparison in the code to only try to add some clarity as to what the end goal is.
Hitokiri

You can use strsep to separate each line.

str = strsep(&line, ",")

Using one function to set the value of 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;
    }
}

The complete code:


#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;
}

The input:

#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

The output:

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

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Checking whitespace length using sscanf

Issue when using sscanf

Parsing Integer and Float Values of a Text File with sscanf

Segmentation Fault when using sscanf

How to seperate integer values using sscanf in c?

How to match second time when using sscanf

Checking if input == Integer/float? using irb

Using += operator with float values

C# accuracy when checking float in List<float> with Contains method

Read expression using fgets and get the numeric values using sscanf

length() of two vectors give different values, but when checking using a for loop, the vectors have the same length

Reading multiple values from formatted string using sscanf

Extract values from text strings using Matlab's sscanf

How to stop ConcurrentModificationException when checking values of JSONobject

Avoiding database when checking for existing values

Exclude certain values when checking for a condition with pandas

Problem checking SQL values with WHEN statement

Excluding 'None' when checking for 'NaN' values in pandas

Type checking json values when unmarshaling in Go

Checking unique values in array using LinkedHashSet in java

Using COUNTIFS with checking string and comparing values

checking if values are existed or new using pandas

checking all values if empty or filled using jquery

Efficiency when using an arraylist of enum for condition checking

The cost of checking the connection when using JdbcPooledConnectionSource

Checking if variable type is nil when using interface

Type Checking failed when using Dependent Pair

Keras 'Error when checking input' when trying to predict multiple values

Error when passing list of float values to function