Open ghostbody opened 8 years ago
Notice that: These knowledge is very important for you and it's a good preparation for the course project as well as some other following courses. You can ignore this assignment, but you are responsible for the yourself.
Learn about command line compile and file input. And then use the method on one of the questions in week 7 in sicily (write this part in your report and snap shoots are recommended).
Learn about breakpoint debug method yourself and using it to debug the following three C programs.
Target: A solution with three correct C source programs.
Questions:
Notice that:
input:
3
3 1 3 2
5 1 2 3 4 5
4 99 100 22 33
output:
1 2 3
1 2 3 4 5
22 33 99 100
Also Notice that the output of the flowing program is not correct at all, please correct it
link: bubble sort insertion sort selection sort
#include <stdio.h>
int main() {
int num[10000];
int n;
int i, j, temp;
int m, k, p, q, o;
int result[2000];
scanf("%d", &n);
for(i = 0; i < n; i++) {
scanf("%d", &num[i]);
}
for(i = 0; i <= n; i++) {
for(j = 0; i + j < n; j++) {
if(num[j] > num[j + 1]) {
temp = num[j];
num[j + 1] = num[j];
num[j] = temp;
}
}
}
for(i = 0; i < n - 1; i++) {
printf("%d ", num[i]);
}
printf("%d\n", num[i]);
return 0;
}
#include <stdio.h>
int main() {
int num[10000];
int n;
int i, j, temp;
scanf("%d", &n);
for(i = 0; i < n; i++) {
scanf("%d", &num[i]);}
for(i=1; i<n; i++){
temp = num[i];
for(j=i-1; j>-1&&num[j]>temp;j--) {
num[i]=num[j]; num[j]=temp;}}
for(i = 0; i < n - 1; i++) {
printf("%d ", num[i]);}
printf("%d\n", num[i]);
return 0;
}
#include <stdio.h>
int main() {
int num[10000];
int n;
int i, j, temp;
scanf("%d", &n);
for(i = 0; i < n; i++)
scanf("%d", &num[i]);
for(i=0; i < n; i++){
min = num[i];
for(j = i; j < n; j++) {
if(min>num[j]) {
temp = num[j];
num[j] = min;
min = temp;
} for(i = 0; i < n - 1; i++) {
printf("%d ", num[i]);}
printf("%d\n", num[i]);
return 0;
}
In this part, you will have some options, if you do more options, you will learn more and get more marks. You should note this part in your report
Comment at the issue which is opened for dicuss for week7 and decribe a problem that you meet and how you solve detailedly.
Notice that
Have a simple presentation in the lab class on Monday (4 persons limited). And after the presentation, everyone is encouraged to ask questions and you can get bonus by asking good questions.
Notice that
You can help others to slove any problems the will meet. Detailedly decribe the quesion, the solution and your personal experience as well.
Notice that
Write personal summary for yourself. List the problems that you have met in your learning in c language this week and decribe the solution as well.
Notice that
Contents: 1、Assignment‘s Questions exclude the source code for the three programs. 2、Discussion, Cooperation and Summary Part.
作业发给学委,不要发压缩包,注意文件命名必须完全一致,否则机器测试无法进行,0分处理。
18:00 Nov 19th
Note that homework after deadline will not be accepted this time whatever your reasons. 本次作业不接受缓交。
1、 期中考试没有全部Accepted的同学,请将没有ac的题目重新做完,自行测试好。 2、没有全部ac的同学,每位同学,请自行到github这个地址进行comment,总结自己问题: link
1、没做完的题目的源代码,以pid.c命名,即1000.c等放在自己学好的文件夹。
2、发给学习委员,统一整理后发给我
2015年11月22日晚9点
不接受缓交
在写程序开发的过程中,不可避免的会出现很多bug,bug的类型也多种多样,可能是逻辑错误,也可能是内存泄露,这个时候我们就需要通过调试跟踪变量的值或者其他信息,来找出错误的位置,再进行修改,现在介绍两种常用的调试方法,断点调试以及输出调试,后面有一个内存泄露的检测小工具,有兴趣的同学可以自学一下。
以devC++为例,其他编译器用法类似 事例程序:
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int getRanking(string s1, string s2) {
int rank = 0;
for (int i = 0; i < s1.length(); i++) {
for (int j = 0; j < s2.find(s1[i]); j++) {
if (s1.find(s2[j]) > i) {
rank++;
}
}
}
return rank;
}
int getMedianRanking(string s1, string* s, int n) {
int total = 0;
for (int i = 0; i < n; i++) {
total += getRanking(s1, s[i]);
//cout << s1 << endl << s[i] << endl;
//cout << getRanking(s1, s[i]) << endl;
}
return total;
}
int main() {
int n;
string s[100];
string result = "ABCDE", target;
while (cin >> n && n != 0) {
for (int i = 0; i < n; i++)
cin >> s[i];
int min = 10000000;
target = result;
int temp = getMedianRanking(result, s, n);
min = temp < min ? temp : min;
while (next_permutation(result.begin(), result.end())) {
temp = getMedianRanking(result, s, n);
if (temp < min) {
min = temp;
target = result;
}
}
cout << target << " is the median ranking with value " << min << '.' << endl;
}
}
/*样例输入
4
ABDCE
BACDE
ABCED
ACBDE
*/
在你想要程序停止的位置所在的行,在行的前面设置一个断点,此时调试程序执行到这一步直接停止,此步不执行,在 开始调试
监视变量值以及当前状态 点击后出现下列对话框,输入要监视变量的名字 然后进行单步调试,观察左上角变量值的变化 开始查找错误
狂printf("blablablablablablablablablablablablabla");
下载得到的 memleak 压缩包大小不到 15 kB,解压后只有两个文件:memleak.c 和 memleak.h。在使用过程中只需要包含头文件 memleak.h 就可以使用 memleak 提供的几个易用而有效的内存检测函数了。
memleak 的原理是利用 C 语言的宏调用来替代原有的函数调用,比如我们在代码中调用 malloc(s),实际是调用了:dbg_malloc(s),这个宏定义在 memleak.h 中给出:
#define malloc(s) (FILE_LINE, dbg_malloc(s))
memleak 维护了一个链表,在这个链表中保存着程序中对内存函数调用的记录,这些函数包括:malloc、calloc、realloc、free。每次调用这些函数时,就会更新这个链表。 有了这个表,我们就可以在适当的位置调用 memleak 提供的函数,显示一些重要的信息,包括 malloc、calloc、realloc、free调用的次数,申请及分配的内存数,调用的文件和位置等等,信息非常详细。有了这些功能,我们就很容易定位内存使用的错误源。
由于 memleak 在某些交叉编译器下不能正常编译通过,这里我将 memleak.c 中的结构体 struct head 修改如下:
struct head
{
struct head *addr;
size_t size;
char *file;
unsigned line;
/* two addresses took the same space as an address and an integer on many archs => usable */
union lf {
struct { struct head*prev, *next; } list;
struct { char *file; unsigned line; } free;
} u;
};
memleak.c 文件中其它调用到 head 中共用体 u 的地方也要做相应的修改。 修改后的文件可以点击这里下载。
memleak 提供了以下几个函数接口:
extern void dbg_init(int history_length);
extern int dbg_check_addr(char *msg, void *ptr, int opt);
extern void dbg_mem_stat(void);
extern void dbg_zero_stat(void);
extern void dbg_abort(char *msg);
extern void dbg_heap_dump(char *keyword);
extern void dbg_history_dump(char *keyword);
extern void dbg_catch_sigsegv(void);
详细的介绍请查看 memleak.c 头部的注释或查看源代码理解。
下面举个简单的例子:
#include
#include
#include "memleak.h"
int main(void)
{
char * s, * t;
dbg_init(10);
s = (char *)malloc(100); // 申请 100 bytes
t = (char *)malloc(11); // 再申请 11 bytes
free(s); // 释放 100 bytes
s = (char *)malloc(80); // 重新申请 80 bytes
dbg_heap_dump(""); // 显示调用栈
dbg_mem_stat(); // 显示调用统计
free(t); // 释放 11 bytes
free(s); // 释放 80 bytes
dbg_mem_stat(); // 再次显示调用统计
return 0;
}
编辑后保存为 test.c,与 memleak.c 和 memleak.h 放于同一目录下。 然后编写一 Makefile:
CC = gcc
EXEC = test
CSRC = test.c memleak.c
OBJS = $(patsubst %.c,%.o, $(CSRC))
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) $(LDLIBS) -o $@
$(OBJS): %.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
-rm -f $(EXEC) *.elf *.gdb *.o
也保存于同一目录,在该目录下 make 编译,执行 ./test 后输出如下:
***** test.c:14: heap dump start
(alloc: test.c:11 size: 11)
(alloc: test.c:13 size: 80)
***** test.c:14: heap dump end
test.c:15: m: 3, c: 0, r: 0, f: 1, mem: 91
test.c:18: m: 3, c: 0, r: 0, f: 3, mem: 0
怎么样,很简单吧?
memleak 中还有一个函数 dbg_catch_sigsegv(void),可以绑定系统出现 SIGSEGV 信号时的处理函数,我们可以通过修改 memleak.c 中的 sigsegv_handler,自定义这个 SIGSEGV 信号处理函数。不知道 uClinux 下的 SIGSEGV 信号是否也存在,有的话调试一些内存问题就更容易了。
实验3:c程序断点调试
C程序完成一般思路
高效c语言编程方法
1、命令行编译与高效文本编辑器
为什么使用命令行编译?
配置方法: 1、打开Dev Cpp,并且找到对应的安装路径。 2、找到定义的MinGW目录下的bin目录这个是dev cpp的核心编译器。
3、配置系统环境变量,在系统的高级选项中找到path(可见第一周python配置方法)
4、打开cmd窗口,输入gcc --version输出编译器版本信息,配置完成。
编译方法: 1、找到一个c源代码所在的文件夹,在文件夹中按住shift+鼠标右键,选择在此处打开命令行。 2、输入gcc + 空格 + 你要编译的文件 -o 编译出来之后的可执行程序的名字, 如:
gcc main.c -o main.exe
(如果省略-o后面的命令,则会生成a.exe) 3、在命令行中输入 main.exe 即可运行程序。高效文本编辑器: 高效文本编辑器是一些专门为编程者设计的编辑器,他们具有自动缩进、自动补全代码、自由配置的特点,深受程序员喜爱。这些编辑器不仅仅c语言使用,c++、pyhton、html、markdown和许多其他语言都适用。他们有,vim、emacs、sublime等。
现在我们介绍sublime-text 3,这是一款收费软件,可是有无限试用期。
下载和使用请自行百度。
2、测试数据的文件输入输出代替键盘输入输出(重点)
现在大家做题一般的输入方法就是,按照西西里的测试例子,键盘输入,当程序错误的时候需要一次次输入非常繁琐,现在给大家提供一种高效而且重要的方法,文件流输入代替键盘流输入。
其实,在抽象的层面上,键盘输入、文件输入和网络输入等都是IO,是等价的。我们可以利用这个进行文件代替键盘输入。
1、在刚才我们编译的程序之中,我们生成了main.exe的程序。建设现在我们的程序是做a-b的简单运算。我们现在在源代码的同一个目录下新建一个文件"input.txt"。我们打开文件输入两个数100和99。
2、接着我们在命令行输入命令
main.exe < input.txt
。我们很惊喜地发现,程序自动输出了1,我们不需要手动去使用键盘输出。对于长而复杂的输入,这无疑是一个简化的过程。
对于文件输出,同样是可以的 'main.exe < input.txt >output.txt'
3、断点调试法(课题讲解)
错误示例代码(来源于同学)
1、设置断点 2、运行程序 3、添加监控变量 4、执行程序、单步运行