使用C中的指针读取和写入文件?

时间:2017-04-18 11:48:16

标签: c file

我编写了一个C代码,用于从输入文件中读取并写入输出文件。

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




int callreadwrite(char *infile, char *outfile) {

   FILE *fi, *fo;
   char *line = NULL, *line1 = NULL, *line2 = NULL, *line3 = NULL, *line4 = NULL, *line5 = NULL, *line6 = NULL,*baseline1 = "Count";

    size_t len = 0;
    ssize_t read;
    int i = 0, countt, klent, tlenn, neq_vctr = 0, n = 0, res = 0, fin = 0, Nlenn, c;

    unsigned char *count, *klen, *tlen, *key, *msg, *nmac;

    time_t ltime; // calendar time 
    ltime = time(NULL); // get current cal time 

    fi = fopen(infile, "r");
    fo = fopen(outfile, "w");



    while ((read = getline(&line1, &len, fi)) != -1) {

      if (strncmp(baseline1, line1, 5) == 0) {
        getline(&line2, &len, fi);
        getline(&line3, &len, fi);
        getline(&line4, &len, fi);
        getline(&line5, &len, fi);
        getline(&line6, &len, fi);

        count = line1 + 8;
        klen = line2 + 7;
        tlen = line3 + 7;
        key = line4 + 6;
        msg = line5 + 6;
        nmac = line6 + 6;
         // convert string to integer: count, key length, message length, tag length
        countt = strtol(count, NULL, 0);
        fprintf(fo, "Count = %d\n", countt);


        klent = strtol(klen, NULL, 0);
        fprintf(fo, "Klen = %d\n", klent);

        tlenn = strtol(tlen, NULL, 0);

        fprintf(fo, "Count = %d\n", countt);
        fprintf(fo, "Klen = %d\n", klent);
        fprintf(fo, "Tlen = %d\n", tlenn);
        fprintf(fo, "Key = %s", key);
        fprintf(fo, "Msg = %s", msg);
        fprintf(fo, "Nmac = %s", nmac);




     }

 }

 fclose(fi);
 fclose(fo);

 return 0;

}




int main() {
     callreadwrite("read.txt", "write.txt");

}

程序将输入文件的内容复制到输出文件。如果输入文件的内容如下

Count = 0
Klen = 10
Tlen = 10
Key = 82f3b69a1bff4de15c33
Msg = fcd6d98bef45ed6850806e96f255fa0c8114b72873abe8f43c10bea7c1df706f10458e6d4e1c9201f057b8492fa10fe4b541d0fc9d41ef839acff1bc76e3fdfebf2235b5bd0347a9a6303e83152f9f8db941b1b94a8a1ce5c273b55dc94d99a171377969234134e7dad1ab4c8e46d18df4dc016764cf95a11ac4b491a2646be1
Mac = 1ba0e66cf72efc349207

Count = 1
Klen = 10
Tlen = 10
Key = 4766e6fe5dffc98a5c50
Msg = d68b828a153f5198c005ee36c0af2ff92e84907517f01d9b7c7993469df5c21078fa356a8c9715ece2414be94e10e547f32cbb8d0582523ed3bb0066046e51722094aa44533d2c876e82db402fbb00a6c2f2cc3487973dfc1674463e81e42a39d9402941f39b5e126bafe864ea1648c0a5be0a912697a87e4f8eabf79cbf130e
Mac = 007e4504041a12f9e345

但是当输入文件包含一个条目时,它会给出错误

Count = 3
Klen = 142
Tlen = 64
Key = f78343071f61ee7d9f791bd53132e6d557928bcfe4b214bebf6f3592e46374c7ab148c3c4d6a1443a4675cf4321298c865b440631947b6b05f2c2a337d1cbb9b3661de974b4604eb41cc77c3659e85470e47e16f22a34619db935d59cbf5e1101ed401c020db069eff1035e9d1bff77bd8b3379e05ac0c20bc0e98aad7d7304dedd3bc5ed4136184649b5e0f7e5b
Msg = d63b50b54e1536e35d5f3c6e29f1e49a78ca43fa22b31232c71f0300bd56517e4cd29ba11ee9f206f1ad31ee8f118c87004d6c6dfe837b70a9a2fa987c8b5b6680720c5dbf8791c1fcd6d59fa16cc20df9bc0fb39f41598a376476e45b9f06add8e34af01b373a9ce6a3d189484cacb6cbe0d3d5ef34d709d72c1dee43dc79da
Mac = 086f674d778db491e73b6fbc5126233c6b6e1f066963356d49ea386d9c0868ad25bf6edad0371cde87cea94a18c6dba47535dfce2e40d2246ab17980495d656c

错误如下

 *** Error in `./aout': munmap_chunk(): invalid pointer: 0x0000000000b70810 ***
   ======= Backtrace: =========
   /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f23e8d397e5]


  ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
  Aborted (core dumped)

任何人都可以告诉我如何在阅读时让指针映射到正确的位置。

2 个答案:

答案 0 :(得分:3)

您的主要问题是getlinegetline将分配一个缓冲区并重新分配它。您为每一行指定了一个指针,但是您使用了一个len变量。

在后续调用中,len将被解释为当前缓冲区的长度,但事实并非如此。因此,如果len大于当前缓冲区,并且根据len符合该缓冲区的行,则可能会覆盖内存,从而导致未定义的行为。

答案 1 :(得分:2)

问题在于您对getline()功能的处理。它将为您分配存储空间,但仅限于特定条件:

  • lineptr == NULL和len == 0:分配所需的空间
  • len!= 0:如果空间不够大,则重新分配空间

在您的情况下,您初始化行指针,但您对所有读取使用相同的len变量。 getline()函数使用len来跟踪它分配了多少空间,因此每行需要一个len。

最简单的解决方案是为每一行创建一个单独的len变量。

size_t len1 = 0, len2 = 0, len3 = 0, len4 = 0, len5 = 0, len6 = 0;

while ((read = getline(&line1, &len1, fi)) != -1) {
  if (strncmp(baseline1, line1, 5) == 0) {
    getline(&line2, &len2, fi);
    getline(&line3, &len3, fi);
    getline(&line4, &len4, fi);
    getline(&line5, &len5, fi);
    getline(&line6, &len6, fi);