C语言学习(动态内存分配和字符串)

动态内存分配:

malloc函数:

  • 要加头文件#inclde<stdlib.h>
  • 格式:void*malloc(size_t size);
  • 向malloc申请的空间的大小是以字节为单位的
  • 返回的结果是void,需要类型转型转换        如a=(int*)malloc(变量or数字*数字);
#include<stdio.h>
#include<stdlib.h>

int main()
{
	int b=7;
	int *a;
	int i;
//可以将a当作数组使用
	a=(int*)malloc(b*sizeof(int));

//输入
	for(i=0;i<7;i++){
		scanf("%d",&a[i]);
	}
//输出
	for(i=0;i<7;i++){
		printf("%d\n",a[i]);
	}
//释放内存空间
	free(a);
	for(i=0;i<7;i++){
		printf("%d\n",a[i]);
	}
	return 0;
} 

当没有空间时,则申请失败返回0或者NULL。

free函数:

  • 格式:free(变量):     原型:   void free (void* 变量);    注意该变量不能释放int *p来的指针
  • free() 可以释放由malloc()、calloc()、realloc()分配的内存空间,以便其他程序再次使用。
  • 申请过的空间,最终都应该要还;若不还,会产生内存垃圾,内存漏洞
  • 只能还申请来的空间的首地址           例如:p向malloc申请了空间,再p++,free(p)只释放了p,无法释放p++

字符串:

  • char 变量,该变量可以存入字符char a=‘a’;
  • 字符串常量在内存中存放位置由系统自动安排,系统在存储一个字符串常量时先给定一个起始位置,所以字符串常量实质上是一个指向该字符串首字符的指针常量。
  • 所以输出字符串时,输出参数给出起始位置(地址)(s[0],s[1],s,s+1),'\0'用来控制结束
  • 0或者'\0'(整数0)结尾的一串字符,注意和'0'不一样,0标志字符串的结束,不是字符串的一部分,计算字符串的长度不包含0
  • 字符串以数组的形式存在,更多的是以指针的形式,以数组或指针的形式访问
  • 通过数组的方式可以遍历字符串
  • 不能用运算符对字符串做运算

字符串变量:

  • char *str="Hello";
  • char word[]="Hello";
  • char line[10]="Hello";        占用六个字节,系统自动生成一个结尾0,算上一个字节

字符串常量:

  • char *s="Hello World";           const char *s="Hello World";
  • s是一个指针,初始化为指向以恶搞字符串常量
  • 因为实际上是const类型,这个常量所在的地方为代码段,只读,不能写入
  • 同一内容的两个字符串常量的地址相同
  • 如果需要修改字符串,应该用数组:char s[ ]="Hello World";
#include<stdio.h>

int main(void)
{
	int i=0;
	const char *s="Hello World";
	const char *s2="Hello World";
	char *s3="Hello";
	
  printf("%p",&i);
//&i=000000000065FE04
//s=0000000000429000
//s2=0000000000429000//代码段,只读 
//s3=000000000042900C

}

数组:这个字符串在这里,可读写

  • 作为本地变量空间自动被回收

指针:这个字符串不知道在哪里,只读

  • 处理参数
  • 动态分配空间 malloc

字符串赋值:

char *t="title";
char *s;
s=t;

并没有产生新的字符串,只是让指针s指向了t所指的字符串,对s的操作就是对t做的

字符串输入输出:

char string[8];
scanf("%s",string);
printf("%s",string);
  • scanf读入一个单词(到空格、tab或回车为止)    PS:gets函数可以读空格,但不安全
  • scanf是不安全的,因为不知道要读入的内容的长度

不安全的输入,解决方案:

  • 在%和s之间的数字表示最多允许读入的字符数量,这个数字要比数组的大小小一(\0占了最后一个数组),           %s改为%7s,表明最多输入7个字符
  • 若输入超出所允许读入的字符数量,则超出的字符算入下一个scanf里面

常见错误:

char *i;

scanf("%s",i);

  • 以为char*就是字符串类型,就可以直接使用
  • 定义字符串指针后,如果没有对它赋值,指针的值是不确定的,不能明确它指向的内存单元。没有对指针i赋值,却对i指向的单位赋值。如果该单位已分配给其他变量,其值就改变了。
#include<stdio.h>
#include<stdlib.h>

int main(void)
{

    char *ch;
    ch   =   (char   *)malloc(sizeof(char)*100);
    scanf("%s",ch);
    puts(ch);
    
    
	return 0;
}

空字符串:

char buffer[100]=" ";        这个数组的长度有100,里面的内容是空的

char buffer[ ]=" ";           这个数组的长度只有1

