第一次写c程序,希望大家多提意见!

eTouX 2010-03-22 09:54:21
一直以来学c只是为了考试,前几天为了把一个文件下的所有的图片拷贝出来写了个c程序,由于是第一次写,经验不足,代码如下,希望大家给我指出有什么不足之处,使我能更上一层楼。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int read()
{
FILE *fp = fopen("./pipe","rb+");
int temp = fgetc(fp);
temp += 1;
rewind(fp);
fwrite(&temp, sizeof(int), 1, fp);
fclose(fp);
return temp;
}

void path(char * p, int nr)
{
*(p+0) = nr / 100 + '0';
*(p+1) = (nr / 10) % 10 + '0';
*(p+2) = nr % 10 + '0';
*(p+3) = '\0';
}

int copy(char * src)
{
FILE *fps = fopen(src, "rb");
if (!fps){
printf("%s doesn't exist.\n",src);
exit(-1);
}
char *p = (char*) malloc(10);
char *dest = (char*) malloc(100);
strcpy(dest,"./pic/");
path(p, read());
strcat(dest,p);
strcat(dest,".jpg\0");


FILE *fpd = fopen(dest,"wb");
if (!fpd) {
printf("Create failed.\n");
exit(-1);
}

while (!feof(fps)) fputc(fgetc(fps), fpd);

fclose(fps);
fclose(fpd);
free(p);
free(dest);
return 0;
}

void init()
{
FILE *fp = fopen("./pipe","r");
if (!fp){
//if there is no pipe then create one.
fp = fopen("./pipe","w");
}
fclose(fp);
}

void rm_space(char * src)
{
int i = 0;
while(*(src+i++));
i -= 2;
while (*(src+i) == '\040'){
*(src+i) = '\0';
i--;
}
}


int main(int argc, char *argv[20])
{
init();
char *src = (char *)malloc(100);
int i = 1;
*src = '\0';
while (i != argc){
if (i < argc){
strcat(src,argv[i++]);
strcat(src,"\040");
}
else
strcat(src,argv[i]);
}

rm_space(src);
copy(src);

free(src);
return 0;
}


下面是一个简单的shell:
#!/bin/bash
rm ./pipe
rm ./pic/*
gcc -o copy main.c
find '/home/etoux/Music/Nightwish APE/' -name '*.jpg' -exec './copy' {} \;


...全文
196 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
eTouX 2010-03-23
  • 打赏
  • 举报
回复
感谢xuwmzi,我已做修改,请看看还有什么要改进的?
////////////////////////////////////////////////////////////////
//说明:
// 该程序配合find指令拷贝一个子目录下所有的图片到指定文件夹
////////////////////////////////////////////////////////////////
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//该函数从一个临时文件读出一个整数加一并返回临时文件。
//返回值:读书的整数
int read()
{
FILE *fp = fopen("./pipe","rb+");
int temp = fgetc(fp);
temp += 1;
rewind(fp);
fwrite(&temp, sizeof(int), 1, fp);
fclose(fp);
return temp;
}

//该函数将一个整数转化成字符串
//字符串存在p指针开始的内存。
void path(char * p, int nr)
{
*(p+0) = nr / 100 + '0';
*(p+1) = (nr / 10) % 10 + '0';
*(p+2) = nr % 10 + '0';
*(p+3) = '\0';
}

//该函数将src所指向的文件,复制到目标文件夹中。
int copy(char * src)
{
char *p = (char*) malloc(10);
char *dest = (char*) malloc(100);

//生成目标路径名。规范为./pic/nr.jpg
strcpy(dest,"./pic/");
path(p, read());
strcat(dest,p);
strcat(dest,".jpg");

FILE *fps = fopen(src, "rb");
if (!fps){
printf("%s doesn't exist.\n",src);
free(p);
free(dest);
return -1;
}

FILE *fpd = fopen(dest,"wb");
if (!fpd) {
printf("Create failed.\n");
free(p);
free(dest);
return -1;
}

//从源文件拷贝到了目标文件
while (!feof(fps)) fputc(fgetc(fps), fpd);

fclose(fps);
fclose(fpd);
free(p);
free(dest);
return 0;
}

//检查是否存在临时文件,如果没有就创建一个。
void init()
{
FILE *fp = fopen("./pipe","r");
if (!fp){
//if there is no pipe then create one.
fp = fopen("./pipe","w");
}
fclose(fp);
}

//删除掉一个字符串中尾端的空格
void rm_space(char * src)
{
int i = 0;
while(*(src+i++));
i -= 2;

//如果是空格,删除
while (*(src+i) == '\040'){
*(src+i) = '\0';
i--;
}
}


int main(int argc, char *argv[50])
{
init();
char *src = (char *)malloc(100);
int i = 1;
*src = '\0';

//将find中传入的多个参数(以空格隔开)合并成一个字符串
//即源文件的路径。
while (i != argc){
if (i < argc){
strcat(src,argv[i++]);
strcat(src,"\040");
}
else
strcat(src,argv[i]);
}

//删除掉字符串尾端的空格,我也不知道为什么会有空格在尾部。
//如果不删除将得不到正确结果
rm_space(src);
copy(src);

free(src);
return 0;
}


/*
#!/bin/bash
rm ./pipe
rm ./pic/*
gcc -o copy main.c
find '/home/etoux/Music/Nightwish APE/' -name '*.jpg' -exec './copy' {} \;
*/



