2017-04-18 71 views
0

我写了一个C代码来读取输入文件并写入输出文件。是使用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) 

任何人都可以让我知道如何使指针映射正确的位置,而阅读。

+0

您应该在调试器中逐行执行代码,以便缩小崩溃的位置。 –

+0

为什么复制“按记录记录”很重要,为什么不复制所有行呢?例如,这种方式更脆弱。该文件缺少一行或其他东西。 – unwind

+0

你的编译器不会激发大量的警告吗? – datell

回答

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); 
3

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

在随后的调用,len将被解释为当前缓冲区的长度,但事实并非如此。因此,比当前缓冲器大的len,与将根据len适合该缓冲区,可以重写存储器,从而导致不确定的行为的线。