使用结构在C中输入CSV文件

时间:2014-11-02 02:24:57

标签: c csv

我想逐行打印来自.csv文件的数据,该数据由comma分隔符分隔。
此代码打印垃圾值。

enum gender{ M, F };

struct student{
     int stud_no;
     enum gender stud_gen;
     char stud_name[100];
     int stud_marks;
};

void main()
{
   struct student s[60];
   int i=0,j,roll_no,marks,k,select;
   FILE *input;
   FILE *output;

   struct student temp;


    input=fopen("Internal test 1 Marks MCA SEM 1 oct 2014 - CS 101.csv","r");
    output=fopen("out.txt","a");

    if (input == NULL) {
        printf("Error opening file...!!!");

    }

  while(fscanf(input,"%d,%c,%100[^,],%d", &s[i].stud_no,&s[i].stud_gen,&s[i].stud_name,&s[i].stud_marks)!=EOF)
  {

    printf("\n%d,%c,%s,%d", s[i].stud_no,s[i].stud_gen,s[i].stud_name,s[i].stud_marks);
    i++;
  }

}

我还尝试了以下代码:Read .CSV file in C但它只打印n字段。我想逐行显示所有字段。

这是我的示例输入。
1401,F,FERNANDES SUZANNA ,13 1402,M,PARSEKAR VIPUL VILAS,14 1403,M,SEQUEIRA CLAYTON DIOGO,8 1404,M,FERNANDES GLENN ,17 1405,F,CHANDRAVARKAR TANUSHREE ROHIT,15

1 个答案:

答案 0 :(得分:2)

虽然有很多方法可以将任何行解析为组件,但可以真正增加理解的一种方法是使用startend指针来处理标识{{1用commas替换它们,读取字段,恢复逗号并移动到下一个字段。这只是null-terminators (i.e. '\0' or just 0)的手动应用程序。以下示例执行此操作,以便您可以查看正在进行的操作。当然,您可以将strtokstart指针(分别为end)替换为sp & p

阅读代码,如果您有任何疑问,请与我们联系:

strtok

<强>输入

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

/* maximum number of student to initially allocate */
#define MAXS 256

enum gender { M, F };

typedef struct {                /* create typedef to struct         */
    int stud_no;
    enum gender stud_gen;
    char *stud_name;
    int stud_marks;
} student;

int main (int argc, char *argv[]) {

    if (argc < 2) {
        printf ("filename.csv please...\n");
        return 1;
    }

    char *line = NULL;          /* pointer to use with getline ()   */
    ssize_t read = 0;           /* characters read by getline ()    */
    size_t n = 0;               /* number of bytes to allocate      */
    student **students = NULL;  /* ptr to array of stuct student    */
    char *sp = NULL;            /* start pointer for parsing line   */
    char *p = NULL;             /* end pointer to use parsing line  */
    int field = 0;              /* counter for field in line         */
    int cnt = 0;                /* counter for number allocated     */
    int it = 0;                 /* simple iterator variable         */

    FILE *fp;
    fp = fopen (argv[1], "r");  /* open file , read only            */
    if (!fp) {
        fprintf (stderr, "failed to open file for reading\n");
        return 1;
    }

    students = calloc (MAXS, sizeof (*students)); /* allocate 256 ptrs set to NULL */

    while ((read = getline (&line, &n, fp)) != -1) {    /* read each line in input file */

        sp = p = line;      /* set start ptr and ptr to beginning of line */
        field = 0;          /* set/reset field to 0 */

        students[cnt] = malloc (sizeof (**students));   /* alloc each stuct with malloc */

        while (*p)          /* for each character in line   */
        {
            if (*p == ',')  /* if ',' end of field found    */
            {
                *p = 0;     /* set as null-term char (temp) */

                if (field == 0) students[cnt]->stud_no    = atoi (sp);
                if (field == 1) {
                    if (*sp == 'M') {
                        students[cnt]->stud_gen   = 0;
                    } else {
                        students[cnt]->stud_gen   = 1;
                    }
                }
                if (field == 2) students[cnt]->stud_name  = strdup (sp);    /* strdup allocates for you */

                *p = ',';   /* replace with original ','    */
                sp = p + 1; /* set new start ptr start pos  */
                field++;    /* update field count           */
            }
            p++;            /* increment pointer p          */
        }
        students[cnt]->stud_marks = atoi (sp);    /* read stud_marks (sp alread set to begin) */

        cnt++;              /* increment students count     */
    }

    fclose (fp);            /* close file stream            */

    if (line)               /* free memory allocated by getline     */
        free (line);

    /* iterate over all students and print  */
    printf ("\nThe students in the class are:\n\n");
    while (students[it])
    {
        printf ("  %d   %c   %-30s   %d\n",
                students[it]->stud_no, (students[it]->stud_gen) ? 'F' : 'M', students[it]->stud_name, students[it]->stud_marks);
        it++;
    }
    printf ("\n");

    /* free memory allocated to struct */
    it = 0;
    while (students[it])
    {
        if (students[it]->stud_name)
            free (students[it]->stud_name);
        free (students[it]);
        it++;
    }
    if (students)
        free (students);

    return 0;
}

<强>输出:

$ cat dat/people.dat
1401,F,FERNANDES SUZANNA ,13
1402,M,PARSEKAR VIPUL VILAS,14
1403,M,SEQUEIRA CLAYTON DIOGO,8
1404,M,FERNANDES GLENN ,17
1405,F,CHANDRAVARKAR TANUSHREE ROHIT,15

valgrind memcheck:

我稍微更新了代码,以确保释放所有已分配的内存以防止任何内存泄漏。简单的事情,如$./bin/stud_struct dat/people.dat The students in the class are: 1401 F FERNANDES SUZANNA 13 1402 M PARSEKAR VIPUL VILAS 14 1403 M SEQUEIRA CLAYTON DIOGO 8 1404 M FERNANDES GLENN 17 1405 F CHANDRAVARKAR TANUSHREE ROHIT 15 line自动分配内存或未能关闭文件流可能导致内存泄漏。以下是getline memcheck确认。

valgrind