4 C 语言 数值存储方式 数组
源码 补码 反码
数组定义,初始化,使用,随机数
找最大数,逆置,冒泡排序,
scanf 输入字符串
字符串处理
字符串溢出等问题
scanf()
gets()
puts()
fputs()
strlen()
strcat()
strncat()
strcmp()
strncmp()
strchr()
strstr()
strtok()
atoi()
atof()
atol()
C 字符串数组
定义数组
遍历输出数组每个元素的值
//GCC编译方式:C:\MinGW\project>gcc-std=c99main.c//编码环境GBK#include<stdio.h>intmain(){intarray[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};//遍历二维数组,并打印for(inti=0;i<3;i++){for(intj=0;j<4;j++){printf("array[%d][%d]=%d\n",i,j,array[i][j]);}}/*输出:array[0][0]=0array[0][1]=1array[0][2]=2array[0][3]=3array[1][0]=4array[1][1]=5array[1][2]=6array[1][3]=7array[2][0]=8array[2][1]=9array[2][2]=10array[2][3]=11*/}
字符数组多种初始化方式
研究\0 对字符串数组的影响
#include<stdio.h>intmain(){//字符串的初始化//charstr[100];//定义一个字符串//charstr[100]={'h','e','l','l','o'};//定义一个字符串,并初始化charstr[100]="hello";//多种初始化str[0]='H';str[1]='e';str[2]='\0';//遇到\0,字符串就结束了str[3]='l';str[4]='o';printf("%s\n",str);//字符串就是以\0结尾的数组//输出Heprintf("str=%d\n",sizeof(str));//输出str=100}
看看字符串数组\0后面是什么东西
#include<stdio.h>intmain(){//固定字符数组大小,研究字符串初始化后是什么东西charstr[10]="Hello";printf("str=%d\n",sizeof(str));//输出str2=10printf("str[4]char=>%cHEX=>%x\n",str[4],str[4]);printf("str[5]char=>%cHEX=>%x\n",str[5],str[5]);printf("str[6]char=>%cHEX=>%x\n",str[6],str[6]);printf("str[7]char=>%cHEX=>%x\n",str[7],str[7]);//输出://str[4]char=>oHEX=>6f//str[5]char=>HEX=>0//str[6]char=>HEX=>0//str[7]char=>HEX=>0}
显示字符串长度大小
#include<stdio.h>intmain(){//打印字符数组大小charstr1[]="Hello";printf("str1=%d\n",sizeof(str1));//输出str1=6}
修改字符串的内容
#include<stdio.h>intmain(){//修改字符串内容charstr3[99]="HelloWorld!";printf("%s",str3);printf(str3);str3[4]='A';printf(str3);//输出HelloWorld!HelloWorld!HellAWorld!}
逆置数组
#include<stdio.h>intmain(){charstr3[99]="HelloWorld!";intlow=0;inthigh=11;//注意上面的那个字符,11位之后就是\0了inttmp_var;while(low<high){tmp_var=str3[low];str3[low]=str3[high];str3[high]=tmp_var;low++;high--;}printf(str3);//输出://数组逆置://!dlroWAlleH}
显示GBK编码的汉字编码
//GBK编码#include<stdio.h>intmain(){charstr4[100]="你好世界";printf("\n%s\n",str4);for(inti=0;i<13;i++){printf("%x\n",str4[i]);}}/*C:\MinGW\project>gcc-std=c99str.cC:\MinGW\project>a.exe你好世界ffffffc4ffffffe3ffffffbaffffffc320ffffffcaffffffc0ffffffbdffffffe70000*/
显示GBK编码的汉字
//GBK编码#include<stdio.h>intmain(){//用GBK编码显示汉字charstr5[100];str5[0]=0xc4;str5[1]=0xe3;str5[2]=0;printf(str5);//输出你}
scanf函数漏洞演示:
遇到空格一定会对scanf有影响
#include<stdio.h>intmain(){chara[3]={0};charb[3]={0};scanf("%s",a);scanf("%s",b);printf("==========\n");printf("%s\n",a);printf("%s\n",b);}测试:C:\MinGW\project>gcc-std=c99str.c正常输入:C:\MinGW\project>a.exe12qw==========12qw
溢出测试1
C:\MinGW\project>a.exe12qwqwqwwqwqw==========wqwwqwqwqwqwqwwqwqw溢出测试2C:\MinGW\project>a.exe123qwerty==========rtyqwerty
scanf 溢出的原因:
#include<stdio.h>#include<stdlib.h>#include<string.h>intmain(){chara[10]={0};charb[300]={0};intc[10];printf("aaddress%p\n",a);printf("baddress%p\n",b);printf("caddress%p\n",c);system("pause");//程序等待在这里}/*C:\MinGW\project>gccstr.cC:\MinGW\project>a.exeaaddress0028FF16baddress0028FDEAcaddress0028FDC0请按任意键继续...*/
scanf会把接受到的值,在内存从开始存,不会去管是否已经溢出
这样会导致覆盖其他变量的数值
可以看出,程序已经出错
gets可以解决scanf的无法记录空格的问题#include<stdio.h>intmain(){chara[30]={0};gets(a);printf(a);}C:\MinGW\project>a.exehelloworld!helloworld!
但是依然会缓冲区溢出
#include<stdio.h>intmain(){chara[3]={0};charb[3]={0};gets(a);gets(b);printf("%s\n",a);printf("%s\n",b);}C:\MinGW\project>a.exe123456789qwertyuiooprtyuioopqwertyuioopC:\MinGW\project>
fgets解决了空格 缓存区溢出问题
#include<stdio.h>intmain(){chara[5]={0};//fgets(a,5,stdin);fgets(a,sizeof(a),stdin);printf("%s\n",a);}C:\MinGW\project>gcc-std=c99str.cC:\MinGW\project>a.exe12e34342312e
puts会在输出后面加入一个\n
#include<stdio.h>intmain(){chara[]="Helloworld!";puts(a);printf("==================");printf(a);printf("==================");}C:\MinGW\project>gcc-std=c99str.cC:\MinGW\project>a.exeHelloworld!==================Helloworld!==================
fput函数,可以代替printf
#include<stdio.h>intmain(){chara[]="Helloworld!";fputs(a,stdout);}C:\MinGW\project>gcc-std=c99str.cC:\MinGW\project>a.exeHelloworld!
对输入的字符,逆置
#include<stdio.h>intmain(){chara[99]={0};scanf("%s",a);printf("%s\n",a);//strlen返回是数组有效长度,不包含\0//获取字符串真实长度,相当于strleninti=0;while(a[i]!='\0')i++;//逆置字符数组intlow=0;inthigh=i-1;//因为字符数组有一个'\0'chartmp;while(low<high){tmp=a[low];a[low]=a[high];a[high]=tmp;low++;high--;}printf("%s\n",a);}C:\MinGW\project>gcc-std=c99str.cC:\MinGW\project>a.exeqwertyuio09876qwertyuio0987667890oiuytrewqC:\MinGW\project>a.exe你好你好strlen4sizeof99煤隳
字符串追加:
注意:可能导致溢出
#include<stdio.h>#include<string.h>intmain(){chara[99]={0};charb[300]={0};scanf("%s",a);scanf("%s",b);strcat(a,b);//把b追加到a后面,a要足够大printf("a+b=%s\n",a);}C:\MinGW\project>a.exe123abca+b=123abc
手动实现strcat
#include<stdio.h>#include<string.h>intmain(){chara[99]={0};charb[300]={0};scanf("%s",a);scanf("%s",b);//strcat(a,b);//把b追加到a后面,a要足够大//手写一个strcatintlena=strlen(a);intlenb=strlen(b);for(inti=lena;i<lena+lenb;i++){a[i]=b[i-lenb];}printf("a+b=%s\n",a);}C:\MinGW\project>gcc-std=c99str.cC:\MinGW\project>a.exe123abca+b=123abc
strncat指定追加个数
#include<stdio.h>#include<string.h>intmain(){chara[10]={0};charb[300]={0};scanf("%s",a);scanf("%s",b);strncat(a,b,sizeof(a)-strlen(b)-1);//留一个'\0'printf("a+b=%s\n",a);}/*C:\MinGW\project>gcc-std=c99str.cC:\MinGW\project>a.exe12345qwertyuiopa+b=12345qwertyuiop*/
将最高位做为符号位(0代表正,1代表负),其余各位代表数值本身的绝对值
+7的原码是00000111
-7的原码是10000111
+0的原码是00000000
-0的原码是10000000
1.2反码一个数如果值为正,那么反码和原码相同
一个数如果为负,那么符号位为1,其他各位与原码相反
+7的反码00000111
-7的反码11111000
-0的反码11111111
1.3补码原码和反码都不利于计算机的运算,如:原码表示的7和-7相加,还需要判断符号位。
正数:原码,反码补码都相同
负数:最高位为1,其余各位原码取反,最后对整个数 + 1
-7的补码:=
10000111(原码)
111111000(反码)
11111001(补码)
+0的补码为00000000
-0的补码也是00000000
补码符号位不动,其他位求反,最后整个数+ 1,得到原码
用补码进行运算,减法可以通过加法实现
7-6=1
7的补码和-6的补码相加:00000111 + 11111010 = 100000001
进位舍弃后,剩下的00000001就是1的补码
-7+6 = -1
-7的补码和6的补码相加:11111001 + 00000110 = 11111111
11111111是-1的补码
2数组内存连续,并且是同一种数据类型的变量,C语言的数组小标好是从0开始的,到n-1.
2.1一维数组定义与使用类型变量名称[数组元素的个数];
2.2数组在内存的存储方式在内存当中是连续的内存空间地址。
2.3一维数组初始化int array[10] = {0};//将数组所有元素都初始化为0
int array[10] = {0,1,2,3,4,5,6,7,8,9}
数组中找最大值思路
数组中找第二大值思路
逆置数组思路
测量楼宇高度的说明
测量地球太阳距离的说明
测量太阳木星距离的说明
2.4二维数组定义与使用intarray[3][4];//12个元素的二维数组
2.5二维数组初始化int a[3][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
3字符串与字符数组3.1字符数组定义char buf[100];
对于C语言字符串其实就是一个最后一个元素为’\0’的char数组.
3.2字符数组初始化char buf[] = “hello world”;
3.3字符数组使用3.4随机数产生函数rand与srand头文件stdlib.h
#include<time.h>
int t = (int)time(NULL);
srand(t);
for (int i = 0; i < 10; i++)
{
printf("%d\n", rand());
}
3.5用scanf输入字符串
char buf[100] = {0};
scanf(“%s”, buf);
scanf("请输入i的值%d",&i);
3.6字符串的结束标志3.7字符串处理函数3.7.1getsgets没有解决缓冲区溢出的问题.
3.7.2fgets函数gets函数不检查预留缓冲区是否能够容纳用户实际输入的数据。多出来的字符会导致内存溢出,fgets函数改进了这个问题。
由于fgets函数是为读取文件设计的,所以读取键盘时没有gets那么方便
char s[100] = { 0 };
fgets(s, sizeof(s), stdin);
3.7.3puts函数puts函数打印字符串,与printf不同,puts会在最后自动添加一个’\n’
char s[] = "hello world";
puts(s);
3.7.4fputs函数fputs是puts的文件操作版本,
char s[] = "hello world";
fputs(s, stdout);
3.7.5strlen,字符串长度strlen返回字符串的长度,但是不包含字符串结尾的’\0’
char buf[10]
sizeof(buf);//返回的是数组buf一共占据了多少字节的内存空间.
3.7.6strcat,字符串追加char str1[100];
char str2[100];
strcat(str1, str2);//把str2追加到str1的后面
str1一定要有足够的空间来放str2,不然会内存溢出.
3.7.7strncat,字符串有限追加strncat(str1, str2, sizeof(str1) –strlen(str1) - 1);
3.7.8strcmp,字符串比较strcmp(a, “str”);//如果两个参数所指的字符串内容相同,函数返回0
3.7.9strncmp,字符串有限比较strncmp(str, “exit”, 4);
3.7.10 strcpy字符串拷贝strcpy(str, “hello world”);//存在溢出的问题,
3.7.11 strncpy字符串有限拷贝strcpy(str, “hello world”, 7);
3.7.12 sprintf,格式化字符串printf是向屏幕输出一个字符串
sprintf是向char数组输出一个字符串,其他行为和printf一模一样
sprintf也存在缓冲区溢出的问题
3.7.13 strchr查找字符strchr(str, ‘c’);
返回值是字符’c’在字符串str中的位置
3.7.14 strstr查找子串3.7.15 strtok分割字符串字符在第一次调用时strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL每次调用成功则返回指向被分割出片段的指针
char buf[] = "abc@defg@igk";
char *p = strtok(buf, "@");;
while (p)
{
printf("%s\n", p);
p = strtok(NULL, "@");
}
3.7.16 atoi转化为int3.7.17 atof转化为float3.7.18 atol转化为long作业说明:
不可以用任何已有的函数,完全自己写代码,完成十进制字符串转化为十进制的整数
作业思路:
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。