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=c99 main.c
//编码环境 GBK
#include <stdio.h>
int main(){
int array[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};
     //遍历二维数组,并打印
 for(int i=0;i< 3;i++){
for(int j=0;j<4;j++){
printf("array[%d][%d]=%d\n",i,j,array[i][j]);
}
}
/* 
输出 :
array[0][0]=0
array[0][1]=1
array[0][2]=2
array[0][3]=3
array[1][0]=4
array[1][1]=5
array[1][2]=6
array[1][3]=7
array[2][0]=8
array[2][1]=9
array[2][2]=10
array[2][3]=11 
*/
}

字符数组多种初始化方式

研究\0 对字符串数组的影响

#include <stdio.h>
int main(){
//字符串的初始化
//char str[100] ; //定义一个字符串
//char str[100] = {‘h‘,‘e‘,‘l‘,‘l‘,‘o‘}; //定义一个字符串,并初始化
char str[100] = "hello"; //多种初始化
     str[0] = ‘H‘;
     str[1] = ‘e‘;
     str[2] = ‘\0‘;       //遇到\0,字符串就结束了
     str[3] = ‘l‘;
     str[4] = ‘o‘;
 printf("%s\n",str); //字符串就是以\0结尾的数组
 //输出 He
 printf("str =%d\n",sizeof(str)); 
 //输出 str =100
}

看看字符串数组\0后面是什么东西

#include <stdio.h>
int main(){
 //固定字符数组大小,研究字符串初始化后是什么东西
 char str[10] = "Hello";
 printf("str =%d\n",sizeof(str)); 
 //输出 str2 =10
     printf("str[4]  char=>%c HEX=>%x\n",str[4],str[4]);
     printf("str[5]  char=>%c HEX=>%x\n",str[5],str[5]);
     printf("str[6]  char=>%c HEX=>%x\n",str[6],str[6]);
     printf("str[7]  char=>%c HEX=>%x\n",str[7],str[7]);
 //输出:
 // str[4]  char=>o HEX=>6f
 // str[5]  char=>  HEX=>0 
 // str[6]  char=>  HEX=>0
 // str[7]  char=>  HEX=>0
}

显示字符串长度大小

#include <stdio.h>
int main(){
 //打印字符数组大小
 char str1[] = "Hello";
 printf("str1 =%d\n",sizeof(str1)); 
 // 输出 str1 =6
}

修改字符串的内容

#include <stdio.h>
int main(){
 //修改字符串内容
 char str3[99]="Hello World!";
 printf("%s",str3);
 printf(str3);
 str3[4]=‘A‘;
 printf(str3);
 //输出 Hello World!Hello World!HellA World!
    
}

逆置数组

#include <stdio.h>
int main(){
char str3[99]="Hello World!";
int  low=0;
    int high=11; //注意上面的那个字符,11位之后就是\0了
    int tmp_var;
    while(low<high){
        tmp_var    =str3[low];
        str3[low]  =str3[high];
        str3[high]   =tmp_var;
        low++;
        high--;
 }
 printf(str3);
     //输出:
 //数组逆置:
     //!dlroW AlleH
}

显示GBK编码的汉字编码

//GBK  编码
#include <stdio.h>
int main(){
 char str4[100] ="你好 世界";
 printf("\n%s\n",str4);
 for(int i=0;i<13;i++){
 printf("%x\n",str4[i]);
 }
}
/*
C:\MinGW\project>gcc -std=c99 str.c
C:\MinGW\project>a.exe
你好 世界
ffffffc4
ffffffe3
ffffffba
ffffffc3
20
ffffffca
ffffffc0
ffffffbd
ffffffe7
0
0
0
0
*/

显示GBK编码的汉字

//GBK  编码
#include <stdio.h>
int main(){
 //用GBK编码显示 汉字
char str5[100];
    str5[0]=0xc4;
    str5[1]=0xe3;
    str5[2]=0;
    printf(str5);
    //输出 你
}

scanf函数漏洞演示:

遇到空格一定会对scanf有影响

