1.字符串的储存
字符串的存储:
只要最后一个为‘\0’就代表结束了,注意哈要给’\0’分配一个空间。
2.字符指针
字符指针是指向字符型数据的指针变量。字符串字面量本身代表的就是存放它的常量存储区的首地址。
char *ptr = "hello";
与
char *ptr;
ptr = "Hello";
等价
同时
char *ptr;
ptr = str;//等价于 ptr = &str[0]
3.字符串的访问和输出\输入
1.如何访问字符串中的单个字符
str[0]就表示第一个字符,str[1]表示第二个字符。
还可以通过间接访问的方式来访问单个字符。例如,ptr指向了字符串数组str的首地址,通过*(ptr+i)的方式访问第i+1个字符,*(ptr + i) = *(str + i) = str[i],也可以通过ptr++操作,即移动指针ptr,使ptr指向字符串中的某个字符。(注意,对于字符串数组不能使用str++操作使其指向字符串中的某个字符,因为数组名是一个地址常量,其值是不能改变的。)
2.字符串的输入\输出
三种方式:
(1)按c格式符,一个一个字符单独输入\输出。
for(i = 0;i < 10;i++)
{
scanf("%c",&str[i]);
}
for(i = 0;i < 10;i++)
{
printf("%c",str[i]);
}
由于字符串长度与字符数组的大小通常并不是完全一致的,因此很少用这种方法,一般都是以“\0”作为标志,识别字符串的结束。
for(i = 0 ; str[i] ! = '\0' ; i++)
{
printf("%c",str[i]);
}
(2)按s格式符,将字符串作为一个整体输入\输出。
scanf("%s",str);
printf("%s",str);
#include
#define N 12
int main()
{
char name[N];
printf("Enter your name:");
scanf("%s",name);
printf("Hello %s!\n",name);
scanf("%s",name);//读取输入缓冲区余下的上次未被读走的字符
printf("Hello %s!\n",name);
}
第一个scanf语句将输入字符串空格前面的字符串读到数组name中,然后由第8行语句打印出第一个“Hello”信息。第九行将输入缓冲区中余下的上次未被读走的空格后面的字符串重新读到数组name中,然后由将第十行语句打印出第二个“Hello"信息。
用%d输入数字或%c输入字符串时,忽略空格、回车或制表符等空白字符(被作为数据的分隔符),读到这些字符是,系统认为数据读入结束,因此用scanf()按s格式符不能输入带空格的字符串。
(3)使用字符串处理函数Gets(),可以输入带空格的字符串。
此外,gets()和scanf()对回车符号的处理也不同。gets()以回车符作为字符串的终止符,同时将回车符从输入缓冲区读走,但不作为字符串的一部分。而scanf()不读走回车符,回车符仍留在输入缓冲区内。
#include
#define N 12
int main()
{
char name[N];
printf("Enter your name:");
gets(name);
printf("Hello %s!\n",name);
return 0;
}
也可也用puts()输出字符串。(函数puts()用于从括号内的参数给出的地址开始,依次输出储存单元的字符,当遇到第一个’\0’时输出结束,并且自动输出一个换行符。puts()唯一不足就是不能像函数printf()那样在输出行中增加一些其它字符信息(如“Hello")并控制输出的格式。
#include
#define N 12
int main()
{
char name[N];
char *ptrName = name;
printf("Enter your name:");
gets(ptrName);
printf("Hello %s!\n",ptrName);
return 0;
}
用字符指针输入字符串是时,必须确保字符指针事先已经指向一个数组的首地址,如本例字符指针变量ptrName指向数组name,但如果删掉第5行语句,并将第六行修改为 char *ptrName;
的话,那么ptrName就会导致非法内存访问错误。
根本原因在于,函数gets()不能限制输入字符串的长度,很容易引起缓冲区溢出,从而黑客攻击以可乘之机。同样scanf()函数也有这个问题,即使使用了带格式的控制的形式,如scanf("%12s",name),也不能直接真正解决这个问题。所以用scanf()和gets输入字符串时,要确保输入字符串的长度不超过数组大小,否则建议使用能限制字符串长度的函数,即:
fgets(name,sizeof(name),stdin);
最后一个问题,如何在一个字符串中包含双引号?
要用到转义字符,即在这个双引号的前面加上一个反斜杠()。
4.字符串处理函数
编程实现按奥运会参赛国国名在字典排序对其出场次序进行排序。假设参赛国不超过150个。
#include
#include
#define MAX_LEN 10
#define N 150
void SortString(char str[][MAX_LEN],int n);
int main()
{
int i,n;
char name[N][MAX_LEN];
printf("How many countries?");
scanf("%d",&n);
getchar();
printf("Input their names:\n");
for(i = 0; i < n; i++)
{
gets(name[i]);
}
SortString(name,n);
printf("Sorted results:\n");
for( i = 0;i < n;i++)
{
puts(name[i]);
}
return 0;
}
void SortString(char str[][MAX_LEN],int n)
{
int i,j;
char temp[MAX_LEN];
for(i = 0;i < n-1;i++)
{
for(j = i+1;j < n; j++)
{
if(strcmp(str[j],str[i])<0)
{
strcpy(temp,str[i]);
strcpy(str[i],str[j]);
strcpy(str[j],temp);
}
}
}
}
上面式子中用到的strcmp(_)函数,就是比较字符串的大小,字符串比较大小时,实际上是根据两字符对比时出现的第一对不相等的字符的大小来决定他们所在字符串的大小的。
5.从函数返回字符串指针
return 只能从函数返回一个值,如何从函数返回一组值?
一种常见的方法是利用数组或者指针作为函数参数,通过传地址调用来获得这些数据,还有一种就是通过返回指针值的函数来返回一个地址值,即指向存储这些数据的一段连续内存空间的首地址,从而活得这些数据。
区分函数指针和指针函数
https://blog.csdn.net/Cuienjie/article/details/106783086?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159636200619724835802430%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=159636200619724835802430&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-1-106783086.first_rank_v2_rank_v25&utm_term=%E5%87%BD%E6%95%B0%E6%8C%87%E9%92%88%E4%B8%8E%E6%8C%87%E9%92%88%E5%87%BD%E6%95%B0%E7%9A%84%E5%8C%BA%E5%88%AB&spm=1018.2118.3001.4187
不使用字符串处理函数strcat(),编程实现strcat()的功能
#include
#define N 80
char *MyStrcat(char *dstStr,char *srcStr);
int main()
{
char first[2*N];
char second[N];
printf("Input the first string:");
gets(first);
printf("Input the second string:");
gets(second);
printf("The results is:%s\n",MyStrcat(first,second));
return 0;
}
//函数功能:将字符串srcStr连接到字符串dsStr后面
char *MyStrcat(char *dstStr,char *srcStr)
{
char *ptr = *dstStr;//保存字符串dstStr首地址
//将指针移动到字符串dsStr的末尾
while(*dstStr != '\0')
{
dstStr++;
}
//将字符串srcStr复制到字符串dsStr的后面
for(;*srcStr != '\0';dstStr++,srcStr++)
{
*dstStr = *srcStr;
}
*dstStr = '\0';//在连接后的字符串的末尾添加字符串结束标志
return ptr;//返回连接后的字符串dsStr的首地址
}
6.补充内容
1.const 类型限定符
(1)const放在类型关键字的前面
const全称constant,意外不可修改的。也就是说const常量为只读常量,无法被修改。
int a,b;
const int *p = &a;
虽然这里 ✳p的值是不可修改的,但p指向的变量a的值仍然是可以修改的,即对a执行赋值操作是合法的。因指针变量p的值是可以修改的,所以如果执行p = &b也是合法的,经过这个赋值知之后,指针变量p就不再向指向变量a而指向变量b.
(2)const 放在类型关键字的后面和*变量名的前面
int const *p = &a;
按照从右往左的顺序,可将这条变量声明语句读作:“p是一个变量指针,可指向一个常量整数”。它表明**p是一个常量,而p不是。由于*p是只读的,所以不饿能使用指针变量p修改这个“为常量的整形数”。
(3)const放在类型关键字 ✳的后面,变量名的前面
int* const p = &a;
按照从右到左的顺序,可将这条变量声明语句读作(p是一个指针常量,可以指向一个整型数据。它表明p是一个常量,而✳p不是。由于p是一个常量指针,是只读的,其值是不可以被修改的,所以在程序中不能修改指针p,让它指向其它变量,但是它所指向的变量的值是可以修改的。
(4)一个const放在类型关键字之前,另一个const放在类型关键字✳之后和变量名之前。
const int* const p = &a;
按照从右到左的顺序,可将这条变量声明语句读作:“p是一个指针常量,可指向一个整型常量,它表明p和✳p都是一个常量,都是只读的。这时,无论执行*p = 20还是执行 p = &b这样的赋值操作,都将被视为非法操作。
以上四种用法中第一种较为常见,C语言的许多标准库函数都在函数的某些指针参数的类型前加入了const限定符,目的就是只允许函数访问该指针参数指向的地址单元中的内容。
2.字符串处理函数
字符串处理函数库中包含了对于字符数据进行测试和操作的标准库函数,使用这些函数时,必须在程序开头包含头文件
(1)输入一行数据,统计其中的英文字符、数字字符、空格和其他字符的个数。
#include
#define N 80
int main()
{
char str[N];
int i,letter = 0,digit = 0,space = 0,others = 0;
printf("Input a string:");
gets(str);
for(i = 0; str[i] !='\0';i++)
{
if(str[i] >= 'a'&&str[i] <= 'z'||str[i] >= 'A'&&str[i] <= 'Z')
letter++;
else if(str[i] >= '0'&&str[i] <= '9' )
digit++;
else if(str[i] == ' ')
space++;
else
others++;
}
printf("English character:%d\n",letter);
printf("digit character:%d\n",digit);
printf("space character:%d\n",space);
printf("other character:%d\n",others);
return 0;
}
如果用字符串处理函数,就可以成为
#include
#include
#define N 80
int main()
{
char str[N];
int i,letter = 0,digit = 0,space = 0,others = 0;
printf("Input a string:");
gets(str);
for(i = 0; str[i] !='\0';i++)
{
if(isalpha(str[i]))
letter++;
else if(isdigit(str[i]))
digit++;
else if(isspace(str[i]))
space++;
else
others++;
}
printf("English character:%d\n",letter);
printf("digit character:%d\n",digit);
printf("space character:%d\n",space);
printf("other character:%d\n",others);
return 0;
}
从键盘键入一个人的英文名和姓名的第一个字母都变成大写字母。
#include
#define N 80
int main()
{
char str[N];
int i,k;
printf("Please Input a name:");
gets(str);
while(str[i] !=' ')
{
i++;
}
k = i;
str[0] = str[0] - 32;
str[k+1] = str[k+1] - 32;
puts(str);
}
用字符串处理函数
#include
#include
#define N 80
int main()
{
char name[N];
int i,k;
printf("Please Input a name:");
gets(name);//输入姓名
name[0] = toupper(name[0]);//首字母变为大写
i = 1;
while(!isspace(name[i]))//跳过所有字母,直到遇到空格为止
{
i++;
}
while(!isalpha(name[i]))//跳过所有字母,直到遇到字母为止
{
i++;
}
name[i] = toupper(name[i]);//将姓的首字母变为大写
printf("Formatted Name:%s\n",name);
return 0;
}
3.数值字符串向数值转换
C语言提供的字符串转换函数可将数字字符串转换为整型或浮点型的数值,使用这些函数时,头文件必须包括
#include
#include
int main()
{
char str[]={" 123.5"};
int intNum;
long longNum;
double doubleNum;
printf("intNum = %d\n",intNum);
printf("longNum = %d\n",longNum);
printf("doubleNum = %f\n",doubleNum);
}