在输入数据是,需要原样输入字符:x=9.5
在使用函数之前应该先声明,事先通知编译器该函数的类型:换句话说,一个声明即是描述一个函数的接口。声明至少应指明函数返回值的类型。
int sum(int a, int b) {
return a + b;
}
int main()
{
int c = sum(1, 2);
return 0;
}
//函数声明
int sum(int a, int b);
int main()
{
int c = sum(1, 2);
return 0;
}
// 函数定义
int sum(int a, int b) {
return a + b;
}
或者
int main()
{
//函数声明
int sum(int a, int b);
int c = sum(1, 2);
return 0;
}
// 函数定义
int sum(int a, int b) {
return a + b;
}
#include
#include "stdio.h":如果使用"",则编译程序首先到当前工作文件夹寻找被包含的文件,若找不到,再到系统include文件夹中查找文件,一般适用于编程者自己的包含文件,必要时可以在文件名前添加所在路径。
常用标准头文件:
a=i++ :1. a=i; 2. i=i+1;
a=++i :1. i=i+1; 2. a=i;
.cpp --> .obj :生成二进制代码表示的目标程序
.obj --> .exe :与编程环境提供的库函数进行链接
原文链接:https://blog.csdn.net/huangfei711/article/details/51220382
step into:单步执行,遇到子函数就进入并且继续单步执行(简而言之,进入子函数);
step over:在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个执行完再停止,也就是把子函数整个作为一步。有一点,经过我们简单的调试,在不存在子函数的情况下是和step into效果一样的(简而言之,越过子函数,但子函数会执行)。
step out:当单步执行到子函数内时,用step out就可以执行完子函数余下部分,并返回到上一层函数。
6指的是输出x共占6位(包括空格,小数点),1表示一位小数:如x=30 ,y=-1.1输出为30 -1.1(-1.1前面有两个空格);
当总位数不够时,不会截断数字而是直接连接:如printf("%d%1.1f",x ,y),其中x=30 ,y=-3.1输出为30-3.1(-1.1前面有两个空格)
原文转载自:https://blog.csdn.net/weixin_36340947/article/details/77920152
1. char、short、int、long、bool 基本类型都可以用于switch语句。
2. float、double都不能用于switch语句。
3. enum类型,即枚举类型可以用于switch语句。
4. 所有类型的对象都不能用于switch语句。
5. 字符串也不能用于switch语句。
6.布尔类型是可以按整数形式转换的。
case标签必须是整型常量表达式
请记住整型常量这四个字,不满足这个特性的不能作为case值,编译会报错。这也决定了switch的参数必须是整型的。
整型,意味着浮点数是不合法的,如case 3.14:不可以;常量,意味着变量是不合法的,如case ival: ival不能是变量。
(1)C++中的const int,注意仅限于C++中的const,C中的const是只读变量,不是常量;
(2)单个字符,如case 'a': 是合法的,因为文字字符是常量,被转成ASCII码,为整型;
(3)使用#define定义的整型,#define定义的一般为常量,比如#define pi 3.14,但是也必须是整型才可以;
(4)使用enum定义的枚举成员。因为枚举成员是const的,且为整型。如果不手动指定枚举值,则默认枚举值为从0开始,依次加
函数被调用时,系统自动为其局部变量分配存储单元;一旦函数调用结束,所有分配给局部变量的单元由系统自动回收。
自动变量的定义形式:
auto 类型名 变量名;
eg. auto int x, y;
在自动变量定义时,auto可以省略,其形式与定义的普通变量完全相同。也就是说局部变量就是自动变量。
自动变量如果没有赋初值,其存储单元中将是随机值。
C语言把保存所有变量的数据区分为动态存储区和静态存储区。
动态存储区: 使用堆栈来管理,适合函数动态分配与回收存储单元。
静态存储区:用于存放全局变量和静态变量。
在静态存储区中,除了全局变量,还有一种特殊的局部变量——静态局部变量。它不会像普通局部变量那样因为函数调用结束而被系统回收,它的生存周期会持续到程序结束。由于存储单元被保留,一旦含有该静态局部变量的函数被再次调用,则静态局部变量会被重新激活,上一次函数调用后值仍然保存着,可供本次调用继续使用。
定义格式:static 类型名 变量名
如果定义时,没有赋初值,系统自动赋 0。并且赋初值只在函数第一次调用时起作用,以后调用都按前一次调用保留的值使用。这是因为静态局部变量的生存周期始于函数的第一次调用,贯穿于整个程序。当函数第一次调用时,静态局部变量的内存单元得已分配,赋以初值,而函数再次调用时,此静态局部变量的单元已经存在,计算机不会再次为它分配单元,赋初值也不会再发生。但静态局部变量受变量作用范围限制,不能作用于其他函数(包括主函数)。
#include
#include
int main(void)
{
for (int i = 1; i < 6; i++)
{
printf("%d\n", factorial(i));
}
system("pause");
}
int factorial(int n)
{
static int f = 1;
f = f * n;
return f;
}
结果如下:
C语言中的字符具有数值特征,不但可以写成字符常量的形式,还可以用相应的ASCII码表示,即可以用整数来表示字符。如:设ch是字符变量,则 ch = 'A' 和 ch = 65 等价。字符可以像整数一样参加运算,此时相当于对字符的ASCII码进行运算。
\\ | 反斜杠 |
\' | 单引号 |
\'' | 双引号 |
\ddd | 1-3位八进制整数所代表的字符 |
\xhh | 1-2位十六进制整数所代表的字符 |
实数由正负号、数字、字母e或者E组成,e之前要有数据,e之后的指数只能是整数。如:6.02E-27
小写转大写:ch_upper = ch_lower - 'a' + 'A';
大写转小写:ch_lower = ch_upper - 'A' + 'a';
先将两个操作数划位二进制数,然后按位运算
int data[4];
int length;
length = sizeof(data)/sizeof(data[0]);
int a[][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
等价于
int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
但不建议省略行长度。
又名“指针变量”,专门用来存放变量地址的变量。如果一个指针变量的值是另一个变量的地址,则称该指针指向那个变量。&称为地址运算符,如:scanf("%d", &n); 把输入的值存储到变量n所在的内存单元里。&n 表示变量n的内存地址或存储位置。定义指针变量的一般形式:
类型名 *指针变量名;
注意指针变量的类型不是指针变量本身的类型,而是指它所指向的变量的数据类型。
*p 为指针申明符,但指针申明并不是指针的组成部分。如,定义int *p; 说明p是指针变量,而不是*p。
int *p:C语言的写法。这表示 *p是一个int ,这种风格强调的是语法。
int* p:C++的写法。表示 p是一个指向int的指针,p的类型是int*,这种风格强调的是类型。
int *p;
p = 0;
p = NULL;
第二、三条语句等价,常量NULL在系统文件stdio.h中被定义,其值为0,将他赋值给指针时代表空指针。C语言的空指针不指向任何单元。
注意:不能用数值作为指针变量的初值。eg:int *p = 1000 (x)
&:取地址运算符。&用于给出变量的地址
*:间接访问运算符。用于访问指针所指向的变量。
(*p)++、 *p = *p + 1、 ++*p:p 所指变量+1
p++:p所指的内存单元的下一个
*p++、*(p++):先取*p的值作为表达式的值,再将指针p的值+1,运算后,p不再指向变量a。
eg:
int a;
int *p = &a;
调用函数不能改变实参指针的值,但可以改变指针所指向变量的值。
指针名和数组名都代表内存地址。
指针名是一个变量,而数组名是一个常量。
指针名所代表的地址是可以改变的,而数组一旦被定义后内存空间就被分配,也就是说数组名所代表的地址是不能改变的。
系统在存储一个字符串常量时先给定一个起始地址,该起始地址代表了存放字符串常量首字符的存储单元的地址,称为字符串常量的值。也就是说,字符串常量实质上就是一个指向该字符串首字符的指针常量。eg:字符串“hello”的值是一个地址,从它指定的存储单元开始连续存放该字符串的6个字符。
如果定义一个字符指针接受字符串常量,该指针就指向字符串的首字母。这样,字符数组和字符指针都可以用来处理字符串。
eg:
char sa[] = "array";
char *p = "point"; //字符指针
printf("%s", sa);
printf("%s", p);
调用printf()函数,以%s的格式输出字符串,作为输出参数,数组名sa,指针p和字符串“string”的值都是地址,从该地址所指定的单元开始连续输出其中的内容,直至遇到‘\0'为止。
char sa[] = "Test";
sa = "Hello"; //错误!!!
eg:
char *s;
scanf("%s", &s); //错误!
为了避免引用未赋值的指针所造成的危害,在定义指针时,可先将它的初值置为NULL。
eg:char *s = NULL;
用 gets() 来输入字符,用 puts() 来输出字符。它们在系统文件 stdio.h 中定义。
scanf() 和 gets() 用于字符串的输入时,参数只能是字符型数组名。
scanf() 遇到回车或者空格输入结束;gets() 遇到回车输入结束,用 gets() 函数输入的字符允许带空格。
puts() 函数输出字符后会自动换行。
将字符串s2复制到s1,函数返回s1.
s1 必须是字符串数组基地址,s2 可以是字符串数组名或者字符串常量。
将字符串s2连接到s1后,函数返回s1.
s1 必须是字符串数组基地址,s2 可以是字符串数组名或者字符串常量。
注意:C语言不允许使用 “+” 直接将两个字符串数组连接。
s1, s2 可以是字符串数组名或者字符串常量。
函数返回一个整数(s1==s2,0;s1
字符串比较规则:
1. 从两个字符串的首字符开始比较,依次比较相对应的字符(比较ASCII码),直到结束或遇到不相同的字符为止
2. 若两个字符不相同,则用第一个不同的字符相减,差为正,则s1 > s2;差为负,则s1 < s2
由于字符串并没有显示地给出有效字符的个数,所以可以通过strlen(s)函数给出有效字符的个数,或者用一下代码:
#include
int main(void)
{
char p[10] = "Happy";
int i = 0;
for (i = 0; p[i] != '\0'; i++);
printf("%d", i);
}
注意上述函数使用前要引入string.h头文件
eg:p = (int *)calloc(n, sizeof(int)) p = (int *)malloc(n * sizeof(int))
动态内存申请得到的是一个没有名字、只有首地址的连续存储空间,相当于一个无名的一维数组。
引用:https://zhidao.baidu.com/question/40468782.html
malloc和calloc函数在参数个数、初始化内存空间、函数返回值上有区别:
1、参数个数上的区别:
malloc函数:malloc(size_t size)函数有一个参数,即要分配的内存空间的大小。
calloc函数:calloc(size_t numElements,size_t sizeOfElement)有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小。
2、初始化内存空间上的区别:
malloc函数:不能初始化所分配的内存空间,在动态分配完内存后,里边数据是随机的垃圾数据。
calloc函数:能初始化所分配的内存空间,在动态分配完内存后,自动初始化该内存空间为零。
3、函数返回值上的区别:
malloc函数:函数返回值是一个对象。
calloc函数:函数返回值是一个数组。
void free(void *p)
void *realloc(void *p, unsigned size)
更改以前的存储分配,并保证原来p指向的存储块内容不变,若分配失败,返回NULL。如果新分配的 size 比原来的小,则内容为原块前size范围内的数据。如果分配成功,原存储块的内容就可能改变了,因此不允许再通过p去使用它。
因为使用realloc(),数据发生了移动,那么所记录的原来的内存地址p所指向的内存空间实际上已经放回到堆上了,这样就会产生p指针的指针悬挂,即指针指向了一块没有分配给用户使用的内存,如果再用p指针进行操作就可能发生意想不到的问题。
可以这样避免:p = (char *)realloc(p, 256);
struct point{
double x;
double y;
}s1, s2;
其中s1,s2是结构变量,该段代码的定义方式相当于
struct point{
double x;
double y;
};
struct point s1;
struct point s2;
指的是在定义结构变量时省略结构名。
struct{
double x;
double y;
}s1, s2;
由于没有给出结构名,在此定义语句后面无法再定义这个类型的其他结构变量。也就是说除了s1,s2,不能再定义别的变量了,除非把定义过程重新再写一遍。
eg: s1 = s2;
赋值时,相当于将赋值符号右边结构变量的每一个成员的值都赋值给了左边结构变量中相应的成员。
结构指针的值实际上是结构变量的首地址,即第一个成员的地址。
可通过结构指针变量p间接访问它所指向的结构变量中的各个成员。
struct point{
double x;
double y;
};
struct point s1 = {100, 100};
struct point *p;
p = &s1;
//两种通过结构指针访问结构变量成员的方式
(*p).x = 120;
p->x = 120;
->指向运算符:访问指针指向的结构成员。
若函数参数为结构变量时,在参数传递时,实际上是把实参结构中的每一个成员值传递给形参结构的成员。而当构成员数量众多(如结构数组形式)时,使用结构指针作为函数参数只要传递一个地址值,因此能够极大的提高参数传递的效率。
又称宏替换,格式:#define 宏名 宏定义字符串
eg:#define PI 3.14
C程序的编译处理用于把每一条C语句用若干机器指令来实现,生成目标程序。由于#define等编译预处理指令不是C语句,不能被编译程序翻译,需要在真正编译之前做一个预处理,解释完编译预处理指令,从而把预处理指令转换成相应的C程序段,最终成为由纯粹的C语句构成的程序,经编译最后的得到目标代码。
如果程序中包含多个程序文件模块,既可以通过外部变量的声明,是全局变量的作用范围扩展到其他文件模块;也可以通过定义静态全局变量,将其作用范围仅限制在一个文件模块中。
全局变量只能在某个模块中定义一次,如果其他模块要使用该全局变量,需要通过外部变量的声明,当程序连接时会统一指向全局变量定义的模块。
外部变量的声明格式:extern 变量名;
它只起说明作用,不分配存储单元,对应的存储单元在全局变量定义时分配。
如果整个程序只有一个文件模块,静态全局变量与一般的全局变量作用完全相同。当程序由多个文件模块构成时,静态全局变量有特殊作用,用于限制全局变量域的扩展。
C语言的静态全局变量可以把变量的作用仅限于当前文件模块,即使其他文件模块使用外部变量声明,也不能使用该变量。
如果一个程序包含多个文件模块,要实现在一个模块中调用另一个模块中的函数时,就需要对函数进行外部声明。
格式:extern 函数类型 函数名(参数);
一般情况下,关键字extern可以省略。编译程序如果在当前模块文件中找不到函数定义体,自动认为该函数是外部函数。
为了避免个文件模块间函数的互相干扰,C语言也允许把函数定义成静态的,以便把函数的适用范围限制在文件模块内,即使其他文件模块有同名的函数定义,相互之间也没有任何关联,增加了模块的独立性。
定义格式:static 函数类型 函数名(参数);
指针数组的各个元素都是指针类型,用于存放内存地址。
格式:类型名 *数组名[数组长度]
eg: char *color[5];
其中color[i]中存放的是字符串的首地址
printf("%s", color[i]); //输出color[i]所指向的字符串
printf("%x", color[i]); //输出color[i]所指向的字符串的首地址
定义格式:类型名 **变量名;
int a = 10;
int *p = &a;
int **p = &p;
char *color[] = {"red", "yello", "blue"};
数组名color的类型就是二级指针(char**),它代表了数组首元素color[0]的地址。
*(color+k)和color[k]等价。
注意color[0]和*(color[0])是不一样的。color[0]是字符指针,指向字符串"red"。*(color[0])代表该字符串的首字母,即'r'。
C语言主函数main()可以有两个参数用于接收命令行参数。
//test.c
int main(int argc, char *argv[])
{
int k;
for(k = 1; k < argc; k++)
{
printf("%s\n", argv[k]);
}
}
第一个参数是指命令行参数的个数(包括命令);第二个参数用于接收命令行参数。
eg: 一个test.c编译好后的文件为test,用于输出键入的命令行参数
test Hello World
argc = 3 (包括test命令),argv[0]指向命令test,argv[1]指向第一个命令行参数Hello。
结果输出:Hello World
接收函数的入口地址的指针,指向函数。
定义格式:类型名 (*变量名)( 参数类型表 )
int (*funptr)(int,int);
funptr = fun; //fun(x, y)已定义好,将函数fun()的入口地址赋给funptr,funptr就指向函数fun()
fun(3, 5);
(*funptr)(3, 5);
在使用函数指针前,要先对它赋值。赋值时,将一个函数名赋值给函数指针,但该函数必须已定义或声明,且函数返回类型和函数指针的类型要一致。
函数调用中, 函数名或已复制的函数指针也能作为实参,此时,形参就是函数指针,它指向实参所代表函数的入口地址。
#include
#include
#include
#include
int main(void)
{
double calc(double (*funptr)(double), double a, double b);
double f1(double x);
double f2(double x);
double result;
double (*funptr)(double);
result = calc(f1, 0, 1);
printf("f1 result = %f\n", result);
funptr = f2;
result = calc(funptr, 0, 2);
printf("f2 result = %f\n", result);
return 0;
}
double f1(double x)
{
return x * x;
}
double f2(double x)
{
return x * x * x;
}
double calc(double (*funptr)(double), double x1, double x2)
{
return funptr(x2) - funptr(x1);
}
自定义类型不是用来定义一些新的数据类型,而是将C语言中的已有类型(包括一定义过的自定义类型)重新命名,用新的名称代替已有数据类型。
一般形式:typedef 已有类型名 新类型名;
eg:typedef int INTEGER;
则 int i; 等价于 INTEGER i;
一般要求重新定i的类型名用大写。
文件指针是特殊指针,指向的是文件类型结构,他是多项信息的综合体。FILE结构中有一个curp成员,通过 fp->curp 可以指示文件缓冲区中数据存取的位置。C程序只使用文件指针fp,用fp代表文件整体。
文件指针不像以前普通指针那样能进行 fp++ 或 *fp等操作,fp++将意味着指向下一个FILE结构(如果存在的话)。
文件操作具有顺序性的特点,前一个数据取出后,下一次将顺序取出后一个数据,fp->curp会发生变化,但改变是隐含在文件读写操作中的,而不需要在编程时写上 fp->curp++ ,类似这样的操作酱油操作系统在文件读写时自动完成。
fopen("文件名", "打开方式")
注意:定位子目录时,用的“\”需要用"\\"去表示。
打开文件时,即是请求系统分配文件缓冲区。
执行fopen()操作,系统完成以下工作:
文件打开的实质是把磁盘文件与文件缓冲区对应起来,这样后面操作至于要用到文件指针即可。
exit(0)是系统标准函数,作用是关闭所有打开的文件,并终止程序的执行。
fclose(文件指针);
该函数返回一个整数,若为0,则代表正常关闭文件。
关闭文件操作处理强制把缓冲区中的数据写入磁盘外,还将释放文件缓冲区单元和FILE结构,使文件指针与具体文件脱钩。
存取数据均为ASCII码字符文本,使用这两个函数读写文件时,逐个字符地进行文件读写。
ch = fget(fp); //每次调用成功,fp会自动后移一个位置,方便读取下一个字符。用 feof() 判断fp 是否指到了文件末尾
fputc(ch,fp); //函数返回值若写成功为ch,若写文件失败为EOF(符号常量,表示为-1)
while(!feof(fp1))
{
ch = fgetc(fp1);
if(ch!=EOF) fputc(ch, fp2);
}
fputs(s, fp); //s是要写入的字符串,可以是字符数组名,字符型指针变量或字符串常量。若执行成功,返回最后一个字符,若不成功,返回EOF。
fgets(s,n,fp); //s可以是字符数组名或字符指针。n是指定读入的字符个数,最多读入n-1个字符,在读取字符后自动添加一个'\0'
fscanf(fp, "%d%f", &n, &x);
fprintf(fp, "%d%f", n, x);
多用于读写数据块(指定字节数),多用于二进制文件。
fread(buffer, size, count, fp);
fwrite(buffer, size, count, fp);
buffer是一个指针,指的是存放输入/输出数据的首地址,size指的是数据块的字节数,count表示要读写的数据块数。
eg:fread(fa, 4, 5, fp); //从fp所指的文件中,每次读4个字节,连续读5次,送入数组fa中。