#include <stdio.h>
int main(){
    char a[3]={0};
    char b[3]={0};
    scanf("%s",a);
    scanf("%s",b);
printf("==========\n");
printf("%s\n",a);
printf("%s\n",b);
}
测试:
C:\MinGW\project>gcc -std=c99 str.c
正常输入:
C:\MinGW\project>a.exe
12
qw
==========
12
qw

溢出测试1

C:\MinGW\project>a.exe
12
qwqwqwwqwqw
==========
wqwwqwqw
qwqwqwwqwqw
溢出测试2
C:\MinGW\project>a.exe
123 qwerty
==========
rty
qwerty

scanf 溢出的原因:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
    char a[10]={0};
    char b[300]={0};
int  c[10];
    printf("a address %p\n",a);
    printf("b address %p\n",b);
    printf("c address %p\n",c);
system("pause"); //程序等待在这里
}
/*
C:\MinGW\project>gcc str.c
C:\MinGW\project>a.exe
a address 0028FF16
b address 0028FDEA
c address 0028FDC0
请按任意键继续. . .
*/

scanf会把接受到的值,在内存从开始存,不会去管是否已经溢出

这样会导致覆盖其他变量的数值

可以看出,程序已经出错

gets可以解决scanf的无法记录空格的问题
#include <stdio.h>
int main(){
    char a[30]={0};
    gets(a);
printf(a);
}
C:\MinGW\project>a.exe
hello world !
hello world !

但是依然会缓冲区溢出

#include <stdio.h>
int main(){
    char a[3]={0};
    char b[3]={0};
    gets(a);
    gets(b);
printf("%s\n",a);
printf("%s\n",b);
}
C:\MinGW\project>a.exe
123456789
qwertyuioop
rtyuioop
qwertyuioop
C:\MinGW\project>

fgets解决了空格 缓存区溢出问题

#include <stdio.h>
int main(){
    char a[5]={0};
   // fgets(a,5,stdin);
    fgets(a,sizeof(a),stdin);
printf("%s\n",a);
}
C:\MinGW\project>gcc -std=c99 str.c
C:\MinGW\project>a.exe
12 e343 423
12 e

puts会在输出后面加入一个\n

#include <stdio.h>
int main(){
    char a[]="Hello world !";
puts(a);
printf("==================");
printf(a);
printf("==================");
}
C:\MinGW\project>gcc -std=c99 str.c
C:\MinGW\project>a.exe
Hello world !
==================Hello world !==================

fput函数,可以代替printf

#include <stdio.h>
int main(){
    char a[]="Hello world !";
fputs(a,stdout);
}
C:\MinGW\project>gcc -std=c99 str.c
C:\MinGW\project>a.exe
Hello world !

对输入的字符,逆置

#include <stdio.h>
int main(){
    char a[99]={0};
scanf("%s",a);
printf("%s \n",a);
//strlen  返回是数组有效长度,不包含\0
//获取字符串真实长度,相当于strlen
int i = 0;
while(a[i] != ‘\0‘) i++;
//逆置字符数组
int low = 0;
int high= i-1; //因为字符数组有一个‘\0‘
char tmp;
while(low < high){
tmp    = a[low];
a[low] = a[high];
a[high]= tmp;
low++;
high--;
}
printf("%s \n",a);
}
C:\MinGW\project>gcc -std=c99 str.c
C:\MinGW\project>a.exe
qwertyuio09876
qwertyuio09876
67890oiuytrewq
C:\MinGW\project>a.exe
你好
你好
strlen 4
sizeof 99
煤隳

字符串追加:

注意:可能导致溢出

#include <stdio.h>
#include <string.h>
int main(){
    char a[99]={0};
    char b[300]={0};
    scanf("%s",a);
    scanf("%s",b);
strcat(a,b); //把b追加到a后面,a要足够大
printf("a+b=%s\n",a);
}
C:\MinGW\project>a.exe
123
abc
a+b=123abc

手动实现strcat

