c - FIFO收货号码(C码)

标签 c pipe fifo

所以我有一个 FIFO 文件,是我在终端中使用 mkfifo() 函数创建的,我正在发送数据:echo"12.5 123 5 -2.1"> rndfifo

我的程序需要读取这些数字并将它们放入一个数组中,以便我以后可以使用它们。我目前只成功地创建了一个程序来读取这些数字并将它们放在一个字符数组中,但我卡住了,不知道如何继续,所以有什么帮助吗?

代码:
MSG_LEN 定义为 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;
}

我写的分隔数字的解决方案(感谢Chintan)
(如果有更好的请写出来)

另外,如果管道发送的是其他内容然后是数字,我该怎么做才能停止程序?

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," ");
}

最佳答案

读取 FIFO 消息并将内容放入 char 数组后,获取该 char 数组并从中解析数字,或者如果有其他东西而不是数字则停止程序。 要从 char 数组中读取数字,请使用 double strtod(const char *nptr, char **endptr) 要了解如何找出 char 数组中是否存在无效字符,请阅读第一个示例,然后引用第二个(长)示例中的注释。

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

从 FIFO 消息中的数字获取平均值的更长示例。 如果您需要将这些数字放在数组中,方法如下(如果您需要取平均值,您甚至不需要将它们放在数组中 :) )

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

最后,printArrayCHECKERR 实现:

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

关于c - FIFO收货号码(C码),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41046396/

相关文章:

c - LTE 到 Wi-Fi 切换

c - C中的多级管道

c++ - C++中使用管道实现父子进程通信

angular - ionic 3 : The pipe '' could not be found

c - 替代轮询功能以检查 FIFO 中的新数据

sql-server - Sql Server BULK INSERT 可以从命名管道/fifo 读取吗?

c++ - Qt Creator gdb 显示 C 数组元素

c - 在 ATtiny85 上设置高速 PWM

c - 我想用管道和信号制作一个 REPL 风格的程序,但是我的程序锁定了

c - 如何处理用户输入错误