① c语言实验:查找c盘中的所有文件夹,对于子文件夹中的文件也要进行查找输出。
优化了一下,但还是有bug,需要细查
#include<io.h>
#include<stdio.h>
#include<string.h>
#define_A_SUBDIR0x10/*Subdirectory*/
voidsearch(char*str1)
{
longflag1=0;
longhandle1;
chars1[]="\",s2[]="*.*",s3[100],name[100];
struct_finddata_tffblk1;
strcat(str1,s1);strcpy(s3,str1);strcat(str1,s2);
handle1=_findfirst(str1,&ffblk1);
while(!flag1)
{
if(strcmp(ffblk1.name,".")&&strcmp(ffblk1.name,".."))
{
if(ffblk1.attrib==_A_SUBDIR){
printf("%sisasub-directory ",ffblk1.name);
strcpy(name,ffblk1.name);
strcat(s3,name);
search(s3);
}
else{
printf("%s ",ffblk1.name);
}
}
flag1=_findnext(handle1,&ffblk1);
}
}
voidmain()
{
// struct_finddata_tffblk;
charstr[200]="C:";//必须是数组,不然空间不够
search(str);
}
② c语言中多个文件的编译问题
第一个问题
请问,我是不是该这样做:
在main.c中#include
在fun.c中同样#include
(好像是必需的,请详细解释)
这是必需的。因为编译器只是把包含文件的代码复制过来,既然你二个文件中都用到头文件的内容,那当然要包含头文件,否则就会出错。
我的观点,如果这两步都是必需的
那么当有很多个比如10个.c程序每个里头都要#include
那么文件是不是会特别大,当有100个.c程序都要包含一下的话,那么不是非常重复么?)
那当然是会重复的。不过这个对程序的运行效率没任何影响,只是在编译过程中对文件的分析时间会稍长些,这也是没有办法的事,全看代码编写者如何组织结构了。
第二个问题:
会的。解决的方法就是在可能被多次包含的头文件中开头加上#pragma
once,那样就可以保证此头文件代码只被执行一次,而不会造成头文件中函数多次重复定义至于引起这种情况的情况。当然你也可以自己用#ifdef等预编译处理来解决。你问的问题不就是这种情况么?main.c和fun.c中都包含头文件tou.h
第三个问题:
当我在main.c中这样
#define
unchar
unsigned
char
那么当我在fun.c中还需要重新创建替换宏unchar吗
可以不在创建而直接使用吗?
答案是需重新创建,不能直接使用。但你可以把一些在多个文件中使用的宏、全局变量等统一定义到一个头文件中,那这样就可以避免多次定义了。
③ C语言 数据结构 文件及查找问题
关键字序列是{22,41,53,8,46,30,1,31,66},计算过程如下:
插入关键字22,索引(散列值)=3*22mod11=0,存入散列表:
下标012345678910
关键字22
插入关键字41,索引(散列值)=3*41mod11=2,存入散列表:
下标012345678910
关键字2241
插入关键字53,索引(散列值)=3*53mod11=5,存入散列表:
下标012345678910
关键字224153
插入关键字8,索引(散列值)=3*8mod11=2,有冲突,取索引2+1=3,没有冲突,存入散列表:
下标012345678910
关键字2241853
插入关键字46,索引(散列值)=3*46mod11=6,存入散列表:
下标012345678910
关键字224185346
插入关键字30,索引(散列值)=3*30mod11=2,有冲突,取索引2+1=3,仍有冲突,
取索引3+1=4,没有冲突,存入散列表:
下标012345678910
关键字22418305346
插入关键字1,索引(散列值)=3*1mod11=3,有冲突,依次取索引4,5,6,均有冲突,
取索引7,没有冲突,存入散列表:
下标012345678910
关键字224183053461
插入关键字31,索引(散列值)=3*31mod11=5,有冲突,依次取索引6,7,均有冲突,
取索引8,没有冲突,存入散列表:
下标012345678910
关键字22418305346131
插入关键字66,索引(散列值)=3*66mod11=0,有冲突,取索引0+1=1,没有冲突,存入散列表:
下标012345678910
关键字2266418305346131
这就是最后得到的散列表.
//C语言测试程序
#include<stdio.h>
#include<stdlib.h>
#defineSUCCESS1
#defineUNSUCCESS0
#defineHASHSIZE11
#defineNULLKEY-1
typedefintStatus;
typedefstruct
{
int*elem;
intcount;
}HashTable;
intm=0;
StatusInitHashTable(HashTable*H)
{
inti;
m=HASHSIZE;
H->count=m;
H->elem=(int*)malloc(m*sizeof(int));
for(i=0;i<m;i++)
{
H->elem[i]=NULLKEY;
}
returnSUCCESS;
}
intHash(intkey)
{
return(3*key)%m;
}
voidInsertHash(HashTable*H,intkey)
{
intaddr;
intpos;
pos=Hash(key);
addr=pos;
while(H->elem[addr]!=NULLKEY)
{
////////
printf("索引=%d有冲突. ",addr);
////////
addr=(addr+1)%m;
if(addr==pos)
{
printf(" 散列表已满! ");
exit(1);
}
}
H->elem[addr]=key;
}
StatusSearchHash(HashTableH,intkey,int*addr)
{
*addr=Hash(key);
while(H.elem[*addr]!=key)
{
*addr=(*addr+1)%m;
if(H.elem[*addr]==NULLKEY||*addr==Hash(key))
{
returnUNSUCCESS;
}
}
returnSUCCESS;
}
voidshowHashTable(HashTable*H)
{
inti;
for(i=0;i<H->count;i++)
{
printf("%4d",i);
}
printf(" ");
for(i=0;i<H->count;i++)
{
if(H->elem[i]==NULLKEY)
{
printf("%4c",0x20);
}
else
{
printf("%4d",H->elem[i]);
}
}
printf(" ");
}
intmain()
{
intkey[]={22,41,53,8,46,30,1,31,66};
intlen;
inti;
HashTableH;
InitHashTable(&H);
len=sizeof(key)/sizeof(key[0]);
for(i=0;i<len;i++)
{
printf("插入关键字%d,索引(Hash)=%d ",key[i],Hash(key[i]));
InsertHash(&H,key[i]);
showHashTable(&H);
}
return0;
}
④ 在win7下用dev编c程序在编译时系统找不到指定的文件 这怎么解决
1,一定要把Dev装在系统盘(一般是C盘),经验所得,多数编译工具必须装在系统盘,否则会出现各种“找不到文件”“XXX指令无效”等错误…。
2,安装完整版的Dev,4.9.9.2的安装包大约10M左右。
3,推荐新版本wxDev-C
7.4这是在Dev停止更新后,另外一个团队接手Dev项目,改进的新版本,国外很火,国内几乎无人知晓。
⑤ c语言程序如何找回main.c文件
C语文程序中必须有main()函数。
C的设计原则是把函数作为程序的构成模块。main()函数称之为主函数,一个C程序总是从main()函数开始执行的。
一、main()函数的形式
在最新的 C99 标准中,只有以下两种定义方式是正确的:
int main( void ) /* 无参数形式 */
{
...
return 0;
}
int main( int argc, char *argv[] ) /* 带参数形式 */
{
...
return 0;
}
int指明了main()函数的返回类型,函数名后面的圆括号一般包含传递给函数的信息。void表示没有给函数传递参数。关于带参数的形式,我们等会讨论。
浏览老版本的C代码,将会发现程序常常以main()这种形式开始。C90标准允许这种形式,但是C99标准不允许。因此即使你当前的编译器允许,也不要这么写。
你还可能看到过另一种形式。
void main()
有些编译器允许这种形式,但是还没有任何标准考虑接受它。C++ 之父 Bjarne Stroustrup 在他的主页上的 FAQ 中明确地表示:void main( ) 的定义从来就不存在于 C++ 或者 C 。所以,编译器不必接受这种形式,并且很多编译器也不允许这么写。
坚持使用标准的意义在于:当你把程序从一个编译器移到另一个编译器时,照样能正常运行。
二、main()函数的返回值
从前面我们知道main()函数的返回值类型是int型的,而程序最后的 return 0; 正与之遥相呼应,0就是main()函数的返回值。那么这个0返回到那里呢?返回给操作系统,表示程序正常退出。因为return语句通常写在程序的最后,不管返回什么值,只要到达这一步,说明程序已经运行完毕。而return的作用不仅在于返回一个值,还在于结束函数。
现在我们来做一个小试验来观察main()函数的返回值。编写如下代码并编译运行:
//a.c
#include "stdio.h"
int main(void)
{
printf("I love you.");
return 0;
}
将这个文件保存为a.c,编译运行后会生成一个a.exe文件。现在打开命令提示符,在命令行里运行刚才编译好的可执行文件,然后输入 echo %ERRORLEVEL% ,回车,就可以看到程序返回 一个0 。如果把 return 0; 改为 return 99; ,那么很显然,再次执行上述步骤以后你可以看到程序返回99。要是你这样写 return 99.99; 那还是返回99,因为99.99被传给操作系统之前,被强制类型转换成整数类型了。
现在,我们把a.c改回原来的代码,然后再编写另一个程序b.c:
//b.c
#include "stdio.h"
int main(void)
{
printf("I’m too.");
return 0;
}
编译运行后打开命令提示符,在命令行里输入a&&b 回车,这样你就可以看到《人鬼情未了》里面经典的爱情对白:
I love you.
I’m too.
&& 的含义是:如果 && 前面的程序正常退出,则继续执行 && 后面的程序,否则不执行。所以,要是把a.c里面的 return 0; 删除或者改为 return 99; ,那么你只能看到 I love you. 。也就是说,程序b.c就不执行了。现在,大家该明白 return 0; 的作用了吧。
三、main()函数的参数
C编译器允许main()函数没有参数,或者有两个参数(有些实现允许更多的参数,但这只是对标准的扩展)。这两个参数,一个是int类型,一个是字符串类型。第一个参数是命令行中的字符串数。按照惯例(但不是必须的),这个int参数被称为argc(argument count)。大家或许现在才明白这个形参为什么要取这么个奇怪的名字吧,呵呵!至于英文的意思,自己查字典吧。第二个参数是一个指向字符串的指针数组。命令行中的每个字符串被存储到内存中,并且分配一个指针指向它。按照惯例,这个指针数组被称为argv(argument value)。系统使用空格把各个字符串格开。一般情况下,把程序本身的名字赋值给argv[0],接着,把最后的第一个字符串赋给argv[1],等等。
现在我们来看一个例子:
//c.c
#include "stdio.h"
int main(int argc, char *argv[])
{
int count;
printf("The command line has %d arguments:
", argc - 1);
for(count = 1; count < argc; count++)
printf("%d: %s
", count, argv[count]);
return 0;
}
编译运行,在命令行输入c I love you 回车,下面是从命令行运行该程序的结果:
The command line has 3 arguments:
1:I
2:love
3:you
从本例可以看出,程序从命令行中接受到4个字符串(包括程序名),并将它们存放在字符串数组中,其对应关系:
argv[0] ------> c(程序名)
argv[1] ------> I
argv[2] ------> love
argv[3] ------> you
至于argc的值,也即是参数的个数,程序在运行时会自动统计,不必我们操心。
这个例子中,每个字符串都时一个单词(字母),那既然是字符串,要把一句话当作参数赋给程序该怎么办?你可以在命令行里这样输入 c "I love you." "I’m too."。程序运行结果:
The command line has 2 arguments:
1:I love you.
2:I’m too.
其对应关系:
argv[0] ------> c(程序名)
argv[1] ------> I love you.
argv[2] ------> I’m too.
要注意的是,你在命令行的输入都将作为字符串形式存储于内存中。也就是说,如果你输入一个数字,那么要输出这个数字,你应该用%s格式而非%d或者其他。
再来看一个例子:
//d.c
#include "stdio.h"
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen(argv[1], "w");
fputs("I love you.", fp);
fclose(fp);
return 0;
}
⑥ linux源代码找到了函数定义的头文件那么相应的。c文件去哪里找
头文件并不一定要与.c文件一一对应。一个头文件里的不同函数可以在不同.c文件中定义。
编译器不是直接从.c文件中找的。编译器先将.c文件编译成.o文件,然后当某个.o文件中调用了某个函数而它自身又没有这个函数时,它就会先把这个没有出现的函数记下来,然后到后面链接的.o文件或者.a或者.so文件中找。如果仍然没有找到,编译器就会提示链接错误。
⑦ c编译器可以找出c源程序中所有的语法错误和逻辑错误
错。c编译器可以找出c源程序中所有的语法错误,但并不找逻辑错误,也找不出逻辑错误。因为编译器不可能知道编程者想要做什么事。
⑧ 既然预编译只是起一个声明的作用,为什么不在工程中每个c文件中包含所有的头文件呢这样不是很方便么
预编译的时候会把包含的头文件展开,即把头文件里面的内容展开在当前文件中,如果包含所有头文件,第一会很占空间,因为有些头文件里面的变量(比如有很大的数组或者什么的)在当前这个文件并没有用到;其次很耗时间,因为要一个个去展开;第三,撇开时间和空间消耗不说,可能会存在不同头文件中声明或者定义了同名变量,这样在编译的时候就会报错。但是你却很难找到错误,因为头文件里面的东西你看不见,其次还可能引起一个重复包含的问题,比如头文件A.h包含了B.h,你在当前.c文件中如果#include"A.h" 后又#include"B.h" 的时候就会报错了,因为你重复包含了,当然重复包含可以通过#ifdef#endif机制解决。但是你不能保证每个头文件中都做了这样的操作。
⑨ 关于C语言编译阶段的一些问题
呵呵,找一本好书吧。我不能完全给你写清楚,"sting.h"的拼写已经有人说了。
简单地说,要理解几种文件:
A:源文件:例如汇编(asm)、c语言、cpp
B:目标文件
C:库文件(lib)
D:可执行文件
A经过编译器得到B,若干个B可以经过库管理程序得到C,C也可以通过库管理程序得到B(提取)
若干个B通过链接器可以得到D,但是比如strcmp是出现在C中的,但实际上链接器会到C中提取出strcmp所在的B,然后将这个B放入到你的D中。整过过程是一个求闭包的过程,具体参见《Linker and Loader》。
最后说说.h,其实.h本身并不是必要的,但是它可以减少人们的错误,减少重复的代码。
比如printf,你完全可以不include<stdio.h>,你就自己写上一行:
int printf(...);
然后你后面就是直接使用就好了,但是这样会有很多缺陷,这些缺陷可能只有你深刻地理解C语言本身的缺陷后才能明白,不多说了。