使用open、read、write处理表格数据

 一、需求

  • 在下面的excel表格中,计算每一个人的总分及评价。当总分大于270时评价为A,当总分位于[240,270]之间时评价为B,当总分低于240分时评价为C。
  • 表格名为score.csv(保存为csv是为了将内容以逗号隔开)
语文数学英语总分评价
张三909192
李四808182
王五707172

 二、解决方案

1.命令行输入指令:./xxxx  score.csv  result.csv。其中xxxx为可执行文件,score.csv作为原数据文件,result.csv作为处理后的输出文件。当result.csv不存在时则创建,存在时截断以防数据覆盖不全。
2.逐行读取,每读取一行原数据文件内容就存入缓冲区数组中,再进行处理,处理后存入输出文件中。

3.read_line为读取一行的函数,逐个读取1个字符,若遇到'\r'或'\n'则说明该行结束。

4.采用sscanf函数在指定格式中提取关键数据,%[^,] 可从当前字符串位置开始读取所有不是逗号的字符,直到遇到逗号或字符串的结尾。

5.使用sprintf可以将格式化数据写入一个字符串中。

 三、代码实现

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

/*返回值:
*-1:表示错吴或者读到尾部
*i:表示读到的数据个数
*/
int read_line(int fd, unsigned char *buf)
{
    int len = 0;
    unsigned char c;
    int i = 0;
    int wei = 0;//尾部判断

    while (1)
    {
        len = read(fd, &c, 1);
        if (len < 0)
        {
            perror("read_line");
            return -1;
        }
        else if (len == 0) // 尾部或者回车后的换行,换行读取的数据是0
        {
            wei = -1;
            break;
        }
        else
        {
            if (c != '\n' && c != '\r')
            {
                buf[i] = c;
                i++;
                wei  = 0;
            }
            else
            {
                wei = 0;
                break; // 行末跳出
            }
        }
    }
    buf[i] = '\0';
    if(wei == -1 && i== 0)
        return -1;
    else
        return i;
}

void process_data(unsigned char *data_buf, unsigned char *result_buf)
{
    if (data_buf[0] == 0xef) /* 对于UTF-8编码的文件,它的前3个字符是0xef 0xbb 0xbf */
    {
        strcpy(result_buf, data_buf);
        strcat(result_buf,"\r\n"); //在尾部加入回车换行
    }
    else
    {
        char name[100];
        int score[3];
        int sum = 0;
        int level;
        char *levels[] = {"A", "B", "C"};
        sscanf(data_buf, "%[^,],%d,%d,%d", name, &score[0], &score[1], &score[2]);
        //printf("result: %s --->get name---> %s\n\r", data_buf, name);
        sum = score[0] + score[1] + score[2];
        if (sum > 270)
        {
            level = 0;
        }
        else if ( sum >= 240 && sum <=270)
        {
            level = 1;
        }
        else
            level = 2;
        sprintf(result_buf,"%s,%d,%d,%d,%d,%s\r\n",name, score[0], score[1], score[2],sum,levels[level]);
        
    }
    //printf("%s",result_buf);
}

/* argc=3
 * argv[0]=./process_excel
 * argv[1]=data.csv
 * argv[2]=result.csv
*/
int main(int argc, char **argv)
{
    int fd_data;
    int fd_result;
    unsigned char data_buf[1000];
    unsigned char result_buf[1000];
    if (argc != 3)
    {
        printf("Usage: %s <data_csv> <result_csv> \n", argv[0]);
        return -1;
    }

    // 打开原始文件
    fd_data = open(argv[1], O_RDONLY);
    if (fd_data < 0)
    {
        perror("open");
        return -1;
    }
    else
    {
        printf("fd = %d\n", fd_data);
    }

    // 创建结果文件
    fd_result = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR,0664);
    if (fd_result < 0)
    {
        perror("creat");
        return -1;
    }
    else
    {
        printf("fd = %d\n", fd_result);
    }

    int len;
    while (1)
    {
        len = read_line(fd_data, data_buf);
        if (len == -1)
            break;
        if (len != 0) //读到回车换行,len=0,result_buf还是上一次的内容
        {
            //printf("%s\n", data_buf);
            process_data(data_buf, result_buf);
            write(fd_result, result_buf, strlen(result_buf));
        }
    }
    close(fd_data);
    close(fd_result);
}

