c - 在c中将文本文件读入字符数组

标签 c arrays csv char text-files

我正在编写一个程序,该程序使用命令行参数从用户接收文本文件的名称。文本文件是一个非常简单的 CSV 文件,例如:

Bob's experiment,12,14,15,16
Mary's experiment,16,15,18

我只是希望它打印实验名称,然后打印所有数值的平均值。我试图通过将所有数字和逗号放入一个字符数组中来做到这一点,但我不知道哪里出了问题。

这就是我所拥有的:

int main(int argc, char *argv[])
  {
    if(argc == 2) {
            FILE *txt_file;
            txt_file=fopen(argv[1], "rt");
            char str[4096];

            if(!txt_file) {
                    printf("File does not exist.\n");
                    return 1;
            }

            while(!feof(txt_file)){
                    char s;
                    s = fgetc(txt_file);

                    //prints experiment name
                    if(s != ',' && (!isdigit(s))) {
                            printf("%c", s);
                    }

                    if(isdigit(s) || s == ',') {
                            fgets(str, 4096, txt_file);
                    }
               }
             fclose(txt_file);
             return 0;
         }

最佳答案

有多种方法可以做到这一点,但您应该根据从文件中读取的数据类型来定制输入例程。这里您正在读取数据,因此您应该关注面向行输入例程(fgetsgetline ,或硬塞的 scanf)。基本方法是将文件中的一行输入读取到缓冲区中,然后根据需要解析该行。您可以动态分配所需的所有存储空间,也可以定义一个足以处理数据的最大值。

接下来,您需要解析从文件中读取的缓冲区,以获取实验名称以及关联的每个,以便可以计算平均值。同样,有很多方法可以做到这一点,但 strtol 是为此目的量身定制的。它需要一个指向要转换的字符串的指针,并返回一个指向下一个非数字字符的endptr。这允许您读取值并设置pointer = endptr+1,这将设置您读取下一个数字。

我在下面的示例中将这些部分组合在一起。对其进行评论是为了帮助您跟进。如果您还有任何其他问题,请发表评论:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXEXPS 256

int main (int argc, char* argv[])
{
    if (argc < 2) {
        fprintf (stderr, "error: insufficient input. Usage %s <filename>\n", argv[0]);
        return 1;
    }

    char *line = NULL;              /* line read from file (getline allocates if NULL)  */
    size_t n = 0;                   /* number of characters to read (0 - no limit)      */
    ssize_t nchr = 0;               /* number of characters actually read by getline    */
    char *p = NULL;                 /* pointer to use parsing values from line          */
    char *lnp = NULL;               /* second pointer to use parsing values from line   */
    char *expname[MAXEXPS] = {0};   /* array of MAXEXPS pointers for experiment names   */
    int expavg[MAXEXPS] = {0};      /* array of MAXEXPS ints to hold averages           */
    int val = 0;                    /* val returned by each call to strtol              */
    int eidx = 0;                   /* experiment index                                 */
    int idx = 0;                    /* value index                                      */

    FILE *txt_file = fopen(argv[1], "r");
    if (!txt_file) {
        fprintf (stderr, "error: unable to open file '%s'\n", argv[1]);
        return 1;
    }

    while ((nchr = getline (&line, &n, txt_file)) != -1)    /* read each line in file   */
    {
        p = strchr (line, ',');                             /* find first ','           */
        *p = 0;                                             /* set it to null (zero)    */
        expname[eidx] = strdup (line);    /* copy exp name to array (strdup allocates)  */
        lnp = ++p;                                          /* set lnp to next char     */
        int sum = 0;                                        /* reset sum to 0           */
        idx = 0;                                            /* reset idx to 0           */
        while ((val = (int)strtol (lnp, &p, 10)) != 0 && lnp != p) /* read next number  */
        {
            sum += val;                                     /* add val to sum           */
            lnp = ++p;                                      /* set lnp to next char     */
            idx++;                                          /* inc idx                  */ 
        }
        expavg[eidx++] = (idx > 0) ? sum / idx : 0;         /* calc avg for experiment  */
    }

    fclose (txt_file);

    /* print the averages of experiments */
    n = 0;
    printf ("\n  Experiment          Avg\n");
    printf ("  -----------------------\n");
    while (expname[n])
    {
        printf ("  %-18s  %d\n", expname[n], expavg[n]);
        n++;
    }
    printf ("\n");

    /* free all allocated memory        */
    n = 0;
    if (line)
        free (line);
    while (expname[n])
        free (expname[n++]);

    return 0;
}

输出:

$ ./bin/csvavgfixed dat/csvavg.dat

  Experiment          Avg
  -----------------------
  Bob's experiment    14
  Mary's experiment   16

内存分配/空闲摘要:

==22148== HEAP SUMMARY:
==22148==     in use at exit: 0 bytes in 0 blocks
==22148==   total heap usage: 4 allocs, 4 frees, 723 bytes allocated
==22148==
==22148== All heap blocks were freed -- no leaks are possible
==22148==
==22148== For counts of detected and suppressed errors, rerun with: -v
==22148== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

关于c - 在c中将文本文件读入字符数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26897673/

相关文章:

c - 将 int 打印为 float 时 printf 的行为是什么?

c - gwan是如何实现异步 Action 的?

javascript - 在 AngularJS 中只返回数组的键

postgresql - 从 CSV 导入到 PostgreSQL 数据库时,我能否将 Unix 时间戳自动转换为 TIMESTAMP 列?

python - 理解 python 中的 csv DictWriter 语法

c - 如何在这段代码中实现定时器中断来计算这个斐波那契函数的秒数?

JavaScript For 循环数组迭代问题 - 使用一个循环与两个循环

ios - 在 swift 中初始化一个具有数组作为属性的自定义对象

python - 从子目录中搜索 CSV 并将文件夹名称添加为一列

c - 播放 .wav C Mac