#include <stdio.h>
#include <string.h>
int main(){
    char a[99]={0};
    char b[300]={0};
    scanf("%s",a);
    scanf("%s",b);
//strcat(a,b); //把b追加到a后面,a要足够大
//手写一个strcat
int lena = strlen(a);
int lenb = strlen(b);
for(int i = lena;i < lena + lenb;i++){
a[i] = b[i-lenb];
}
printf("a+b=%s\n",a);
}
C:\MinGW\project>gcc -std=c99 str.c
C:\MinGW\project>a.exe
123
abc
a+b=123abc

strncat指定追加个数

#include <stdio.h>
#include <string.h>
int main(){
    char a[10]={0};
    char b[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=c99 str.c
C:\MinGW\project>a.exe
12345
qwertyuiop
a+b=12345qwertyuiop
*/

1         整数在计算机内部的存储方式

1.1      原码

将最高位做为符号位(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.1         gets

gets没有解决缓冲区溢出的问题.

3.7.2         fgets函数

gets函数不检查预留缓冲区是否能够容纳用户实际输入的数据。多出来的字符会导致内存溢出,fgets函数改进了这个问题。

由于fgets函数是为读取文件设计的,所以读取键盘时没有gets那么方便


char s[100] = { 0 };

fgets(s, sizeof(s), stdin);

3.7.3         puts函数

puts函数打印字符串,与printf不同,puts会在最后自动添加一个’\n’


char s[] =  "hello world";

puts(s);

3.7.4         fputs函数

fputs是puts的文件操作版本,


char s[] =  "hello world";

fputs(s, stdout);

3.7.5         strlen,字符串长度

strlen返回字符串的长度,但是不包含字符串结尾的’\0’

char buf[10]

sizeof(buf);//返回的是数组buf一共占据了多少字节的内存空间.

3.7.6         strcat,字符串追加

char str1[100];

char str2[100];

strcat(str1, str2);//把str2追加到str1的后面

str1一定要有足够的空间来放str2,不然会内存溢出.

3.7.7         strncat,字符串有限追加

strncat(str1, str2, sizeof(str1) –strlen(str1) - 1);

3.7.8         strcmp,字符串比较

strcmp(a, “str”);//如果两个参数所指的字符串内容相同,函数返回0

3.7.9         strncmp,字符串有限比较

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[]  = "[email protected]@igk";

char *p =  strtok(buf, "@");;

while (p)

{

printf("%s\n", p);

p = strtok(NULL, "@");

}

3.7.16      atoi转化为int

3.7.17      atof转化为float

3.7.18      atol转化为long

作业说明:

不可以用任何已有的函数,完全自己写代码,完成十进制字符串转化为十进制的整数

作业思路:

时间: 2024-10-22 00:57:21

4 C 语言 数值存储方式 数组的相关文章

C语言 数据存储方式

C语言 数据存储方式 一.源码 一个数的原码(原始的二进制码)有如下特点: 最高位做为符号位,0表示正,为1表示负 其它数值部分就是数值本身绝对值的二进制数 负数的原码是在其绝对值的基础上,最高位变为1 下面数值以1字节的大小描述: 十进制数 原码 +15 0000 1111 -15 1000 1111 +0 0000 0000 -0 1000 0000 注:原码表示法简单易懂,与带符号数本身转换方便,只要符号还原即可,但当两个正数相减或不同符号数相加时,必须比较两个数哪个绝对值大,才能决定谁减

从java toBinaryString() 看计算机数值存储方式(原码、反码、补码)

一.toBinaryString 方法及其含义 1.1 方法说明 该方法位于java.lang.Integer类中 方法签名:public static String toBinaryString(int i) 含义:返回参数数值的补码形式,正数则忽略前面的0.(官方注释:返回表示传入参数的一个无符号(这里无符号大概单纯指数值前面没有+-号,实则是有符号位) 的二进制字符串.如果参数为负数x,返回的值则为 2^32 + x [就是它的补码]) 1.2 使用示例 System.out.printl

C语言浮点数存储方式

对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用 32bit,double数据占用 64bit.其实不论是float类型还是double类型,在计算机内存中的存储方式都是遵从IEEE的规范的,float 遵从的是IEEE R32.24 ,而double 遵从的是R64.53. 无论是单精度还是双精度,在内存存储中都分为3个部分: 1) 符号位(Sign):0代表正,1代表为负: 2) 指数位(Exponent):用于存储科学计数法中的指数数据,

一道题回顾计算机数值存储方式-原码,反码,补码

突然想到了计算机的补码,现在利用这个题目回顾一下相关知识点 unsigned char ch = -1; int val = ch; val的最终值是255: 换算成二进制一下,-1的源码:1000 0001,反码:1111 1110 ,负数在计算机中是以补码形式存储的,-1的补码:1111 1111 ch 变量是 无符号的,也就是整个补码的二进制位都是数值位,1111 1111 二进制位换算成十进制就是255,最终赋值给整数结果自然也是255 这道题目考察的就是计算机数值的存储方式,对于正数,

树的存储方式数组链表+vector

图的邻接矩阵存储法,它的空间和时间复杂度都是N2,现在我来介绍另外一种存储图的方法:邻接表,这样空间和时间复杂度就都是M.对于稀疏图来说,M要远远小于N2 模板如下: struct edge{ int u,v,w,next; }edge[N*3]; int first[N],t; void init() { t = 0; memset(first,-1,sizeof(first)); } void add(int u,int v,int w) { edge[t].u = u;     //u:第

移码及浮点数在内存中的存储方式

首先说一下十进制的小数怎么转化为二进制的小数,计算机根本就不认识10进制的数据,他只认识0和1,所以,10进制的小数在计算机中是用二进制的小数表示的. 十进制的小数转化为二进制的小数的方法: 可以简单的概括为正序取整,将十进制的小数部分乘以2,然后取整数部分. 例如将0.2转化为二进制的小数,那么0.2*2=0.4,其整数部分是0,所以二进制小数的第一位为0,然后0.4*2=0.8,其整数部分是0,所以二进制小数的第二位为0,然后0.8*2=1.6,其整数部分是1,所以二进制小数的第三位是1,然

C语言中存储多个字符串的两种方式

C语言中存储多个字符串的两种方式 方式一    二维字符串数组 声明: char name[4][10] = { "Justinian", "Momo", "Becky", "Bush" }; 在内存中的存储: J u s t i n i a n \0 M o m o \0 \0 \0 \0 \0 \0 B e c k y \0 \0 \0 \0 \0 B u s h \0 \0 \0 \0 \0 \0 这种方式会造成内存空间

java 数据结构 图中使用的一些常用算法 图的存储结构 邻接矩阵:图的邻接矩阵存储方式是用两个数组来标示图。一个一位数组存储图顶点的信息,一个二维数组(称为邻接矩阵)存储图中边或者弧的信息。 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 实例如下,左图是一个无向图。右图是邻接矩阵表示:

以下内容主要来自大话数据结构之中,部分内容参考互联网中其他前辈的博客. 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示一个图,V是图G中顶点的集合,E是图G中边的集合. 无边图:若顶点Vi到Vj之间的边没有方向,则称这条边为无项边(Edge),用序偶对(Vi,Vj)标示. 对于下图无向图G1来说,G1=(V1, {E1}),其中顶点集合V1={A,B,C,D}:边集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}: 有向图:若

数组模拟堆栈的存储方式代码实践

堆栈的模式是先进后出,取出后堆栈中就没有取出的元素了,所以在模拟时候要注意这些问题. 1 import java.util.Arrays; 2 3 /* 4 5 需求:编写一个类使用数组模拟堆栈的存储方式. 6 7 堆栈存储特点: 先进后出,后进先出. 8 9 注意: 不再使用的对象,应该不要让变量指向该对象,要让该对象尽快的被垃圾回收期回收. 10 11 12 */ 13 class StackList{ 14 15 Object[] elements; 16 17 int index = 0