四、%[^,]

#include <stdio.h>

char data_buf[] = ",Alice,lina,85,90,78";
char name1[50], name2[50];
int score[3];

int main() {
    // 使用 sscanf 解析数据
    sscanf(data_buf, ",%[^,],%[^,],%d,%d,%d", name1, name2, &score[0], &score[1], &score[2]);

    // 输出结果
    printf("%s,%s,%d,%d,%d\n", name1, name2, score[0], score[1], score[2]);

    return 0;
}

// 此时,name1 的值为 "Alice"
// name2 的值为 "lina"
// score[0] 的值为 85
// score[1] 的值为 90
// score[2] 的值为 78

//输出:Alice,lina,85,90,78

五、read_line函数

写法一:

因为行末\r\n,读到\n再退出,\r也写入buf

int read_line(int fd, char *buf)
{
    int len = 0;
    char c;
    int i = 0;
    while(1)
    {
        len = read(fd, &c, 1);
        if(len <= 0)
            return -1;
        else
        {
            if(c != '\n')
            {
                buf[i] = c;
                i++;
            }
            else
            {
                break;
            }
        }
    }
    buf[i] = '\0';
    return i;
}

 写法二:

读到\r,用lseek函数跳过\n字符

int read_line(int fd, char *buf)
{
    int len = 0;
    char c;
    int i = 0;
    while(1)
    {
        len = read(fd, &c, 1);
        if(len <= 0)
            return -1;
        else
        {
            if(c != '\r' )
            {
                buf[i] = c;
                i++;
            }
            else
            {
                lseek(fd, 1, SEEK_CUR); 
                break;
            }
        }
    }
    buf[i] = '\0';
    return i;
}

 写法三:

考虑是unix还是windows系统

\r就是"回到行首",\n就是"到下一行"

即:\r回车使光标到行首,\n换行使光标下移一格

通常用的Enter是两个加起来的,即\r\n

  • Unix系统里,每行结尾只有“<换行>”,即“\n”;
  • Windows系统里面,每行结尾是“<换行><回车>”,即“\n\r”;
  • Mac系统里,每行结尾是“<回车>”。
printf aaaa \r\n bbbbbb
print ccccc \n ddddddd
print eeeeeeeee \r ffffff

运行结果

aaaa
bbbbbb
ccccc
ddddddd
ffffff

 \r 就是return 回到本行行首,这就会把这一之前的输出覆盖掉,因此ffffff会覆盖eeeeeeeee
\n 是换行+回车,把光标先移到下一行,然后光标回到下一行的行首

代码具体实现 :

int read_line(int fd, char *buf)
{
    int len = 0;
    char c;
    int i = 0;
    while (1)
    {
        len = read(fd, &c, 1);
        if (len <= 0)
            return -1;
        else
        {
            if (c == '\r')
            {
                // 读取到 '\r',检查下一个字符是否是 '\n'
                len = read(fd, &c, 1);
                if (len > 0 && c != '\n')
                {
                    lseek(fd, -1, SEEK_CUR); // 如果不是 '\n',回退一个字节
                }
                break; // 行结束
            }
            else if (c == '\n')
            {
                // 读取到 '\n',行结束
                break;
            }
            buf[i] = c;
            i++;
        }
    }
    buf[i] = '\0';
    return i;
}

这个逻辑确保了无论是 Windows 风格的换行符(\r\n)还是 Unix 风格的换行符(\n),都能被正确处理。

