前情提要:如果不涉及面向对象的部分,那么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结构的地址指针。所以可以使用"->",而此时就不能使用
"."来操作。因为"." "相当于"对象的成员调用。