命令行, <sublime class="log_commands"></sublime>
if(x == (pow(a,3) + pow(b,3) + pow(c,3))){
printf("%4d \n", x);
} //必须== ( 有括号把右侧项包裹
6_11 迭代法平方根e
6_12牛顿法求方程根
6_13二分法求fangchenggen
6_1 最大公约数,最小公倍数
segment fault。 scanf 没加 & 。数组越界。循环错误
7_1 素数
8_8 char num = 48 + 9int = ‘9’
10_4 传递float *p
10_5 一圈,123报数,剩下的一个
常用库函数
0.1 <stdio.h>
Break 跳出当前层循环
- fopen
- int feof(FILE *stream)
- void rewind(FILEF * stream)
- 将文件 内部的 位置指针 ,重新指向开头,等同于fseek(0)
- putchar()
- fread()
- purw()
- fseek()
定义函数:int fseek(FILE * stream, long offset, int whence);
- 欲将读写位置移动到文件开头时:fseek(FILE *stream, 0, SEEK_SET);
- 欲将读写位置移动到文件尾时:fseek(FILE *stream, 0, 0SEEK_END);
- int printf(const char *format, ....)
- strlen(s)
unsigned int strlen (char *s);
【参数说明】s为指定的字符串。
strlen()用来计算指定的字符串s 的长度,不包括结束字符"\0"。
static char s[20] = "computer";
-
scanf() 为何有的变量加& 有的不加?
因为char str[10] ,一个数组,str是内存段头地址
fscanf()
%[*][width][length]specifier
;char *fgets(char *buf, int bufsize, FILE *stream);获取一行。
如果使用fgets()读取某个文件,第一次读取的bufsize为5,而文件的第一行有10个字符(算上'\n'),那么读取文件的指针会偏移至当前读取完的这个字符之后的位置。也就是第二次再用fgets()读取文件的时候,则会继续读取其后的字符。而,如果使用fgets() 读取文件的时候bufsize大于该行的字符总数加2(多出来的两个,一个保存文件本身的'\n'换行,一个保存字符串本身的结束标识'\0'),文件并不会继续读下去,仅仅只是这一行读取完,随后指向文件的指针会自动偏移至下一行
例:
如果一个文件的当前位置的文本如下
Love, I Have
Since you can do it.
如果用fgets(str1,6,file1);去读取
则执行后str1 = "Love," ,读取了6-1=5个字符
这个时候再执行fgets(str1,20,file1)则执行后str1 = " I Have\n"
而如果
fgets(str1,23,file1);
则执行str1="Love ,I Have",读取了一行(包括行尾的'\n',并自动加上字符串结束符'\0'),当前文件位置移至下一行,虽然23大于当前行上字符总和,可是不会继续到下一行。而下一次调用fgets()继续读取的时候是从下一行开始读。
- strstr()
strstr()函数用来检索子串在字符串中首次出现的位置,其原型为:
char *strstr( char *str, char * substr );【参数说明】str为要检索的字符串,substr为要检索的子串。
【返回值】返回字符串str中第一次出现子串substr的地址;如果没有检索到子串,则返回NULL。
#include<stdio.h> #include<string.h> int main(){ // 也可以改成 char str[] = "http://see.xidian.edu.cn/cpp/u/xitong/"; char *str = "http://see.xidian.edu.cn/cpp/u/xitong/"; char *substr = "see"; char *s = strstr(str, substr); printf("%s\n", s); return 0; }
- Strcmp strcpy
#include <string.h> main(){ char *a = "aBcDeF"; char *b = "AbCdEf"; char *c = "aacdef"; char *d = "aBcDeF"; printf("strcmp(a, b) : %d\n", strcmp(a, b)); printf("strcmp(a, c) : %d\n", strcmp(a, c)); printf("strcmp(a, d) : %d\n", strcmp(a, d)); }
char str1[15]; char str2[15]; int ret; strcpy(str1, "abcdef"); strcpy(str2, "ABCDEF");
10的n次方可以表示为pow(10, n)
1数据类型
Ctrl + Shift +V --------粘贴过程中保持缩进
1.1 整数类型
(Int)强制类型转换
- char 1 -128-127 / 0-255
- unsigned char 1 0-255
- int 2or4 -32768~32767
- short 2 -32768~32767
- long 4 -2147483648~2147483647
1.2浮点类型
- float 4 6位小数
- double 8 15位小数
- long double 16 19位小数
#include <stdio.h>
#include <float.h>
int main(){
printf("float 存储最大字节数 : %lu \n", sizeof(float));
printf("float 最小值:%E \n" , FLT_MIN);
printf("float 最大值:%E \n",FLT_MAX);
printf("精度值: %d \n", FLT_DIG);
return 0;
}/
- 如果I为整型变量,f为float型变量,c表达式'a'+I*f的类型为
- 即使是两个float,都化成double,float的数据在运算时一律转化成双精度模型
-
1.3 void类型
- void exit(int status);
- int rand(void);
- 指针指向void:
- 类型为void * 的指针,代表对象的地址,而不是类型。
- 例如:void *malloc(size_tsize); 反悔指向void的指针,可以转换为任何数据类型
1.4 前缀
0X 十六进制
0 8⃣️进制
后缀
ULul
2 变量 & 常量
- 静态局部变量 在静态存储区 分配存储单元
- 'A' 和 "A" 都是字符串常量
- 'a' 知识编写整数的另一种方法
- "a" 只是编写一个有 双引号之间字符 和 一个附加 二进制为0的字符 所
- 初始化的 一个无名数组的指针 的 一种简短方法
char *S = “\ta\017bc”; //6个字符
已初始化的的全局变量和局部静态变量存放在.data段,未初始化的全局变量和局部静态变量一般存放在.bss段里,前者在生产可执行文件时就分配好内存了,后者在加载时才分配
- 静态外部变量可以赋初值,也可以不付初值
- 静态外部变量的作用与外部变量相同 error
2.1 指针
```python
int p =0;
int p =0;
含义:
1. p指向 的 内存,存放的是 整形数据;
2. 该内存区域只存放了一个数据,跨越的内存区域 为4字节,即p+1的效果是跳过4字节
```python
struct a {
int x1;
short x2;
a *next;
}
- p指向的内存区域依次存放了三种类型的数据,int\short\指针类型
- p指向的内存区域跨越了12个字节,即p+1的效果是跳过了12个字节
- 为何不是10?对齐
const修饰符
const int* p; #整形常量(修饰int
int* const p; #常量指针(修饰p p是指针变量
const int* const p; (
函数与指针
- 指向函数的指针: 可以利用它代替函数名来调用函数。
- 如何定义:由于一个程序中可以用多个函数名相同(重载),因此定义函数指针的时候必须包含函数的参数,这样才能准确的指向。
- int (p)(const char ,int ); 表示p是一个指向函数的指针,返回int
- 若 int* p(const char*,int); 函数的声明,函数名为p,返回一个指向int型的指针.
- int* (p)(const char , int);
-
宏定义
可以引用已经定义了的宏名,可以层层置换
宏名的有效范围定义命令之后到本源文件结束,可以用#define终止宏定义的作用域
-
#define M 5
#define N M+M
枚举类型
- 枚举元素是 常量,不能赋值
- 枚举元素有值,默认从0;enum weekday {sun=7,mon=1,tue,wed,thu,fri,sat}day;
- 可用作判断 > 也可
- 整数,不可直接赋值 枚举变量 。 day = (enum weekday)2;(将顺序号为2的枚举元素赋值给day)
-
Static
最主要有两点用途。
- 让一个变量长期有效,而不管其是在什么地方被申明。比如:
int fun1()
{
static int s_value = 0;
....
}
那么fun1不管在什么地方被调用,当函数退出后,s_value最后的值将一直会被系统保存(相当于一个全局变量),下次s_value再被用到时,也即当fun1()再次被调用时,s_value初始值将是最近被保存过的值(请注意s_value初始化操作只会被执行一次,即上述s_value =0 这个语句)。
2.避免多个文件使用了相同的变量名而导致冲突
比如有多个文件,分别由几个人独立开发的。假定他们在各自的文件中定义相同的“全局”变量名(仅仅指在他们独自的文件中全局),当系统集成时,由于他们使用了名字一样的“全局”变量,导致有难于遇见的问题。解决这个问题方便的做法就是在各自文件中,在相同的全局变量申明前加上static修饰符。这样系统就会为他们分配不同的内存,互不影响了。
当一个进程的全局变量被声明为static之后,它的中文名叫静态全局变量。静态全局变量和其他的全局变量的存储地点并没有区别,都是在.data段(已初始化)或者.bss段(未初始化)内,但是它只在定义它的源文件内有效,其他源文件无法访问它。所以,普通全局变量穿上static外衣后,它就变成了新娘,已心有所属,只能被定义它的源文件(新郎)中的变量或函数访问。
静态局部变量,函数内使用,值保存
3 存储类
3.1 auto存储类
3.2 register存储类
3.3 extern存储类
3.4
4 运算符
~ ,++>(/*+- >>)>== >&& > ||
(2) a||b+c&&b-c
5 函数 & 作用域
5.1 引用方式调用函数
void swap(int *x, int *y){
int temp;
temp = *x;
*x = *y;
*y = temp;
return;
}
#include<stdio.h>
void swap(int *x, int *y);
int main(){
int a = 100;
int b = 200;
swap(&a, &b);
return;
}
6 数组
- 字符数组最后不必是'\0'
6.1 多维数组
6.2 传递数组给函数
- 方式一
void myFunc(int *param){}
- 方式二
void myFunc(int param[10]){}
- 方式三
void myFunc(int param[]){}
实例
double getAverage(int arr[], int size){
int i;
double avg;
double sum;
for(i = 0; i<size; ++i){
sum += arr[i];
}
avg = sum / size;
return avg;
}
#include<stdio.h>
double getAverage(int arr[],int size);
int main(){
int balance[5] = {1,2,3,4};
double avg = getAverage(balance , 4);
return 0;
}
不管是
int intArr[6]
还是int intArr[]
都不会创建一个数组出来,编译器也不会为它们分配内存,实际的数组是不存在的,它们最终还是会转换为int *intArr
这样的指针。这就意味着,两种形式都不能将数组的所有元素“一股脑”传递进来,大家还得规规矩矩使用数组指针,所以在函数内不可能知道数组的大小必须传递进来。
用函数做参数时,必须在主调函数和被盗函数中分别定义数组?
型参数组长度可以大于实参数组长度
数组名做参数属于值传递
6.2.传递二维数组给函数
6.3 从函数返回数组
6.4 指向数组的指针
Double *p;
Double balance[10];
p= balance
7 指针
8 字符串
9 结构体
#include <stdio.h>
struct m{
int x;
int *y;
}*p;
int a[4]={11,22,33,44};
struct m b[4] = {55,&a[2],66,&a[0],77,&a[1]};
int main (){
p= b;
printf("%d \n", ++p->x); // ->优先级大于++
printf("%d \n",(++p)->x);
printf("%d \n", ++(*p->y)); // *的优先级高于->
return 0;
}
10 共用体(
11 位域(
12 typedef
13 输入 & 输出
13.1 scarf & gets
Scanf(%c) 时。会吧换行符接受
scanf %s:当遇到回车,空格和tab键会自动在字符串后面添加'\0',但是回车,空格和tab键仍会留在输入的缓冲区中。要处理。
gets:可接受回车键之前输入的所有字符,并用'\n'替代 '\0'.回车键不会留在输入缓冲区中。
13.2 printf(%s) puts()
puts只是多个换行
%c 字符
%d 有符号十进制整数
%ld是按长整型输出,长度是整型的2倍32位,%e %E 使用eE的科学计数法
%x %X 无符号十六进制 (大小写字母)
%o 8进制
unsigned a,b,x
int n;
a=0x763;
n=6;
b=a<<(12-n);
x=(a>>n-2)^b; //+,-,的优先级比<<,>>高。
printf(“\n b=%x, \n x=%x”,b,x);
%2d 结果十进制,长度为2 ,右对齐,不够补空格,多了以实际长度输出
比如结果是1,输出:(空格)1
结果为123(长度大于等于2):输出:123
补充:
%-2d 左对齐,其余同上
%.2d从执行效果来看,和% 02d一样
%04d,输出4位(十进制),不足在前面补0,如 123-》0123
M %md 以宽度m输出整型数,不足m时,左补空格
0m %0md 以宽度m输出整型数,不足m时,左补零
m,n %m.nf 以宽度m输出实型小数,小数位为n位double i = 12.3,
printf("%2f",i,a ) ;
输出:12.300000
printf("%2.1f",i,a ) ;
输出:12.3
14 文件读写
FILE *fopen( const char *filename, const char *mode);
r 允许读取,
r+ 允许读写,文件必须存在。2000——1
rb打开二进制文件,允许读写。
w 允许写入,如果与已存在的文件相同,清空重写
w+ 允许读写, 创建空文件。
a 允许写入,追加内容
a+ 允许读写,开头读,追加
int fclose( FILE *fp);
成功返回0
错误返回EOF
实际上,清空缓冲区中数据, 关闭文件,并释放该文件所有内存
- 使用flcose 关闭文件时,先写缓冲区到文件,再释放指针。
fread()函数用于从文件流中读取数据,其原型为:
size_t fread(void *buffer, size_t size, size_t count, FILE * stream);
【参数】buffer为接收数据的地址,size为一个单元的大小,count为单元个数,stream为文件流。
fread() 和 fwrite() 一般用于二进制文件的输入输出,ASCII文件还是不要考虑了。
Dangling pointer & Wild pointer
void func()
{
char *dp = malloc(A_CONST);
/* ... */
free(dp); /* dp now becomes a dangling pointer */
dp = NULL; /* dp is no longer dangling */
/* ... */
}
and the wild pointer is the one not initialized
How to avoid ?
void safefree(void **pp)
{
if (pp != NULL) { /* safety check */
free(*pp); /* deallocate chunk, note that free(NULL) is valid */
*pp = NULL; /* reset original pointer */
}
}
int f(int i)
{
char *p = NULL, *p2;
p = (char *)malloc(1000); /* get a chunk */
p2 = p; /* copy the pointer */
/* use the chunk here */
safefree(&p); /* safety freeing; does not affect p2 variable */
safefree(&p); /* this second call won't fail */
char c = *p2; /* p2 is still a dangling pointer, so this is undefined behavior. */
}
malloc() 相关概念
- (参数) 以Byte记
- 函数执行完后该块内存并未初始化
- 成功返回内存块地址
- 返回类型是void* ,意思是反悔指针类型未知,所以要进行强制类型转换
char *ch = (char *)malloc(10);
动态内存分配:
#include <stdio.h> // printf, scanf, NULL
#include <stdlib.h> // malloc free rand symtem
int main(){
int i,n;
char *buffer;
printf("请输入字符串的长度:");
scanf("%d", $i);
buffer = (char *)malloc(i+1); //字符串结尾有 \0
if(buffer == null) exit(1); // 检测是否分配成功
//随机生成字串
for(n = 0; n<i; n++){
buffer[n] = rand()%26 + 'a';
}
buffer[i+1] = '\0';
printf("随机生成的字符串为: %s \n", buffer);
free(buffer);
system("pause");
return 0;
}
int arr[]= {11,22,33,44,55};
数组名可以认为是一个指针,它指向数组的第0个元素
如何以指针的方式遍历数组
#include<stdio.h>
int main(){
int arr[] = {11,22,33,44,55};
int len = sizeof(arr) / sizeof(int);
int i;
for(i= 0;i<len;i++){
print("%d", *(arr+i));
}
printf("\n");
return 0;
}
- sizeof() 数组占用字节数
- sizeof(int) 数组元素占用字节数
- arr 是int* 类型的指针 , 每次加 1,即 增加sizeof(int)
- *(arr+i)
指向数组的指针
int arr[] = {11,22,33,44}
int *p = arr;
* arr本身就是一个指针, 可以直接赋值给 指针变
* 也可 int *p = &arr[0];
数组指针指向的是数组中的一个具体元素,不是整个数组,所以数组指针的类型和数组元素的类型有关
阿斯顿发
int *p = arr, len = sizeof(arr)/ sizeof(int);
// 编译器并不知道 p是个数组,所以不能 sizeof(p) 获得len
下标访问
p是指向数组arr的指针, 可以 p[i];
使用指针
*(p+i)
#include <stdio.h>
int main(){
int arr[] = {11,22,33,44};
int i, *p = arr, len = sizeof(arr)/sizeof(int);
for(i= 0; i< len; i++){
printf("%d", *p++);
}
print("\n");
return 0;
}
// eual *(p++)
// wrong *(arr++)
main函数的参数
main() 可选两个参数,命令行下传入, argc 是安参数十几个数自动赋予。
main(int argc,char *argv){
while(argc-- >1)
{
printf("%s", *argv++);
}
}
多维数组的地址##
int a[3][4] = {{0,1,2,3,4},{4,5,6,7},{8,9,10,11}}
可以分成3个数组,
然而是 a[0], a[1], a[2]
a是 a[0]的首地址
a, a[0], *(a+0), *a , &a[0][0] 是相等的
a[1] 是第二个一位数组的数组名, 和首地址
&a[i] 不能被理解为a[i]的地址, 因为不存在元素a[i]
a[0] 可以看成是a[0]+0 , 是一维数组a[0]的 0号元素的首地址。a[0]+1 是1号元素首地址
#include <stdio.h>
int main(){
int a[3][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};
//printf("%d", a);
//printf("%d", &a[2]);
printf("%d \n", *(a[0]+2));
printf("%d \n", *(*(a+1)));
printf("%d \n", **(a+2) );
printf("%d,%d \n",*(a[1]+1),*(*(a+1)+1));
return 0;
}