%.2f
取小数点后两位 %2d
补齐两位
C初阶1:数组
- 数组指针:指向数组的指针
数组的返回值如果是负数(如-1)是不合法的,可以用来做判断 - 二维数组作为参数,列数需要确定,C语言在二维数组传参的缺陷
因此,二维数组->一维数组:元素下标=现行序号*列元素个数+现列序号
C初阶2:字符串
- 字符串可以整体输入
scanf()
输出printf()
(不需像数组一样遍历)的原因:字符串结尾有\0
,用%s
作为标识符,如果识别到\0就停止
char str[8];
scanf("%7s",str);//%和s之间的数字表示最多允许输入的字符数,为数组长度-1
printf("%s\n",str);
%和s之间的数字表示最多允许输入的字符数,为
数组长度-1
- 如果字符串指针指向字面量,不可以被修改,如:
char* ptr ="Hello World";
- *
ptr ='h';
//错误!!!字符串字面量放在一个不能被修改的地方,用字符串指针修改会出错 - 最好加上
const
,即:const char* ptr="Hello World";
这样如修改可以编译是报错 - 指向字符串数组,可以被修改,如:
char arr[]="Hello World";
char* ptr = arr;
*(ptr+6)='w';//可以修改
char arr[]="hello world"
strlen(arr)=11
//空格算,\0不算const
指定某些变量不可以被修改,主要用在函数参数里
char
可传到const char
可变的可传到不可变的,const char
不能传到char
不可变的不能传到可变的,因为这样传多半是想变(不可以呦!)
C初阶4
- 关于字符串的一些函数
stdio.h中
sprintf
:数据按格式写入字符串
sscanf
:按格式从字符串读取数据
stdlib.h
atof
:字符串转浮点数
atoi
:字符串转整数
atol
:字符串转长整数
string.h
复制
strcpy
:字符串拷贝
strncpy
:指定个数字符串拷贝
连接
strcat
:字符串连接
strncat
:指定个数字符串连接
比较
strcmp
:字符串比较
strncmp
:指定个数字符串比较
查找
strchr
:查找字符串中第一个出现指定字符的位置
strrchr
:查找字符串中最后一个出现指定字符的位置
strstr
:查找字符串中第一个出现指定子串的位置
strtok
:切分字符串
其他
strerror
:获取出错信息
strlen
:获取字符串长度
重要示例:
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
int max(int a,int b){
return a>b?a:b;
}
void MyStrcpy(char* dst,char* src){
int i=0;
for(;'\0'!=src[i];++i){
dst[i]=src[i];
}
dst[i]='\0';
}
void MyStrcat(char* dst,char* src){
int i=0;
while('\0'!=dst[i]) ++i;
int j=0;
while('\0'!=src[j]) dst[i++]=src[j++];
dst[i]='\0';
}
void swap(char* a,char* b){
/*int i=0,j=0;
while('\0'!=a[i]&&'\0'!=b[j]){
char t=a[i];
a[i]=b[j];
b[j]=t;
++i;
++j;
}
if('\0'!=a[i]){
MyStrcat(b,a+i);
a[i]='\0';
}else if('\0'!=b[j]){
MyStrcat(a,b+j);
b[j]='\0';
}*/
while(*a && *b){
char t = *a;
*a = *b;
*b=t;
++a;
++b;
}
if(*a){
MyStrcpy(b,a);
*a ='\0';
}else if(*b){
MyStrcpy(a,b);
*b='\0';
}
/*while('\0'!=a[i]){
b[j++]=a[i++];
}
while('\0'!=b[j]){
a[i++]=b[j++];
}
a[i]=b[j]='\0';}
*/
/*int maxlen = max(strlen(a),strlen(b)+1);
char t[maxlen];
MyStrcpy(t,a);
MyStrcpy(a,b);
MyStrcpy(b,t);*/
}
bool MyStrcmp(char* a,char* b){
while(*a && *b){
if(*a!=*b)return false;
++a;
++b;
}
return '\0'==*a && '\0'== *b;
}
int main(){
char a[30]={'\0'};
scanf("%s",a);
char b[30]={'\0'};
scanf("%s",b);
printf("a:%s b:%s\n",a,b);
swap(a,b);
printf("a:%s b:%s\n",a,b);
MyStrcat(a,b);
printf("a:%s b:%s\n",a,b);
MyStrcmp(a,b)?(printf("一样\n")):(printf("不同\n"));
}
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
int max(int a,int b){
return a>b?a:b;
}
char* MyStrcpy(char* dst,const char* src){
int i=0;
for(;'\0'!=src[i];++i){
dst[i]=src[i];
}
dst[i]='\0';
return dst;
}
char* MyStrcat(char* dst,const char* src){
int i=0;
while('\0'!=dst[i]) ++i;
int j=0;
while('\0'!=src[j]) dst[i++]=src[j++];
dst[i]='\0';
return dst;
}
void swap(char* a,char* b){
/*int i=0,j=0;
while('\0'!=a[i]&&'\0'!=b[j]){
char t=a[i];
a[i]=b[j];
b[j]=t;
++i;
++j;
}
if('\0'!=a[i]){
MyStrcat(b,a+i);
a[i]='\0';
}else if('\0'!=b[j]){
MyStrcat(a,b+j);
b[j]='\0';
}*/
while(*a && *b){
char t = *a;
*a = *b;
*b=t;
++a;
++b;
}
if(*a){
MyStrcpy(b,a);
*a ='\0';
}else if(*b){
MyStrcpy(a,b);
*b='\0';
}
/*while('\0'!=a[i]){
b[j++]=a[i++];
}
while('\0'!=b[j]){
a[i++]=b[j++];
}
a[i]=b[j]='\0';}
*/
/*int maxlen = max(strlen(a),strlen(b)+1);
char t[maxlen];
MyStrcpy(t,a);
MyStrcpy(a,b);
MyStrcpy(b,t);*/
}
bool MyStrcmp(const char* a,const char* b){
while(*a && *b){
if(*a!=*b)return false;
++a;
++b;
}
return '\0'==*a && '\0'== *b;
}
int main(){
const char* s = "abcd";
char sarr[30] = "def";
const char* m=s;
const char arr[]="Hello World";
const char* ptr = arr;
const char* t ="abcd";
MyStrcmp(s,t);
char res[50]={'\0'};
MyStrcpy(res,s);
MyStrcat(res,sarr);
MyStrcat(res,arr);
MyStrcat(res,t);
printf("%s\n",res);
printf("%s\n",MyStrcat(MyStrcat(MyStrcat(MyStrcpy(res,s),sarr),arr),t));
/* char a[30]={'\0'};
scanf("%s",a);
char b[30]={'\0'};
scanf("%s",b);
printf("a:%s b:%s\n",a,b);
swap(a,b);
printf("a:%s b:%s\n",a,b);
MyStrcat(a,b);
printf("a:%s b:%s\n",a,b);
MyStrcmp(a,b)?(printf("一样\n")):(printf("不同\n"));
*/
}
示例1:
int n;
char s[]="123456";
sscanf(s,"%d",&n);//把s按数字(%d)形式读取到n中
sprintf(s,"%d",n/10);把n/10按数字(%d)形式写入到s
printf("%d\n",n);
printf("%s\n",s);
示例2:
char tiangan[] = "甲乙丙丁戊己庚辛壬癸";
char dizhi[]="子丑寅卯辰巳午未申酉戌亥";
//ASCII-->2Byte -->GB2312-->CJK-->Unicode-->UTF-8/UTF-16
for(int i=0;i<10;++i){
printf("%.3s\n",tiangan+i*3);//汉字用UTF-8编码方式是3个字节,一个字符一个字节,所以三个字符表一个汉字,用%.3s
}
for(int i=0;i<60;++i){
printf("%.3s",tiangan+(i%10)*3);
printf("%.3s",dizhi+(i%12)*3);
if(i%10==9){printf("\n");
}
字符串长度不包含\0,字符数组长度包含\0
空字符串 char str[10]="";//str[0]为\0
char str[]=""; //str数组长度为1
char* str =NULL;//指针定义时必须初始化
char str="abcd""1234"//"abcd1234"相邻梁字符串自动连接
C初阶3:进制
八进制(O)010表示8,十六进制(X)0xa表示10;
示例3:
#include<stdio.h>
int main(){
int n;
scanf("%i",&n);//%i 可以输入任何进制
printf("%#d\n",n);//用十进制形式输出
printf("%#o\n",n);//用八进制形式输出
printf("%#x\n",n);//用十六进制形式输出
}
C初阶4:指针
示例:
#include<stdio.h>
int main(){
int arr[] = {2,4,6,8,10};
for(int i=0;i<5;++i){
printf("%p ",&arr[i]);
}
printf("\n");
int* p = arr;
for(int i=0;i<5;++i){
printf("%p ",p+i);//p+1其实是地址往后偏移一个int的字节,即加4个字节
// ~addr(p+i) = addr(p) +sizeof(int)*i
}
printf("\n");
}
-
++
优先级最高,
*p++
//取当前元素值 并指向下一个元素的值
*++p
先p自加,返回p自加后指向的值,//取下一个元素的值
++*p
对p指向的值加1,//把当前元素+1,不改变p的值(地址) -
指针要用在一片连续内存上,常用于数组的连续内存
-
指针类型的大小:
32位~4Byte
,64位~8Byte
printf("%d\n",sizeof ( p ));
-
void*
可以强转成其余类型指针 -
指针类型:
char*
int*
-
指针单位长度:
+-移动的字节数
-
二维指针用来存放指针的地址
int n=10;
int* p=&n;
int** pp=&p;
- 二维指针解引用是指针的值(即地址)
*pp = p;
**pp=n;
- 数组指针:指向数组的指针
int arr[]={1,2,3,4};
int* p=arr;
- 指针数组:指针类型的数组,存放的都是指针(地址)
int* parr = {&arr[0],&arr[1],&arr[2]};
int* parr = {arr,arr+1,arr+2,arr+3};
parr[i]
与*(parr+i)
相同
-
int* *q=parr
;二维指针可以存放指针数组的地址 -
常量指针:
const int* p
*p
是常量不可改,p指向的值不能改,p的值(指向的地址)能改。
值不能改 但指针指向的地址可以改
即:p指向的地址里放的值不可改,不能通过解引用改变指向的值,只能访问指向的值
- 指针常量:
int* const p
p
是常量,p的值不能改,p指向的值可以改。
指向地址不能改值可以改
即:指针指向的地址不能修改
- 常量指针常量:
const int* const p
p
和*p
都是常量,所指地址和值都不可改
小技巧:const离
*
近,就*p
不可改 const离p
近,就p
的值(所指地址)不可改
-
连续定义指针:
int *p,*q;
const int* p,*q;
//p和q指向的值都不可改
int* const p = &n,*q=&m;
//p是指针常量,q只是 指针
int* const p=&n,*const q=&m;
//p,q都是指针常量,指向的地址不可改 -
const char* s2 = "hello world";
字符串指针是字面量,不可改,最好在前面加const
,避免误改发生错误
const char* ss2[] ={"abcdef","1234","999"}
;//字符串类型的指针数组
const char** pp =ss2
//指针数组可以放到二维指针里
0地址为NULL,不可访问,表:指针没有初始化 或 返回指针无效
主函数
#include<stdio.h>
#include<stdlib.h>
//argc:argument count
//argc:argument vector
//func(int arr[]) 等价于~func(int* arr)
//int main(int argc,char* argv[]){} ~ int main(int argc,char** argv){} //char* argv[]就是指针数组,因此可等价于二维指针
int main(int argc,char** argv){
printf("argc:%d\n",argc);
for(int i=0;i<argc;++i){
printf("%d:%s\n",i,argv[i]);
}
//return EXIT_SUCCESS;//返回0
return EXIT_FAILURE; //返回非1
}
执行完程序,紧跟这echo $?可以查看主程序的返回值,返回值为0表示执行成功,非0表示失败。