将数据从文件输入到数据结构中

时间:2014-12-09 21:45:19

标签: c file data-structures

我对使用C编程很新,我想要做的是将文件中的数据输入到数据结构中。我意识到我有一些错误,我无法弄明白。任何帮助将不胜感激。

我正在阅读的文本文件包含:

0001:0002:0003:0021:CLS  
0001:0010:0003:0021:CLS  
0001:0002:0002:0080:<HTML>  
0005:0002:0002:8080:<BR>  
0005:0012:0002:8080:<BR>  

 我的代码是:

int main() {  
banner(); //call on banner  
int exists(const char *filename);  
const char s[2] = ":";  
char filename[500];  
FILE * inputFile;  
FILE * outputFile;  
char *token;  
int n;  
struct Packet;  
Packet *P;  


printf("Input the file name: ");  
    scanf("%s",filename);  
    printf("\n");



    inputFile = fopen(filename, "r");    
    if (inputFile != NULL)    
    {  
        printf("This file exists");      
    }  
    else   
    {  
        printf("This file doesn't exist\n");    


while(P >=sizeof(Packet)){    
           P=(struct Packet*)calloc( 5, sizeof(Packet *) );  
            fscanf(inputFile,"%s %d %d %d", &P->S, &P->D, &P->T, &P->P, &P->D );  
            fprintf(inputFile,"%s %d %d %d %d\n", P->S, P->D, P->T, P->P, P->D);  
        }  


  while(!feof(inputFile)){
        {
            P=(Packet*)calloc( 5, sizeof(struct Packet *) );
            fscanf(inputFile,"%s %d %d %d", P->S, P->D, P->T, P->P, P->D );
            fprintf(inputFile,"%d %d %d %d %s\n", P->S, P->D, P->T, P->P, P->D);
        }
    }

2 个答案:

答案 0 :(得分:1)

您面临的最大挑战是为工作选择正确的工具。您还必须将结构声明与您拥有的数据相匹配。

虽然scanf是一个很好的工具,但当您要读取不同的输入行时,它不适合该作业。在您的数据中,您需要blank linesvarying number of fields每行阅读。而不是尝试 shoehorn 一系列测试和格式字符串,以便scanf可以工作,正确的方法是从文件中读取整行数据,然后解析该数据以获得需要的信息。

面向行的输入的正确工具是fgetsgetline。在这个例子中,我更喜欢getline,因为它返回它在每行中读取的实际字符数,允许对空/短行进行简单测试。

阅读完一行数据后,该作业的正确工具可以是strtokstrsep。您还可以使用简单的指针手动解析数据行。无论如何,您解析数据并将分离的值分配给结构。

我已将部分代码留在下面注释,以便您可以按照更改进行操作。一些简单的风格,其余的实现我上面描述的。请注意,有很多方法可以做到这一点。仔细看看,如果您有疑问,请告诉我。明确了解为什么需要在结构中声明数组:

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

#define MAXS 500

// typedef struct __Packet {
//     int Source[500];
//     int Destination[500];
//     int Type[500];
//     int Port[500];
//     char Data[60];
// } Packet;

typedef struct {    /* don't use initial 'C'aps - c isn't c++ or visual basic */
    int src;        /* obviously, you are free to do so, but it's ugly...     */
    int dest;
    int type;
    int port;
    char *data;
} packet;

int main () {

    // banner ();           //call on banner
    // int exists (const char *filename);
    // const char s[2] = ":";
    // char filename[500];
    // char *token;
    // int n;
    // struct Packet;
    // Packet *P;

    char *filename = NULL;
    FILE *iFile = NULL;
    // FILE *oFile = NULL;
    char *line = NULL;      /* NULL forces getline to allocate  */
    size_t n = 0;           /* max chars to read (0 - no limit  */
    ssize_t nchr = 0;       /* number of chars actually read    */
    size_t idx = 0;         /* packet array index               */
    char *p = NULL;         /* general pointer to parse line    */
    char *sp = NULL;        /* pointer to save start address    */
    int i = 0;              /* general iterator                 */

    /* allocate an array of pointers to struct */
    packet **pkt = calloc (MAXS, sizeof (*pkt));
    if (!pkt) {
        fprintf (stderr, "error: allocation failed (**pkt)\n");
        exit (EXIT_FAILURE);
    }

    printf ("\n Input the file name: ");
    scanf ("%m[^\n]%*c", &filename);        /* older scanf versions use 'a' instead of 'm' */
    printf ("\n");

    iFile = fopen (filename, "r");
    if (!iFile) {
        fprintf (stderr, "error: unable to open file '%s'\n", filename);
        exit (EXIT_FAILURE);
    }

    /* read each line in iFile  */
    while ((nchr = getline (&line, &n, iFile)) != -1)
    {
        if (nchr < 4)               /* if blank or short line, skip     */
            continue;

        if (line[nchr-1] == '\n')   /* strip newline from end           */
            line[--nchr] = 0;   

        sp = line;                  /* save start address for getline   */

        pkt[idx] = calloc (1, sizeof (**pkt));  /* allocate structure   */
        if (!pkt[idx]) {
            fprintf (stderr, "error: allocation failed (pkt[%zd])\n", idx);
            exit (EXIT_FAILURE);
        }

        /* parse line and fill struct */
        if ((pkt[idx]->src = atoi (strtok (line, ":"))))
        {
            pkt[idx]->dest = atoi (strtok (NULL, ":"));
            pkt[idx]->type = atoi (strtok (NULL, ":"));
            pkt[idx]->port = atoi (strtok (NULL, ":"));
            if ((p = strtok (NULL, ":")))
                pkt[idx]->data = strdup (p);
        }

        idx++;                      /* increment pkt array index        */
        line = sp;                  /* restore start address of line    */
    }

    if (line) free (line);          /* free buffer allocated by getline */
    if (iFile) fclose (iFile);      /* close file stream when done      */
    if (filename) free (filename);  /* free memory allocate by scanf    */

    /* print array (you can also use 'for (i=0; i<idx; i++)' to iterate)*/
    printf (" array of struct content:\n\n");
    while (pkt[i])
    {
        printf (" pkt[%d]    src: %4d    dest: %4d    type: %4d    port: %4d    data: %s\n",
                i, pkt[i]->src, pkt[i]->dest, pkt[i]->type, pkt[i]->port, pkt[i]->data);
        i++;
    }

    i = 0;                          /* reset iterator variable to zero  */
    while (pkt[i])                  /* free all memory allocated        */
    {
        if (pkt[i]->data) free (pkt[i]->data);
        free (pkt[i]);
        i++;
    }
    if (pkt) free (pkt);

    printf ("\n");                  /* make it pretty   */

    return 0;
}

<强>输入

$ cat dat/structrd.txt
0001:0002:0003:0021:CLS
0001:0010:0003:0021:CLS
0001:0002:0002:0080:
0005:0002:0002:8080:

0005:0012:0002:8080:

<强>输出:

$ ./bin/struct_rd_txt

 Input the file name: dat/structrd.txt

 array of struct content:

 pkt[0]    src:    1    dest:    2    type:    3    port:   21    data: CLS
 pkt[1]    src:    1    dest:   10    type:    3    port:   21    data: CLS
 pkt[2]    src:    1    dest:    2    type:    2    port:   80    data: (null)
 pkt[3]    src:    5    dest:    2    type:    2    port: 8080    data: (null)
 pkt[4]    src:    5    dest:   12    type:    2    port: 8080    data: (null)

注意:当您使用破坏原始缓冲区的函数(如getline)时,需要保存strtok分配的缓冲区的起始地址,以便{{ 1}}可以准确地跟踪它正在使用的内存。 (如果你没有getline

,就会发生不好的事情

版本使用:)

如果对于某些奇怪的阅读,您没有fgets可用,请使用getline。这是另一个合适的工具。然后放慢速度并阅读fgets以查看它是如何使用的。然后,您可以正确更新程序。这将包括以下更改:

man page

答案 1 :(得分:0)

我发现的一些错误是:

  • while(P >=sizeof(Packet))这项检查似乎毫无意义。请查看EOF常量以确定何时结束循环。
  • (struct Packet*)此处不要使用关键字struct,因为Packet已经是结构的typedef。
  • calloc(5, sizeof(Packet *))您不想分配指针的大小,而是分配实际结构的大小。
  • &P->Source, &P->Destination, ...您不必传递数组地址(&),因为数组本身指针。
  • fprintf(inputFile,"%s %d %d %d %d\n" %s说明符应该是最后一个,因为第一个说明符是int数组。此外,您必须取消引用int数组才能打印数字。

我认为你应该更详细地研究数组和指针。