C语言学习笔记4---数组、字符串
文章目录
- 数组
- 一维数组
- 二维数组
- 传参为数组
- 数组与指针的关系
- 字符串
- 字符串的初始化
- 字符串的输出
- 字符串操作函数【注:待补充】
- 字符串数组
- 重要链接
- 参考文献
数组
数组用于存储一系列具有相同数据类型的变量。数组内的元素具有连续的内存位置。
一维数组
一维数组的声明
声明一个数组时,必须要指明数组的数据类型type, 数组的长度
。长度需为大于0的整数, 数组的长度用中括号包裹。
代码语法为:
type 数组名[数组的长度,即元素个数];
一维数组的初始化
初始化一维数组,若需初始化的数组已事先声明过,则直接将用大括号包裹的数组元素赋值给该数组。若事先并未声明,则在初始化是需要指明数组的数据类型。声明与初始化数组同时进行时,方括号内的数组长度可忽略,直接默认为初始化的数组元素的个数。如 int a[] = {0,0,0,3, 0, 5,0,0}.
代码语法为:
type 数组名[数组长度] = {元素1, 元素2, 元素3,…元素n};
若为稀疏数组且需要经常性更新数组元素,即数组的长度可能不能完全确定,如a[] = {0,0,0,3, 0, 5,0,0},后期还需要添加元素,可写为:
a[] = {[3]=3, [5] = 5}
遍历时,数组的长度可写为sizeof(a)/sizeof(a[0])
即
for(int i = 0; i < sizeof(a)/sizeof(a[0]);i++){printf("%d", a[i]);}
【注】
- 初始化时数组的长度并不是必须要写的,若中括号内不写数组长度,则默认数组的长度即为元素的个数。若中括号内写了数组长度, 则后面大括号中的元素个数不可超过中括号中所写的数组长度。
- 数组变量本身不能被赋值。如果要把一个数组中的内容全部传输给另外一个数组,只能通过遍历。
- 若函数的参数是数组时,需要传入数组的长度,否则无法做运算。
一维数组的索引
索引值从0即基索引至数组长度减1。数组中的元素可以通过数组名与索引值来访问。
【代码实例】
#include <stdio.h>int main ()
{int n[ 10 ]; /* n 是一个包含 10 个整数的数组 */int i,j;/* 初始化数组元素 */ for ( i = 0; i < 10; i++ ){n[ i ] = i + 100; /* 设置元素 i 为 i + 100 */}/* 输出数组中每个元素的值 */for (j = 0; j < 10; j++ ){printf("Element[%d] = %d\n", j, n[j] );}return 0;
}
二维数组
多维数组的声明同一维数组一样也需要指明数据类型,每一个维度上的长度也需要用中括号来包裹说明。是几维数组就需要几个中括号。代码语法为:
type 多维数组名[size1][size2][size3]…[size n];
多维数组中最简单的形式是二维数组,本质上是一个元素为一维数组的列表。其声明与初始化规则同一维数组,代码语法分别为:
type 数组名[行数][列数];
type 数组名[行数][列数] = {{第一行的一维数组元素},{第二行的一维数组元素},…{第n行的一维数组元素}};
二维数组的索引也需要从两个维度来看,行列索引分别都是从基索引0至行数减1与列数减1.
【代码实例】
#include <stdio.h>int main ()
{/* 一个带有 5 行 2 列的数组 */int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}};int i, j;/* 输出数组中每个元素的值 */for ( i = 0; i < 5; i++ ){for ( j = 0; j < 2; j++ ){printf("a[%d][%d] = %d\n", i,j, a[i][j] );}}return 0;
}
传参为数组
函数参数表中的数组实际为指针,所以无法得到该数组中元素的个数。sizeof(数组名)==sizeof(数据类型*)
,同时指针可以用数组的运算符[]
进行运算。如
- int sum(int *ar, int n); 与 int sum(int ar[], int n)等价
- 以下四种函数原型是等价的:
int sum(int *ar, int n);%数组写为指针的形式
int sum(int *, int); %忽略数组名与变量名
int sum(int ar[], int n);%参数为数组形式
int sum(int [], int);%忽略参数中数组的名称与变量名称
- 以下四种函数原型是等价的:
传入函数的数组成了什么? 如如下代码段
int isPrime(int x, int knownPrimes[], int numberOfKnownPrimes)
{int ret =1;int i;for(i=0; i<numberOfKnownPrimes; i++){if (x%knownPrimes[i]==0){ret = 0;break;}}return ret;
}
数组与指针的关系
数组变量为特殊的指针
数组变量本身表达地址
,所以定义指向数组的指针时无需用&
取地址,a==&a[0]
如int a[10]; int *p=a;
但是数组的单元表达的是变量,需要用&
取地址。- []运算符可以对数组做,也可以对指针做
- *运算符可以对指针做,也可以对数组做,如
*a=25
- 数组变量为
const
的指针,所以不能被赋值,所以数组变量之间不能相互赋值。即int a[]
等价于int * const a
字符串
在C语言中,字符串实际上是使用空字符\0
结尾的一维字符数组
。\0
是用于标记字符串的结束。
字符串的初始化
- 使用数组形式,应用大括号进行初始化。
char 字符串名[字符的个数+1]={'英文字符1','英文字符2',...,'英文字符n','\0'};
例: char logo[9] = {‘h’,‘h’,‘x’,‘x’,‘t’,‘t’,‘x’,‘s’,‘\0’};
- 直接使用双引号来初始化。
char 字符串名[字符的个数+1]="字符串的内容";
例: char logo[] = “hhxxttxs”;
【注】:1,2两种初始化方式中,中括号内的内容都可省略。
字符串的输出
- 使用索引遍历输出
#include <stdio.h>
int main(){char list[] = {'h','h','x','x','t','t','x','s','\0'};for(int i = 0; i < 9;i++){printf("%c ", list[i]);}return 0;
}
- 直接整串输出
#include <stdio.h>
int main(){char list[] = {'h','h','x','x','t','t','x','s','\0'};printf("%s",list);return 0;
}
字符串操作函数【注:待补充】
- putchar()
函数声明:
int putchar(int c)
;
把一个无符号字符写入到标准输出中,如发生错误则返回EOF(-1)(end of fail)表示写失败。与printf()函数的区别:参考文献
1)printf()为发送格式化的输出到标准输出int printf(const char *format, ...)
,可输出各种类型的数据;而putchar()是把一个无符号字符写入到标准输出中,只能输出单个字符。
2)printf()的返回值是正常输出的参数的数量,而putchar()的返回值则是是否正常输出。
3)printf()的时间复杂度是O(nlog(n))O(nlog(n))O(nlog(n)), 而putchar()的复杂度为O(1)O(1)O(1),输出句子也只有O(n)O(n)O(n)。
4)printf()每执行一次解析一次格式串,而putchar()是编译时尽量优化。
- getchar()
函数声明:
int getchar(void)
从标准输入读入一个无符号字符,该函数以无符号char强制转换为int的形式返回读取的字符,如果到达文件末尾或发生读入错误,则返回EOF(-1)。与scanf()的区别:参考文献
1)scanf()为格式化输入函数int scanf(const char *format, ...)
,可输入各种类型的数据。而getchar()是键盘输入函数,其功能是从键盘上输入一个字符。
2)scanf()函数在读取数字时会跳过空格、制表符合换行符;getchar()只能输入字符型,输入时遇到回车键才从缓冲区依次提取字符。
3)scanf()以空格、Enter、Tab结束一次输入,不接受空格符
,不会舍弃最后的回车符(即回车符会残留在缓冲区中);getchar()以Enter结束输入,接受空格符
,会舍弃最后的回车符。
【代码演示】
#include<stdio.h>
int main(int argc, char const *argv[]){int ch;while((ch = getchar())!=EOF){putchar(ch);}return 0;
}
需包含头文件string.h
的字符串库函数
1)strlen()函数
。计算字符串的长度。与sizeof()不同的是该函数返回的字符串长度不包含结束字符。
函数声明: strlen(const char *s);
【代码演示】
/*自写strlen函数:mylen*/
#include <stdio.h>
#include <string.h>
int mylen(const char* s){
//数组写法------------------------------------------/*int index = 0;while(s[index] != '\0'){index ++;}return index;
-------------------------------------------------------------------*///指针写法---------------------------------------------------------------char* t = s;while(*t!= '\0'){t++;}return (t - s);
}
//------------------------------------------------------------------------------------------ int main(int argc, char const *argv[]){char str[] = "This is a series of codes";printf("The number of codes of str is %d\n", mylen(str));return 0;
}
2)strcmp()函数
。按照ASCII码逐一比较两个字符串的大小关系。
函数声明: int strcmp(char *a, char *b)
。
该函数会对字符串a和b的每个字符,按照ASCII 码值逐一比较,如果二者完全相同返回0;如果字符串a的ASCII码值首先出现较大者,会返回1,否则返回-1。
【代码演示】
//strcmp()函数
/*函数说明
int strcmp(const char *s1, const char *s2);
0: s1==s2
1: s1>s2
-1: s1<s2
*/
#include <stdio.h>
#include <string.h>
/*自写strlen函数:mycmp*/
int mycmp(char *str1, char *str2){
//---------------------------------------------------------------------------
/*数组写法*/int index = 0;while( str1[index]==str2[index] && str1[index] != '\0'){index++;}int res = -1;if(str1[index]==str2[index]){res = 0;}else{res = (str1[index] - str2[index])/(abs(str1[index] - str2[index]));}return res;
}
/*指针写法*/
/*while(*str1==*str2 && *str1 != '\0'){str1++;str2++;}int res = -1;if(*str1==*str2){res = 0;}else{res = (*str1 - *str2)/(abs(*str1 - *str2));}return res;
}*/
int main(void){char str_1[] = "abc";char str_2[] = "ABC";printf("%d\n", mycmp(str_1,str_2));if(strcmp(str_1,str_2)==0){printf("str_1 is equal to str_2\n");}return 0;
}
3)strcpy()函数
。strcpy(字符串1,字符串2)复制字符串2到字符串1中。返回的是一个字符指针, 字符串2会将字符串1覆盖。
函数声明: char* strcpy(char *restrict dst, const char *restrict src).
这里 restrict
表明dst与src两个指针所指向的内存空间不重叠。
需要注意的是字符串在复制的过程中遇到\0
也会进行复制,因此若源字符串(字符串2)的字符串长度小于目的字符串(字符串1)的长度的话,使用strcpy函数后新的字符串长度同源字符串一致。
【代码演示】
#include <stdio.h>
#include <string.h>
int mycpy(char *str1, const char *str2){//用于复制一个字符串
//----------------------------------------------------------------------------------
/*数组写法*/int index = 0;while( str2[index]!= '\0'){str1[index]=str2[index];index++;}str1[index] = '\0';return str1;
}
//-----------------------------------------------------------------------------------------
/*指针写法*/
/*
char* res = str1;
while(*str2 != '\0'){*str1 = *str2;str1++;str2++;//*str1++=*str2++;}*str1 = '\0';return *res;
*/
//-------------------------------------------------------------------------------------------------
int main(int argc, char const *argv[]){char str1[] = "abcdefg";char str2[] = "ABCD";char str3[] = "abcdefg";mycpy(str1, str2);printf("str2 拷贝到 str1 的结果为 %s\n", str1);//(1)长度短的字符串拷贝到长度长的字符串mycpy(str2, str3);printf("str3 拷贝到 str2 的结果为 %s\n", str2);//(2)长度长的字符串拷贝到长度短的字符串return 0;
}/*
输出结果为:
str2 拷贝到 str1 的结果为 ABCD//(1)
str3 拷贝到 str2 的结果为 abcdefg//(2)
*/
4)strncpy()函数
。strncpy(字符串1,字符串2,个数n)复制字符串2中的n个字符到字符串1中。返回的是一个字符指针, 字符串2会将字符串1覆盖。
函数声明: char *strncpy(char *dest, const char *src, size_t n)
【代码演示】
//strncpy()函数
#include <stdio.h>
#include <string.h>
int myncpy(char *str1, const char *str2, int n){//用于复制一个字符串
//----------------------------------------------------------------------------------
/*数组写法*/
/*int index = 0;//while( str2[index]!= '\0'){while( index < n){str1[index]=str2[index];index++;}str1[index] = '\0';return str1;
}*/
//-----------------------------------------------------------------------------------------
/*指针写法*/char* res = str1;
while(str1 - res < n){*str1 = *str2;str1++;str2++;//*str1++=*str2++;}*str1 = '\0';return *res;
}
//-------------------------------------------------------------------------------------------------
int main(int argc, char const *argv[]){char str1[] = "abcdefg";char str2[] = "ABCD";char str3[] = "abcdefg";myncpy(str1, str2, 2);printf("str2 拷贝到 str1 的结果为 %s\n", str1);myncpy(str2, str3, 3);printf("str3 拷贝到 str2 的结果为 %s\n", str2);return 0;
}
5)strcat()函数
。strat(字符串1,字符串2)将字符串2中的字符连接到字符串1中。返回的是一个字符指针。
函数声明: char *strcat(char *dest, const char *src)
【代码演示】
//strcat()函数
#include <stdio.h>
#include <string.h>
int mycat(char *str1, const char *str2){//用于复制一个字符串//----------------------------------------------------------------------------------
/*数组写法*/int lenstr1 = strlen(str1);int index = 0, lenstr2 = strlen(str2);//while( str2[index]!= '\0'){while( index < lenstr2){str1[lenstr1+index]=str2[index];index++;}//str1[lenstr1+index] = '\0';str1[lenstr1+index]=str2[index];return str1;
}
//-----------------------------------------------------------------------------------------//-----------------------------------------------------------------------------------------
/*指针写法*/
/*
int lenstr1 = strlen(str1);
while(*str2!='\0'){*(str1 + lenstr1) = *str2;lenstr1++;str2++;//*str1++=*str2++;}*(str1 + lenstr1) = *str2;return *str1;
}*/
//-------------------------------------------------------------------------------------------------int main(){char str1[] = "abcdefg";char str2[] = "ABCD";mycat(str1, str2);printf("str2 拼接到 str1 后的结果为: |%s|\n", str1);return 0;
}
6)strchr()函数
。strchr(字符串1,字符串2)将字符串2中的字符连接到字符串1中。返回的是一个字符指针。
**函数声明: ** char *strchr(const char *str, int c)
【代码演示】
//mychr()
#include <stdio.h>
#include <string.h>char *mychr(const char *str, int c){while(*str){if(*str==c){return (void *)str;break;}str++;}return NULL;
}int main(){char *str = "haohaoxuexi,tiantianxiangshang";char c = 'u';char *ret = NULL;//没有位置指定时好习惯是先指向空位置char *res = NULL;ret = strchr(str, c);printf("使用库函数strchr的返回结果为%s\n", ret);res = mychr(str,c);printf("使用自定义函数mychr的返回结果为%s\n", res);return 0;
}
7)strrchr()函数
。strrchr(字符串,字符)在参数 str 所指向的字符串中搜索最后一次出现字符 c(一个无符号字符)的位置。
**函数声明: ** char *strrchr(const char *str, int c)
【代码演示】
//mychrr()
#include <stdio.h>
#include <string.h>char *mychrr(const char *str, int c){int index= 0; char *str2 = (char *)str;//保持数据类型的一致性while(*str){if(*str==c){index = (str-str2);}str++;}if(index==0){return NULL;}else{return (void *)(str2+index);}
}int main(){char *str = "haohaoxuexi,tiantianxiangshang";char c = 'n';char *ret = NULL;//没有位置指定时好习惯是先指向空位置char *res = NULL;ret = strrchr(str, c);printf("使用库函数strrchr的返回结果为%s\n", ret);res = mychrr(str,c);printf("使用自定义函数mychrr的返回结果为%s\n", res);return 0;
}
8)strstr()函数
。strstr(字符串1,字符串2)在字符串1中查找第一次出现字符串2的位置,不包含终止符 ‘\0’。
**函数声明: ** char *strstr(const char *first, const char *second)
【代码演示】复制链接
//复制自https://blog.51cto.com/thinkerfans/1351064
#include <stdio.h>
#include <string.h>char *mystrstr(const char*, const char*);
char *mystrstr(const char *src, const char *find){if(NULL==src||NULL==find){return NULL;}char *cp = (char *)src;char *s1, *s2;while(*cp){s1 = cp;s2 = (char *)find;while(*s1 && *s2 &&(*s1 == *s2)){s1++, s2++;}if(!*s2){return cp;}cp++;}return NULL;
}int main(){char *src = "hello, china and hello, world";char *find = ",";char *re = mystrstr(src, find);char *res = strstr(src, find);if(re){printf("%s\n", re);}else{printf("no find\n");}printf("%s\n", res);return 0;
}
9)strcasestr()函数
。strcasestr(字符串1,字符串2)同strstr()函数功能一样,区别是strcasestr将大小写都用小写字符来匹配。在字符串1中查找第一次出现字符串2的位置,不包含终止符 ‘\0’。
**函数声明: ** char *strcasestr(const char *first, const char *second)
【代码演示】复制链接
//复制自https://blog.51cto.com/thinkerfans/1351698
#include<stdio.h>
#include <ctype.h>//tolower()函数头文件
#include<string.h>
char * mystrcasestr(const char * ,const char *);
char * mystrcasestr(const char *src, const char *find){if(NULL == src || NULL == find)return NULL;char *cp = (char *)src;char *s1 , *s2;while(*cp){s1 = cp;s2 = (char * )find;while(*s2 && *s1 && !(tolower(*s1) - tolower(*s2)))s1++,s2++;if(!(*s2))return cp;cp++;} return NULL;
}
int main(){char *src = "HeLlO, china and hello,world";char *find = "hElLo,";char *re = mystrcasestr(src,find);if(re)printf("%s\n",re);elseprintf("no find\n"); return 0;
}
10) tolower()函数
。tolower(int 字符)将大写字符转化为小写字符。头文件为#include <ctype.h>
**函数声明: ** int tolower(int c);
//mytolower
//参考自 https://blog.51cto.com/thinkerfans/1351723
#include<stdio.h>
#include<string.h>
#include <ctype.h>
int mytolower(int c){if('A'<=c && 'Z'>=c)return c-'A'+'a';return c;
}
char mytolower2(char c){if('A'<=c && 'Z'>=c)return 'z'-('Z'-c);return c;
}
int main(){char s1[] = "3489 ASDFDF adfdf +-*/";char s2[] = "3489 ASDFDF adfdf +-*/";unsigned int i=0;//int i=0;for(;i < strlen(s1);i++){s1[i] = mytolower2(s1[i]);s2[i] = tolower(s2[i]);}printf("s1=%s\n",s1);printf("s2=%s\n",s2);return 0;
}
11) toupper
。toupper 字符)将小写字符转化为大写字符。头文件为#include <ctype.h>
**函数声明: ** int upper(int c);
//mytoupper
//参考自 https://blog.51cto.com/thinkerfans/1351723
#include<stdio.h>
#include<string.h>
#include <ctype.h>
int mytoupper(int c){if('a'<=c && 'z'>=c)return c-'a'+'A';return c;
}
char mytoupper2(char c){if('a'<=c && 'z'>=c)return 'Z'-('z'-c);return c;
}
int main(){char s1[] = "3489 ASDFDF adfdf +-*/";char s2[] = "3489 ASDFDF adfdf +-*/";unsigned int i=0;//int i=0;for(;i < strlen(s1);i++){s1[i] = mytoupper2(s1[i]);s2[i] = toupper(s2[i]);}printf("s1=%s\n",s1);printf("s2=%s\n",s2);return 0;
}
字符串数组
由多个字符串构成的数组。
- char **a 表示a是一个指针,指向另一个指针,被指向的指针指向一个字符串。
- char a[][] 第二维需要有确切的大小
- char *a[]
代码示例
#include<stdio.h>
int main(){printf("请输入月份:");int month;scanf("%d",&month);char *a[]={"January","February","March","April","May","Jane","July","August","September","Octobor","November","December"};printf("%s\n", a[month-1]); return 0;
}
重要链接
1. http://www.jbox.dk/sanos/source/lib/string.c.html
2. http://www.rowleydownload.co.uk/maxq30/documentation/index.htm?http://www.rowleydownload.co.uk/maxq30/documentation/strcasestr.htm
3. http://www.jbox.dk/sanos/source/lib/ctype.c.html
https://blog.51cto.com/thinkerfans
参考文献
C|菜鸟教程。链接
thinkerfans 博客。链接
C语言学习笔记4---数组、字符串相关推荐
- c语言数组与指针的基础知识,C语言学习笔记之数组与指针的关系
首先,大家先需知道一个关于基类型的概念 基类型:组成一个新类型的基础类型 这句话是什么意思呢?举个例子: int a[3] = {1,2,3}; 上面是由三个int类型的数组成一个新的类型也就是数组, ...
- cpp学习笔记(关于数组+字符串和字符数组)
1.cpp中的数组和java中不大一样,首先cpp中的数组不是对象,无法调用length方法,只能通过计算来得到数组的长度. 一维数组; 而且要么在定义的时候确定数组的长度. 要么在后面初始化的时候确 ...
- C语言如何加缓冲,C语言学习笔记之输出缓冲
在c语言中经常用到输出函数printf,当我们像往常一样在输出函数中输入我们的想要的输出的东西后加\n换行 验证结果如我们输出的一样 如果我们在后面加入死循环会不会出现这些语句呢 结果卡死了,可还是输 ...
- C语言学习笔记09-数组、字符数组、字符串数组、二维数组(单字符输入输出putchar、getchar,字符串输入输出的scanf、gets、puts)
C语言数组 数组作用:可以用来保存很多记录(可以看成一种大容器).一些简单游戏也基本由数组实现,如游戏地图(二维数组)等等. 一个数组 划分 多个单元(下标区分) -存放-> 多个同类元 ...
- C语言学习笔记10-指针(动态内存分配malloc/calloc、realloc、释放free,可变数组实现;Tips:返回指针的函数使用本地变量有风险!;最后:函数指针)
C语言:指针 1. 指针:保存地址的变量 *p (pointer) ,这种变量的值是内存的地址. 取地址符& 只用于获取变量(有地址的东西)的地址:scanf函数-取地址符 地址的大小 ...
- c语言中void arrout,c语言学习笔记(数组、函数
<c语言学习笔记(数组.函数>由会员分享,可在线阅读,更多相关<c语言学习笔记(数组.函数(53页珍藏版)>请在人人文库网上搜索. 1.数组2010-3-29 22:40一维数 ...
- Go语言学习笔记-数组、切片、map
Go语言学习笔记-数组.切片.map 数组:同一数据类型元素的集合.是值类型,长度固定无法修改 声明格式:var 数组名字 [元素数量] 数据类型 var arr [3] int //声明定义了一个长 ...
- 梓益C语言学习笔记之指针
梓益C语言学习笔记之指针 一.32位平台下,地址是32位,所以指针变量占32位,共4个字节 二.内存单元的地址即为指针,存放指针的变量称为指针变量,故:"指针"是指地址,是常量,& ...
- go get 拉取指定版本_go语言学习笔记-基础知识-3
相关文档 go语言学习笔记-目录 1.简介 1.1 什么是GO Go 是一个开源的编程语言,它能让构造简单.可靠且高效的软件变得容易.Go是从2007年末由Robert Griesemer, Rob ...
- C语言学习笔记-P1 初识C语言(2)
C语言学习笔记-P1 初识C语言(2) C语言学习笔记-P1 初识C语言(2) 一.常量 1.字面常量 2.const修饰的常变量 3.#define定义的标识符常量 3.枚举常量 二.字符串+转义字 ...
最新文章
- 从DDD DSL DCI 说起
- quartusII中功能仿真和时序仿真的分析
- tensorflow2 存取模型_思维导图:长短期记忆模型
- 4.MATLAB基础编程操作——变量、常量、基础数学运算
- matlab循环标注,for循环
- php session 回收,关于php session gc回收的问题
- github 搜索_Fzf:Golang开发的Github高星系统模糊搜索补全工具
- SAP UI5 view.bindElement will also trigger an odata request
- linux nginx 系统服务,linux 把nginx加入到系统服务的方法
- IE中如何屏蔽窗口关闭
- mysql未监控在3306_监控MySQL或Web服务是否正常
- clion stfp 配置
- e.style.opacity 通过javascript调用元素的样式属性
- linux加密认证全面分析
- Android进阶(九)APP编程感想
- 银河麒麟(linux)wireshark 打开抓包报错 The capture session could not be initiated on interface ‘enp2s0‘(You...
- 处理 yarn 项目 has unmet peer dependency
- 【C语言细节】计算自然对数的底 e遇坑
- word从任意页开始加页码
- 为什么你学过Java却忘光了——记第一次助教同学见面会,java开发面试笔试题