还有一点,我运行了可以把图片拷贝出来,但终端出现了一面一排字不知道是什么意思,谁能解释下吗?


======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0x2c2ff1]
/lib/tls/i686/cmov/libc.so.6[0x2c46f2]
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0x2c779d]
/lib/tls/i686/cmov/libc.so.6(fclose+0x14a)[0x2b350a]
./copy(read+0x6e)[0x8048732]
./copy[0x8048825]
./copy[0x8048a8d]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x26eb56]
./copy[0x8048631]
======= Memory map: ========
0023b000-00256000 r-xp 00000000 08:05 2171 /lib/ld-2.10.1.so
00256000-00257000 r--p 0001a000 08:05 2171 /lib/ld-2.10.1.so
00257000-00258000 rw-p 0001b000 08:05 2171 /lib/ld-2.10.1.so
00258000-00396000 r-xp 00000000 08:05 5593 /lib/tls/i686/cmov/libc-2.10.1.so
00396000-00398000 r--p 0013e000 08:05 5593 /lib/tls/i686/cmov/libc-2.10.1.so
00398000-00399000 rw-p 00140000 08:05 5593 /lib/tls/i686/cmov/libc-2.10.1.so
00399000-0039c000 rw-p 00000000 00:00 0
008f1000-0090d000 r-xp 00000000 08:05 2221 /lib/libgcc_s.so.1
0090d000-0090e000 r--p 0001b000 08:05 2221 /lib/libgcc_s.so.1
0090e000-0090f000 rw-p 0001c000 08:05 2221 /lib/libgcc_s.so.1
00fd2000-00fd3000 r-xp 00000000 00:00 0 [vdso]
08048000-08049000 r-xp 00000000 08:03 50 /home/etoux/work/copy/copy
08049000-0804a000 r--p 00000000 08:03 50 /home/etoux/work/copy/copy
0804a000-0804b000 rw-p 00001000 08:03 50 /home/etoux/work/copy/copy
08afc000-08b1d000 rw-p 00000000 00:00 0 [heap]
b7700000-b7721000 rw-p 00000000 00:00 0
b7721000-b7800000 ---p 00000000 00:00 0
b784c000-b784d000 rw-p 00000000 00:00 0
b785d000-b785f000 rw-p 00000000 00:00 0
bfdd9000-bfdee000 rw-p 00000000 00:00 0 [stack]
find: `./copy' terminated by signal 6
cocat 2010-03-23
  • 打赏
  • 举报
回复
都是牛人~第一次啊
eTouX 2010-03-23
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 xuwmzi 的回复:]

引用 9 楼 xuwmzi 的回复:
你多处用exit()直接退出,最后用return 0,进行返回.不觉得有什么不对么?

不知道这话,你明白了没,你的return 只有一个,而且是常量,没有其他返回值,只有退出选项,这样的函数,根本没必要有返回值,不是么?
[/Quote]

你说的对,我本打算出错了返回不一样的值,写的时候忘记了。
xuwmzi 2010-03-23
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 xuwmzi 的回复:]
你多处用exit()直接退出,最后用return 0,进行返回.不觉得有什么不对么?
[/Quote]
不知道这话,你明白了没,你的return 只有一个,而且是常量,没有其他返回值,只有退出选项,这样的函数,根本没必要有返回值,不是么?
zhangwenlang 2010-03-23
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 jackyjkchen 的回复:]
单凭你的命名和排版规范,楼主,你很有前途。
[/Quote]楼主应该第一次就能写出这个风格的代码,绝对的天才。。
linyongzuo 2010-03-23
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 huanmie_09 的回复:]
引用 13 楼 yuzl32 的回复:
引用 10 楼 cocat 的回复:
都是牛人~第一次啊

+2

+3
[/Quote]
+4
huanmie_09 2010-03-23
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 yuzl32 的回复:]
引用 10 楼 cocat 的回复:
都是牛人~第一次啊

+2
[/Quote]
+3
yuzl32 2010-03-23
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 cocat 的回复:]
都是牛人~第一次啊
[/Quote]
+2
eTouX 2010-03-23
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 xuwmzi 的回复:]
过谦了吧,第一次哪写的出这个来.
注释需要注意一下,为了以后的方便阅读和修改,最好在函数前写一下参数作用,参数作用等,相当于函数介绍.
像 if else while for 之类后边跟一条语句,可以加个大括号,更加明了.不加只要自己很清醒也没问题
temp += 1;像这样的,不明白要表达什么意思,可以加个注释嘛.然后用temp++;
while (*(src+i) == '\040')……
[/Quote]

谢谢这位朋友!!至于我说的“第一次”是第一次因为需求而写,以前做作业做了挺多的。
eTouX 2010-03-23
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 xuwmzi 的回复:]

其实我看你写的程序只是由上向下看一遍而以,并没有管他是做什么的,当然编写者自然应该写明白.
编写程序,有时候需要注意很多东西,可能远远超过你的想你,比如说你的这个函数
void path(char * p, int nr);
nr 的取值是有范围的是吧,如果超出范围是不是超过你的想你?得到意外的结果?
我记得有一个sprintf() 函数可以实现类型间的转换,你不妨查查.
[/Quote]

超出范围就会覆盖了,我假定我的文件没有达到1000个。

谢谢你的帮助,我想我学会了很多。
eTouX 2010-03-23
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 xuwmzi 的回复:]

其实我看你写的程序只是由上向下看一遍而以,并没有管他是做什么的,当然编写者自然应该写明白.
编写程序,有时候需要注意很多东西,可能远远超过你的想你,比如说你的这个函数
void path(char * p, int nr);
nr 的取值是有范围的是吧,如果超出范围是不是超过你的想你?得到意外的结果?
我记得有一个sprintf() 函数可以实现类型间的转换,你不妨查查.
[/Quote]

谢谢,学习了。至于这个取值范围我原本是想到的,写的时候忘记了。。
xuwmzi 2010-03-23
  • 打赏
  • 举报
回复
其实我看你写的程序只是由上向下看一遍而以,并没有管他是做什么的,当然编写者自然应该写明白.
编写程序,有时候需要注意很多东西,可能远远超过你的想你,比如说你的这个函数
void path(char * p, int nr);
nr 的取值是有范围的是吧,如果超出范围是不是超过你的想你?得到意外的结果?
我记得有一个sprintf() 函数可以实现类型间的转换,你不妨查查.
赵4老师 2010-03-23
  • 打赏
  • 举报
回复
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
invail 2010-03-23
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 cocat 的回复:]
都是牛人~第一次啊
[/Quote]
+1
xuwmzi 2010-03-22
  • 打赏
  • 举报
回复
过谦了吧,第一次哪写的出这个来.
注释需要注意一下,为了以后的方便阅读和修改,最好在函数前写一下参数作用,参数作用等,相当于函数介绍.
像 if else while for 之类后边跟一条语句,可以加个大括号,更加明了.不加只要自己很清醒也没问题
temp += 1;像这样的,不明白要表达什么意思,可以加个注释嘛.然后用temp++;
while (*(src+i) == '\040') 这样的,别人看起来,根本不知道什么意思,过段时间说不定你自己也不知道,加个注释呗.
int copy(char * src) 这个函数,你多处用exit()直接退出,最后用return 0,进行返回.不觉得有什么不对么?exit 退出真的指望OS帮你处理?一个程序要有健壮性,不要随便遇到错误就退出.除非是被恶意破坏,否则一定要坚持运行下去,哈哈
先说这些,都是些小问题.好好学,很有前途
jackyjkchen 2010-03-22
  • 打赏
  • 举报
回复
单凭你的命名和排版规范,楼主,你很有前途。

eTouX 2010-03-22
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 phoenix_ymj 的回复:]
注意格式
[/Quote]

正确的格式是怎么样的?
  • 打赏
  • 举报
回复
楼主很不错哇!接着加油!
eTouX 2010-03-22
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 cattycat 的回复:]
不错,这个是你前几天shell那个问题吧,没看清楚是怎么判断文件是否存在的。
[/Quote]

我采用的是用数字依次递增的方法命名新的文件的,递归的方法不用api还真不知道应该怎么做
phoenix_ymj 2010-03-22
  • 打赏
  • 举报
回复
注意格式
加载更多回复(3)
程序名称:OllyDBG版 本:1.10汉 化 人:cao_cong联系方式:cao_cong_hx@yahoo.com.cn汉化日期:2005.11.28汉化说明: 本来是想等 OllyDBG 2.0 出来再汉化的,可看到dyk158兄弟的修改版说明中对我原来汉化版本的汉化质量提了一点小小的意见,想想也是,我原来的汉化版是OllyDBG 1.10 的最终版本刚出来时汉化的,距今已经一年多了也没有更新过,当时只顾不出因汉化造成的Bug,汉化嘛确实不咋的。看到BoOMBoX/TSRh2004他们制作的美化界面,确实也觉得漂亮,最后决定再出个汉化版本。这个版本的汉化加测试、修改花了我整整两个星期的业余时间,其中的非标字符对照文本有4000多行,看一遍都半天。这个版本中的所有翻译我都重新过了几遍,绝大部分都重新翻译过,力求做到准确,希望能给大家一个比较完美的汉化版本。在制作过程中参考了TT小组翻译的OllyDBG帮助及dyk158修改、聆风听雨汉化的ODbyDYK修改版,主要是想让翻译更准确一点,能让新手把汉化版和TT小组汉化的帮助文档对照起来学习。在此对以上提到的各位表示衷心的感谢! 这个软件汉化起来确实是个苦差事,不光是要翻译的资源多,还有一个重要的方面就是稍不留神就会出现汉化引起的Bug。经常是用原版来调试汉化版找问题,象原来菜单上的“&Window”汉化后会出错,还是调试后才知道原来它内部加载菜单时还有个这个“&Window”,只有两个都汉化才不会出错。另外其它的许多问题都只好靠调试来解决。原来汉化时又没有把要注意的地方下来,这次光测试就花了好几天。 这个汉化版本除因汉化必要而打补丁外,我不准备再对它打任何补丁。一是我怕打补丁影响 OllyDBG 的兼容性;二是已经有Fly和dyk158他们做了,我想我自己再做的话也不会比他们做的更好;三是我实在是感到太累了!如果大家要想要修改的版本的话,推荐使用freecat兄弟制作的AutoPath,我把这个插件放在 FixOD 目录下,我把freecat兄弟发布时所用的说明也放在同一目录下,大家可以根据说明来使用这个插件改造你的OllyDBG。 在这里我要感谢看雪论坛上的看雪老大和论坛上各位兄弟的支持,正是有了他们的测试和建议,经过多次修正后,才有了今天的这个最终版本,由衷的感谢看雪论坛上的各位兄弟!汉化第二版主要更新:1、界面采用 BoOMBoX/TSRh2004 制作的美化界面,主要为了好看一点。2、绝大部分句子都重新翻译过,力求做到准确。3、配置文件中除字体、语法高亮、颜色这几个部分保留为中文外,其它的都恢复为英文。保留字体、语法高亮、颜色这几个部分为中文的目的是因为我发现若先运行过英文版配置好后,汉化版中对应这几个部分的一些菜单也会取原英文版配置中的英文字串,而不是汉化过的字串。我觉得翻译后既能保持与英文版的兼容性,又能让英文版与中文版的界面等互不干扰。4、dyk158 建议我把配置文件中的字体、语法高亮、颜色这几个部分恢复为英文,我专门做了个恢复为英文配置的补丁(如果你以前运行过英文版进行了相应配置,则补丁后的汉化版本对应这几个部分的相应菜单将会显示英文,若你是用打过这个补丁的汉化版本生成配置文件,则相应菜单将会显示中文)放在英文配置补丁目录下,需要字体、语法高亮、颜色这部分也用英文配置的朋友可以把这个补丁放到我做的汉化版的安装目录,选择 Ollydbg.exe 补丁就可以了。这个补丁同样适用于原版界面的汉化版本。5、上一版中部分未汉化的内容这次除了不能汉化的外,基本上都已汉化。6、另有一个界面未作美化的汉化版放在原版界面目录,可以按自己的喜好选择使用哪一个。7、FixOD 目录下放的是用 freecat 的 AutoPath.dll 打过补丁的 OllyDBG,使用前请先备份好你原来的Ollydbg.exe文件,再把这个目录下的Ollydbg.exe、AutoPath.dll、AutoPath.ini复制到你的OllyDBG安装目录下就可以了。在上一版的基础上,插件做了如下更新:1、脚本插件 ODbgScript.dll (v1.23 汉化版)2、快捷命令插件 CmdBar.dll (v3.10.109c 汉化版,这个版本有支持运行 OllyScript 脚本的命令:OSC)3、标签插件 Labeler.dll (v1.33.108 汉化版)4、图表插件 OllyFlow.dll (v0.71 汉化版,我从IDA中提取了个wingraph32.exe放在插件目录下,用于配合这个插件)5、断点管理 olly_bp_man.dll (汉化版,在我机器上不能用,放在备用目录)6、字串参考修改版本 ustrrefadd.dll (汉化版)另外还添加了dyk158 汉化的两个插件:1、脱壳插件 OllyDump.dll (V3.00.110 dyk158 汉化版)2、脱壳插件 pedumper.dll (v3.03 dyk158 汉化版) 推荐大家试用一下这两个插件:ApiBreak 插件,用于在对话框、字串、注册表、时间、内存等 API 函数上设置断点,还可设置万能断点,简单易用;GODUP 插件,包含 Map 载入器、资源查看器、进程查看器、IDA 签名载入程序及自带的一个记事本这五个工具。感觉它自带的记事本用来在调试时记一些东西比较方便。 如果你以前没用过OllyDBG的话,我要提醒你使用前先在菜单的 选项->界面->目录 中把插件和 UDD 的路径设置好,以免影响使用! 此汉化版中的插件除了一个 PuntosMagicos.dll 插件没汉化外(我实在是弄不懂是哪国语言),其它的插件都已汉化。目录下的OLLYDBG.HLP帮助文件是由TT小组翻译的中文帮助,在此对TT小组的辛勤劳动表示感谢!(OLLYDBG_EN.HLP为原版英文帮助)声明: 1.本汉化软件包内的所有英文及其他语言的源程序的版权归原作者(公司)所有。 2.本人不对使用本汉化软件造成的任何情况的损失负责。 3.本汉化软件仅供学习研究之用。严禁用于商业用途。本人不对使用本汉化软件造成的任何法律纠纷负责。 4.如果你对本汉化软件有什么建议请联系我。 5.请在转载时保留此汉化版的完整性。

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