C/C++ 笔试,难倒我哉

  2012-6-27日下午,去了一个软件公司笔试面试,3道题目,都是 C 语言的编程题,题意简单明了,写起来好麻烦,而且是在纸上写的,平常习惯了写写改改,后来发现整个卷面乱的真不是给人看的。

  第一题:将n个文件合并到一个文件中,要求保存每个文件的文件名,文件长度,文件数据。函数签名 int fpack(const char *flist[], const char *dstfile); flist的形式 {"1.doc", "2.txt", "3.exe", NULL} 。第一题就难倒我了,首先是要读写二进制文件,fread, fwrite本身就用的不多,又有4个参数,参数 File * 在第一个还是在第四个常搞不清楚,且第二个参数和第三个参数容易混淆;文件长度要通过读文件数据才知道,那么文件头信息中的文件长度还不能一开始就写入,需要 fseek 来回定位,当时就直接看第2题和第3题了,最后回过头了,硬着头皮写完了这个函数,现在回来仔细想想当时写得真是漏洞百出啊,于是又重新写了一遍:

  

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 struct SFile {  //  注意边界对齐,f_name[6] 与 f_name[8] 时,sizeof(SFile) 都等于12
 5     int f_len;  //  感觉 f_len 应该写在 f_name 前面比较好
 6     char f_name[8];
 7 };
 8 
 9 void print_buf(const char *buf, int len) {
10     for (int i = 0; i < len; ++i)
11         printf("%X", buf[i]);
12     puts("");
13 }
14 
15 int fpack(const char *flist[], const char *dstfile) {
16     int n = 0;
17     const char **p = flist;
18     char buf[1024];
19     int len = 0;
20     SFile file;
21 
22     for (; *p != NULL; ++p, ++n) ;  //  统计需要 pack 的文件个数
23 
24     FILE *pDst = fopen(dstfile, "wb");
25     if (pDst == NULL) {
26         puts("pDst fopen error!");
27         return -1;
28     }
29 
30     printf("n = [%d]\n", n);    //
31     fwrite(&n, sizeof(n), 1, pDst); //  文件前siezof(int)个字节保存文件的个数
32 
33     for (p = flist; *p != NULL; ++p) {  //  遍历每个文件
34         printf("f_name = [%s]\n", *p);
35         strcpy(file.f_name, *p);    //  构造结构体
36         file.f_len = 0;
37 
38         FILE *pf = fopen(*p, "rb"); //  打开文件
39         if (pf == NULL) {
40             puts("pf fopen error!");
41             fclose(pDst);
42             return -1;
43         }
44 
45         fseek(pDst, sizeof(SFile), SEEK_CUR);   //  跨越文件头信息,先写文件数据
46         while ((len = fread(buf, 1, 1024, pf)) > 0) {   //  注意不能写成 fread(buf, 1024, 1, pf),否则 len 为 0
47             printf("len = [%d]\n", len);    //
48             print_buf(buf, len);    //
49             file.f_len += len;  //  更新文件长度数据
50             fwrite(buf, 1, len, pDst);
51         }
52 
53         int sz1 = sizeof(SFile);
54         int sz2 = file.f_len;
55         printf("sz1 = [%d], sz2 = [%d]\n", sz1, sz2);   //
56         printf("fn = [%d], fl = [%d]\n", sizeof(file.f_name), sizeof(file.f_len));
57 
58         fseek(pDst, -(sz1 + sz2), SEEK_CUR);    //  回到写文件头信息的位置
59         fwrite(&file, sz1, 1, pDst);            //  写入头信息
60         fseek(pDst, 0, SEEK_END);               //  定位到文件尾,为下一个文件做准备
61 
62         fclose(pf); //  关闭当前文件
63     }
64 
65     fclose(pDst);   //  关闭目标文件
66     return 0;
67 }
68 
69 int main(int argc, char *argv[])
70 {
71     const char *s[8] = {"111.txt", "222.txt", "333.txt"};
72     const char *d = "d.txt";
73 
74     printf("iRet = %d\n", fpack(s, d));
75 
76     return 0;
77 }

运行结果如下:

就算去掉注释,也最起码要50行,一面A4纸还真不一定能写下,何况纸上涂改是必然的。

  第三题:将一个带头结点的单链表转换成一个带头结点的双向循环链表,这个题目不仅要满足是双向链表,还要满足循环链表,从单链表直接跳了两步,但是和第一题、第二题比起来,对我来说或许还能折腾出来,于是就先写了此题,回来在机器来又找原来写了遍,测试了下基本没有出错,如下:

 1 #include <malloc.h>
 2 #include <stdio.h>
 3 
 4 struct Node {
 5     int data;
 6     Node *next;
 7 };
 8 
 9 struct BiNode {
10     int data;
11     BiNode *next;
12     BiNode *prev;
13 };
14 
15 BiNode *convert(const Node *head) {  //  假定内存足够,malloc不会失败
16     BiNode *pBh = (BiNode *)malloc(sizeof(BiNode)); //  双向循环链表头结点
17     pBh->data = 0;
18     pBh->next = pBh->prev = NULL;   //  默认置空
19 
20     BiNode *q = NULL;
21     Node *p = head->next;
22 
23     if (p != NULL) {   //  单链表不为空
24         q = (BiNode *)malloc(sizeof(BiNode));
25         q->data = p->data;
26         q->next = q->prev = q;  //  双向循环链表只有一个结点的时候,next 和 prev 均指向自己
27         pBh->next = pBh->prev = q;  //  头结点两个指针均指向第一个结点
28 
29         p = p->next;
30         for (; p != NULL; p = p->next) {    //  遍历单链表余下的结点
31             BiNode *t = (BiNode *)malloc(sizeof(BiNode));
32             t->data = p->data;
33             t->next = q->next;
34             t->prev = q;
35 
36             q->next = t;    //  原来的尾结点next指向新的尾结点
37             pBh->next->prev = t;    //  第一个结点prev指向新的尾结点
38 
39             q = t;  //  q 保持指向尾结点
40         }
41     }
42 
43     return pBh;
44 }
45 
46 void print_clockwise(const BiNode *h) {
47     const BiNode *p = h->next;  //  第一个结点
48     printf("data = [%d]\n", p->data);
49 
50     p = p->next;
51     for (; p != h->next; p = p->next)
52         printf("data = [%d]\n", p->data);
53 
54     puts("----");
55 }
56 
57 void print_anticlockwise(const BiNode *h) {
58     const BiNode *p = h->next;  //  第一个结点
59     printf("data = [%d]\n", p->data);
60 
61     p = p->prev;
62     for (; p != h->prev; p = p->prev)
63         printf("data = [%d]\n", p->data);
64 
65     puts("----");
66 }
67 
68 int main(void)
69 {
70     //  构造单链表
71     Node n[5];
72     Node *head = &n[0];
73     head->data = 0;
74     head->next = &n[1];
75     n[1].data = 1;
76     n[1].next = &n[2];
77     n[2].data = 2;
78     n[2].next = &n[3];
79     n[3].data = 3;
80     n[3].next = &n[4];
81     n[4].data = 4;
82     n[4].next = NULL;
83 
84     BiNode *pBh = convert(head);
85 
86     //  顺时针打印
87     print_clockwise(pBh);
88 
89     //  逆时针打印
90     print_anticlockwise(pBh);
91 
92     return 0;
93 }

运行结果如下:

哗啦哗啦又是90行,A4纸很紧张啊~~!

原文地址:https://www.cnblogs.com/nysanier/p/2566389.html