二维字符数组:

char a[ ] [ ];

char *a[ ];

程序参数:

int main(int argc,char const *argv[ ])

  • argc是命令行总的参数个数  

    argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数是命令行后面跟的用户输入的参数

  • argc和argv是你通过命令行窗口传给程序的。

  • 在程序启动的时候(),就携带参数给他,而不是运行过程中敲入东西给程序。这时候需要用用到带参数(int argc, char *argv[])的main函数。

putchar:

  • int putchar(int c);
  • 向标准输出写一个字符
  • 返回写几个字符,EOF(-1)表示写入失败

getchar:

  • int getchar(void);
  • 从标准输入读入一个字符
  • 返回类型是int是为了返回EOF(-1)
  • 区分scanf,scanf将一串字符或数字作为一个整体,而getchar是一个个字符或数字地读入
#include<stdio.h>

int main(int argc,char const *argv[])
{
	int ch;
	
	while((ch=getchar())!=EOF){
		putchar(ch);
	}
	
	printf("EOF\n");
	
	return 0;
} 
//写入任何字符或数字都会原封不动地输出
//在windouws下,CTRL+Z便会输出EOF 

EOF的作用:

  • 当终端有字符输入时,Ctrl+Z产生的EOF相当于结束本行的输入,将引起getchar()新一轮的输入;
  • 当终端没有字符输入或者可以说当getchar()读取新的一次输入时,输入Ctrl+Z,此时产生的EOF相当于文件结束符,程序将结束getchar()的执行。

string.h:

strlen

  • size_t strlen(const char *s);             strlen(数组名);
  • size_t表示对象类型,const保证不改变变量
  • 意义:返回s的字符串长度(不包括结尾的\0)
  • #include<stdio.h>
    #include<string.h>
    
    int f(const char*s)
    {
    	int cnt=0,idx=0;
    	while(s[idx]!='\0'){
    		idx++;
    		cnt++;
    	}//对数组s开始记数,一直到读入到字符数组最后的\0便推出记数 
    	return cnt;
    }
    int main(int argc,char const *argv[])
    {
    	char line[]="Hello";
    	printf("strlen=%lu\n",strlen(line)); 
    	printf("strlen=%lu\n",f(line));
    	//%lu表示输出无符号长整型整数 (long unsigned) 
    	printf("sizeof=%lu\n",sizeof(line));
    	
    	return 0;
    } 
    
    // 结果:strlen=5        strlen=5     sizeof=6

strcmp

  • int strcmp(const *s1,const *s2);           strcmp(s1,s2);
  • int strncmp ( const char * str1, const char * str2, size_t n );
    【参数】str1, str2 为需要比较的两个字符串,n为要比较的字符的数目。
  • 比较两个字符串,返回:
  • 0:s1==s2
  • 1:s1>s2
  • -1:  s1<s2
  •  比对两个数组之间相对应的字符的ASCii码大小,相减得到结果
  • 三种比较字符大小的方法 
    #include<stdio.h>
    #include<string.h>
    //该函数不需要string.h
    int mycmp(const char *s1,const char *s2)
    {
    //	int idx=0;
    //	whlie(s1[idx]==s2[idx]&&s1[idx]!='\0'){
    //		inx++;
    //	}
    	while(*s1==*s2&&*s1!='\0'){
    		s1++;
    		s2++;
    	}
    	return *s1-*s2;
    	
    }
    
    int main(int argc,char const *argv[])
    {
    	char s1[]="abc";
    	char s2[]="abc";
    	printf("%d\n",mycmp(s1,s2));
    	printf("%d\n",strcmp(s1,s2);
    } 
    

strcpy

  • char*strcpy(char*restrict dst,const char *restrict src);            
  • 把src的字符串拷贝到dst,从后往前拷贝,restrict表示src和dst不重叠(c99)
  • 有返回值,返回dst,可参与其他函数运算
  • 复制一个字符串
    char*dst=(char*)malloc(strlen(src))+1);
    //+1是因为strlen不包括结尾的\0字符
    strcpy(dst,src); 
    char*f(char*dst,const cahr*src)
    {
    	int idx=0;
    	while(src[idx]){
    		dst[idx]=src[idx];
    		idx++;
    	}
    	dst[idx]='\0';
    	
    	return dst;
    }
    char*f(char*dst,const cahr*src)
    {
    	char*ret=dst;
    //	while(*dst++=*src++)
    //	;
    //	*dst='\0';
    	while(*src!='\0'){
    //		*dst=*src;
    //		dst++;
    //		src++;
            *dst++=*src++;//先取值再自增  
    	}
    	return ret;
    }

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值