### 回答1: 在LabVIEW中,可以通过各种方法将数据保存到Excel表格中。这里我将介绍一种常用的方法。 首先,你需要在你的LabVIEW程序中安装Excel文件操作库,该库支持将数据写入到Excel表格中。你可以在NI官方网站上下载并安装nidevfile库以支持Excel文件操作。 然后,在你的LabVIEW程序中,你需要创建一个Excel表格对象,并打开要保存数据的Excel文件。你可以使用"Open/Create/Replace File"函数来打开或创建Excel文件,该函数将返回一个Excel表格对象的引用。 接下来,你可以使用"Property Node"来创建数据表并设置要保存的数据。你可以使用"Property Node"来设置表格的行数、列数以及每个单元格中的数据。你可以使用"Set Table Array"函数来设置整个表格数据。 最后,你需要使用"Close File"函数来关闭并保存Excel文件。这个函数将确保数据被保存到Excel文件中。 需要注意的是,使用LabVIEW将数据保存到Excel文件时,你需要确保Excel文件没有在其他程序中打开,否则会导致操作失败。以及在每次写入数据之前,你需要检查是否已经连接到Excel表格对象,以确保成功写入数据。 总结起来,通过安装Excel文件操作库,创建Excel表格对象,设置数据并保存文件,你就可以将数据保存到Excel表格中。这种方法在实际应用中非常常见,可以方便地将LabVIEW中采集的数据保存并进一步进行分析和处理。 ### 回答2: LabVIEW可以通过使用LabVIEW中的数据存储和检索工具包,将数据保存到Excel表格中。下面是一个简单的步骤指南: 1. 打开LabVIEW,创建一个新的VI。 2. 在Block Diagram中,右键单击空白区域,选择"Functions" -> "File I/O" -> "Spreadsheet" -> "Write to Spreadsheet File"。 3. 将"Write to Spreadsheet File"拖动到Block Diagram上,并与其他模块连接。 4. 右键单击"Write to Spreadsheet File"模块,选择"Create Constant"。 5. 选择要保存数据的Excel文件路径,可以使用绝对或相对路径。 6. 选择要写入的工作表名称,或者创建一个新的工作表。 7. 创建要保存的数据 - 可以是数组、矩阵、表格或其他数据类型。 8. 将要保存的数据连接到"Write to Spreadsheet File"模块的输入端,将Excel工作表的数据类型设置为正确的类型。 9. 运行VI,数据将被保存到Excel表格中。 10. 如果需要在LabVIEW中读取Excel数据,可以使用"Read from Spreadsheet File"模块来实现。 注意事项: - 确保安装了LabVIEW数据存储和检索工具包,并将其添加到您的LabVIEW开发环境中。 - 在将数据写入Excel表格之前,确保关闭任何已打开的相关Excel文件。 - 要避免因读取或写入文件权限不足而出现权限问题,请以管理员身份运行LabVIEW。 ### 回答3: LabVIEW是一款用于数据采集、信号处理和自动化控制的软件,它具有强大的数据处理和可视化功能。 要将数据保存到Excel表格中,需要使用LabVIEW的Excel插件,该插件提供了一系列的函数和工具,用于将数据导出到Excel表格中。下面是一个简单的步骤来保存数据到Excel表格: 1. 首先,需要在LabVIEW中安装Excel插件。可以通过NI Package Manager来安装这个插件。 2. 在程序中创建一个Excel文件,可以使用“Create Excel Workbook”函数来创建一个空的Excel文件。 3. 然后,使用“Create Worksheet”函数在Excel文件中创建一个工作表。 4. 创建一个用来保存数据的数组,可以将需要保存的数据放入这个数组中。 5. 使用Write To Measurement File”函数来将数据写入到Excel文件的工作表中。在函数的输入参数中,选择Excel文件路径和名称,选取要保存数据的工作表,将待保存的数据输入到函数的输入端。 6. 最后,使用“Close Measurement File”函数来关闭Excel文件。 通过以上步骤,就可以将数据保存到Excel表格中。除了这种简单的方法之外,LabVIEW还提供了更多高级的功能,可以自动化地进行数据的保存和处理,例如选择特定的行、列,设置格式,编辑单元格等等。 总的来说,LabVIEW是一种非常强大的工具,可以方便地将数据保存到Excel表格中,并且还可以进行更多复杂的数据处理操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值