首页 > 代码库 > 第一章 C/C++语言概述 【代码手输一遍】
第一章 C/C++语言概述 【代码手输一遍】
前情提要:如果不涉及面向对象的部分,那么C++语言和C语言的语法90%以上是一样的,只不过略有扩充,用起来更为方便而已。
查看gcc版本:
E:\Program Files\MinGW\bin>gcc -v Reading specs from ./../lib/gcc/mingw32/3.4.5/specs Configured with: ../gcc-3.4.5-20060117-3/configure --with-gcc --with-gnu-ld --wi th-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --dis able-nls --enable-languages=c,c++,f77,ada,objc,java --disable-win32-registry --d isable-shared --enable-sjlj-exceptions --enable-libgcj --disable-java-awt --with out-x --enable-java-gc=boehm --disable-libgcj-debug --enable-interpreter --enabl e-hash-synchronization --enable-libstdcxx-debug Thread model: win32 gcc version 3.4.5 (mingw vista special r3)
所有程序都在gcc 3.4.5下编译运行。
//1.1程序的基本框架 //gcc warning:return type of “main” is not “int” #include "stdio.h" int main(){ printf("hello world\n"); return 0; } //1.3 C/C++语言的数据类型 //说明数据类型之间的自动转换 int main(){ int n1=1378; short n2; char c=‘a‘; double d1=7.809; double d2; n2=c;//n2 becaming 97 printf("c=%c,n2=%d\n",c,n2); c=n1; //char型变量只有一个字节,int型为两个字节 //1387十六进制为562,char型的c只得到了62,变成十进制即为98 //故输出c=b printf("c=%c,n1=%d\n",c,n1); n1=d1; //n1变为7 printf("n1=%d\n",n1); d2 = n1; printf("d2=%f\n",d2); return 0; } //1.4常量 #define MAPLENGTH 100 #define MAPWIDTH 80 int main(){ int mapSize; mapSize=MAPLENGTH*MAPWIDTH; printf("the map size is %d\n",mapSize); } //1.5 运算符和表达式 //算术运算符之除法运算符 int main(){ int a=10; int b=3; double d=a/b; printf("%f\n",d); d=5/2; printf("%f\n",d); d=5/2.0; printf("%f\n",d); d=(double)a/b; printf("%f\n",d); return 0; } //1.5 运算符和表达式 //算术运算符之自增自减运算符 int main(){ int n1,n2=5; n2++; ++n2; n1=n2++; n1=++n2; printf("n1=%d,n2=%d\n",n1,n2); } //1.5 运算符和表达式 //位运算符之左移运算符 int main(){ int n1=15; short n2=15; unsigned short n3=15; unsigned char c=15; n1<<=15; n2<<=15; n3<<=15; c<<=6; printf("n1=%x,n2=%d,n3=%d,c=%x,c<<4=%d",n1,n2,n3,c,c<<4); return 0; } //1.5 运算符和表达式 //位运算符之右移运算符 #include "stdio.h" int main(){ int n1=15; short n2=-15; unsigned short n3=0xffe0; unsigned char c=15; n1=n1>>2; n2>>=3; n3>>=4; c>>=3; printf("n1=%x,n2=%d,n3=%x,c=%x",n1,n2,n3,c); return 0; } //1.9 函数 #include "stdio.h" int multiple(int x,int y); //函数声明 int main(){ int a=0,b=0; scanf("%d%d",&a,&b); printf("%d\n",multiple(a,b)); return 0; } int multiple(int x,int y) return x*y; } //1.12 数组 //我擦,输入100个参数,有没有搞错啊 #include "stdio.h" #define MAX_NUM 100 int main(){ int i,j; int an[MAX_NUM]; //下面输入100个整数 for(i=0;i<MAX_NUM;i++){ scanf("%d",&an[i]); } //排序 for(i=0;i<MAX_NUM-1;i++){ int nTmpMin=i; for(j=i;j<MAX_NUM;j++){ if(an[j]<an[nTmpMin]) nTmpMin=j; } //置换 int temp=an[i]; an[i]=an[nTmpMin]; an[nTmpMin]=temp; } //输出排序之后的元素 for(i=0;i<MAX_NUM;i++){ printf("%d\n",an[i]); } return 0; } //-------------------------------------- //1.13 字符串 //字符串常量&字符串变量,字符串变量包含\0结尾 #include "stdio.h" #include "string.h" int main(){ char szTitle[]="Prison Break"; char szHero[100]="Michael Scofield"; char szPrisonName[100]; char szResponse[100]; printf("what is the name of the Prison Break in %s\n",szTitle); //用scanf输入字符串不能含有空格,可用gets取代之 scanf("%s",szPrisonName); //int strcmp(const char *s1,const char *s2) 比较字符串s1与s2的大小,并返回s1-s2 if(strcmp(szPrisonName,"Fox-River")==0){ printf("Yeah! Do you love %s?\n",szHero); } else{ strcpy(szResponse,"it seems you have‘t watched it!\n"); printf(szResponse); } szTitle[0]=‘t‘; szTitle[3]=0;//等效于szTitle[3]=‘\0‘ printf(szTitle); return 0; }
指针一般规律:若有定义T *p;不论T是什么类型,sizeof(T *)的值都是4.因为指针表示的是地址,而当前流行的cpu内存寻址范围一般都是4GB即2^32,所以一个地址正好用32位,即4个字节表示。
tip1,不同类型的指针,若不经过强制类型转换,是不能互相赋值的,
eg. pn=(int *)p;
tip2,两个类型为T的指针相减的意义:p1-p2=(地址p1-地址p2)/sizeof(T);
tip3,指针和整数相加的定义:n+p意为,地址p+nXsizeof(T);
//1.14 指针 #include "stdio.h" int main(){ int *pn1,*pn2; char *pc1,*pc2; int n=4; pn1=(int *)100; pn2=(int *)200; printf("%d\n",pn2-pn1);//输出25,因为(200-100)/sizeof(int)=100/4=25 pc1=(char *)pn1;//pc1地址为100 pc2=(char *)pn2; printf("%d\n",pc1-pc2);//(100-200)/sizeof(char)=-100 printf("%d\n",(pn2+n)-pn1); int *pn3=pn2+n; printf("%d\n",pn3-pn1); printf("%d",(pc2-10)-pc1); return 0; } //1.14 指针 //指针和数组 #include "stdio.h" int main(){ int i,an[200]; int *p; p=an; *p=10; *(p+1)=20; p[0]=30; p[4]=40; for(i=0;i<10;i++)//循环赋值 *(p+i)=i; p++; printf("%d\n",p[0]); p=an+6; printf("%d\n",*p); return 0; } //1.14 指针 //bubble sort #include "stdio.h" void BubbleSort(int *pa,int nNum){ int i,j;//在for中定义i,j在gcc下会报错:loop initial declaration used outside c99 mode for(i=nNum-1;i>0;i--){ for(j=0;j<i;j++){ if(pa[j]>pa[i]){ int temp=pa[j]; pa[j]=pa[i]; pa[i]=temp; } } } } #define NUM 5 int main(){ int an[NUM]={5,4,8,2,1}; BubbleSort(an,NUM); int i; for(i=0;i<NUM;i++){ printf("%d\n",an[i]); } return 0; } //1.14 指针 //字符串和指针 #include "stdio.h" #include "string.h" int main(){ char *p="Tom\n"; char szName[20]; char *pName=szName; scanf("%s",pName); printf(p); printf("Name is %s",pName); return 0; }
tip,void指针:主要用于内存复制,将内存中某一块内容复制到另一块去,标准库函数void *memcpy(void *dest,const void *src,unsigned int n);将地址src开始的n字节内容复制到地址dest,返回值是dest
eg. memcpy(a2,a1,10*sizeof(int));
//1.14 指针 //1.14.8 函数指针定义形式:类型名(* 指针变量名)(参数类型1,参数类型2,···); #include "stdio.h" void PrintMin(int a,int b){ if(a<b) printf("%d",a); else printf("%d",b); } int main(){ void (*pf)(int ,int );//定义函数指针pf int x=4,y=5; pf=PrintMin; pf(x,y); return 0; } //1.14 指针 /* 1.14.8 C/C++中有一个快速排序的标准库函数qsort,使用该函数可对任何类型一维数组排序 void qsort(void *base,int nele,unsigned int width, int (*pfCompare)(const void *,const void *)); qsort函数用法规定,“比较函数”原型应该是:int 函数名(const void *elem1,const void *elem2); 自主设置比较规则,*elem1要排在*elem2前面,则函数返回值必须为负整数; 无所谓,则返回值为0; 后面,则返回值必须为正整数; */ #include "stdio.h" #include "stdlib.h" int MyCompare(const void *elem1,const void *elem2){ unsigned int *p1,*p2; p1=(unsigned int *) elem1; p2=(unsigned int *) elem2; return (*p1%10)-(*p2%10);//按个位数字大小来排序 } #define NUM 5 int main(){ unsigned int an[NUM]={8,123,11,10,4}; qsort(an,NUM,sizeof(unsigned int),MyCompare); int i; for(i=0;i<NUM;i++){ printf("%d, ",an[i]); } return 0; }
指针tip:1.14.9 指针和动态内存分配,1.14.10 误用无效指针
//1.15 结构体 /* tip 结构体定义一定是以分号结束的, struct Student { ...}; Student stu1,stu2; 等价于: struct Student { ...} stu1,stu2; */ #include "stdio.h" #include "string.h" #include "stdlib.h" #define NUM 4 struct Student { unsigned ID; char szName[20]; float fGPA; }; Student MyClass[NUM]={ {1234,"Tom",3.78}, {1238,"Jack",3.25}, {1232,"Mary",4.00}, {1234,"Jone",2.78} }; int CompareID(const void *elem1,const void *elem2){ Student *p1=(Student *) elem1; Student *p2=(Student *) elem2; return ps1.ID-ps2.ID; } int CompareName(const void *elem1,const void *elem2){ Student *p1=(Student *) elem1; Student *p2=(Student *) elem2; return strcmp(ps1.szName,ps2.szName); } int main(){ int i; qsort(MyClass,NUM,sizeof(Student),CompareID); for(i=0;i<NUM;i++){ printf("%s",MyClass[i].szName); printf("\n"); } qsort(MyClass,NUM,sizeof(Student),CompareName); for(i=0;i<NUM;i++){ printf("%s",MyClass[i].szName); printf("\n"); } return 0; }
P62的代码1.15结构体真是好奇怪,看不出为什么错。。。
Mark:小工具,在线程序编译器http://codepad.org调试结果如下:
Line 19: error: expected ‘=‘, ‘,‘, ‘;‘, ‘asm‘ or ‘__attribute__‘ before ‘MyClass‘ 以下略
本地调错信息如下
---------- gcc编译并生成 ----------
sheldon.c:19: error: syntax error before "MyClass"
以下略
问题:明明定义了Student结构体,怎么又说“Student”未声明呢???
Answer:感谢@斯雷波 的关注和解答,以上代码修改两处后可在C++编译环境调试通过。
26、27行修改*p1 *p2为*ps1 *ps2【打错了】,28行修改点号为箭头;
31到33行做类似修改;
若不修改点号为箭头,codepad报错如下
In function ‘int CompareName(const void*, const void*)‘:
Line 33: error: request for member ‘szName‘ in ‘ps1‘, which is of non-class type ‘Student*‘
compilation terminated due to -Wfatal-errors.
在codepad设置为C++语言或者使用VC++6.0都可以调试通过,本地gcc始终对19行报错 error: syntax error before "MyClass";
Tip:28行的修改参考C中指针中点与箭头区别
在c++中I如果是对象,就可以通过"."来调用I中的成员变量。
如果I是指针的话,就不能通过"."来调用,而只能使用"->"来调用。
在C语言中不存在对象的概念。
这种情况的出现是因为使用了结构,例如
struct CandyBar{
float weight;
int calorie;
};
在程序中
CandyBar snack={
2.3,
350
};
我们就可以用snack.weight来取得结构中的值。
这时是不能使用"->"来调用的,"->"符号指针对指针来说的。
如下情况可以使用"->"
CandyBar* bird;
bird->weight=2.33;
此时bird为一个CandyBar结构的地址指针。所以可以使用"->",而此时就不能使用
"."来操作。因为"." "相当于"对象的成员调用。