FIFO receiving numbers (C code)

1.4k Views Asked by At

So I have a FIFO file that I made with mkfifo() function in terminal and I'm sending data with : echo"12.5 123 5 -2.1" > rndfifo

My program needs to read those numbers and put them in a array so that I can use them later . I currently only succeeded in creating a program that reads those numbers and placing them in a char array, but I got stuck and have no clue how to continue so any help?

Code:
MSG_LEN defined at 16

int main(int argc, char **argv) {
if(2 != argc)
   exit(EXIT_FAILURE); 

int fd = open(argv[1], O_RDONLY);
if(-1 == fd);
   exit(EXIT_FAILURE);

do {
    char buf[MSG_LEN];
    int bytesRead;

    if(-1 == (bytesRead = read(fd, buf,MSG_LEN))){
       perror("Reading from PIPE failed");
       exit(exit_failure);
    }
    if (0 == bytesRead)
        break;

    printf("Read number: %d\n", atoi(buf));
} while (true);

close(fd);
return 0;
}

The solution for separating numbers that I wrote (Thanks Chintan)
(if there are any better ones please write them)

Also what can i do to stop the program if a pipe sends something else then a number?

char *deo;
float tmp;
deo = strtok(buf," ");
while(deo != NULL){
    sscanf(deo,"%f",&tmp);
    //tmp one number from buf(sent from FIFO)
    deo = strtok(NULL," ");
}
1

There are 1 best solutions below

0
On

After you have read the FIFO message, and placed the content in char array, take that char array and parse numbers from it, or stop the program if there is something else then a number. For reading numbers from char array use double strtod(const char *nptr, char **endptr) To see how to find out if there was some invalid character in char array read the first example and then refer to NOTE in the second (long) example.

Try the following short example with different strings:

char buffer[128] = "12.5 123 5 -2.1 text text 0.0 -15";

char buffer[128] = "text";

char buffer[128] = "1 2 39 3.45 0 17.3 0 10e2 78.33";

char buffer[128] = "12.5  123 5 -2.1";
char *beginPtr = buffer;
char *endPtr = NULL;
double current = 0;

while(true) 
{
    // After strtod call, if parsing was successful, 
    // endPtr will point to the first character after 
    // parsed number.
    // If no number is parsed, endPtr will not change.
    current = strtod(beginPtr, &endPtr);
    
    // If endPtr is unchanged from last iteration,
    // strtod encountered some non-float character
    // EOF for example
    if(beginPtr == endPtr) {
        break;
    }

    // Moving beginPtr
    beginPtr = endPtr;
    printf("%lf\n", current);
}

Longer example with getting average value from numbers in FIFO message. If you need to put those numbers in array, here is how (if you need to take the average, you don't even need to put them in array :) )

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define MAX_LEN (256)
// cond should be TRUE if there is no error
void CHECKERR(bool cond, char* msg);
void printArray(double *array, int n);

int main(int argc, char** argv)
{
    // For errno 22, perror will print 'Invalid argument'
    errno = 22;
    CHECKERR(2 == argc, "Usage: ./2 pathToFifoFile\n");
    errno = 0;

    int fileDesc = 0;
    char buffer[MAX_LEN];
    char *beginPtr = NULL;
    char *endPtr = NULL;

    double *array = NULL;        
    double current = 0.0;
    double sum = 0.0;
    double avg = 0.0;
    int count = 0;
    
    fileDesc = open(argv[1], O_RDONLY);
    CHECKERR(-1 != fileDesc, "Failed to open file.\n");    
    CHECKERR(-1 != read(fileDesc, buffer, sizeof buffer), "Failed to read file.\n");

    beginPtr = buffer;
    while(true) 
    {   
        // Move the endPtr if parsing was successful
        current = strtod(beginPtr, &endPtr);

        // NOTE: echo "12.5  123 5 -2.1" > /tmp/rndfifo
        // will put '\n' at the end of the string.
        // If you have regular string, change the *endPtr != '\0'
        if(beginPtr == endPtr && *endPtr != '\n')
        {
            printf("Further characters after float: %s\n", endPtr);
            errno = 22;            
            CHECKERR(false, "FIFO contains non-float characters");
        }
    
        if(beginPtr == endPtr) {
            break;
        }
        // Moving beginPtr
        beginPtr = endPtr;
    
        sum += current;
        count++;        
    }

    // Print out average
    avg = sum / count;
    printf("Average: %.2lf\n", avg);

    // At this point we know how much numbers are stored in buffer
    array = (double*)malloc(count * sizeof(double));
    CHECKERR(NULL != array, "malloc() failed.\n");
     
    // Go trough buffer again to put numbers in array
    beginPtr = buffer;
    int i;
    for(i = 0; i < count; i++) 
    {
        current = strtod(beginPtr, &endPtr);
        beginPtr = endPtr;
        array[i] = current;
    }

    close(fileDesc);
    printArray(array, count);
    free(array);

    return 0;
}

And at last, printArray and CHECKERR implementations:

void printArray(double *array, int n)
{
    int i;
    for(i = 0; i < n; i++) {
        printf("%.2lf ", array[i]);
    }
    putchar('\n');
}


void CHECKERR(bool cond, char* msg)
{
    if(!cond) 
    {
        perror(msg);
        exit(EXIT_FAILURE);
    }
}