参考书:《C Primer Plus》第六版
文章目录
- @[toc]
- 1. 表示字符串和字符串I/O
- 定义字符串
- 2. 字符串输入
- 3. 字符串输出
- 4. 自定义输入/输出函数
- 5. 字符串函数
- 6. 命令行参数
- 7. 把字符串转换为数字
- 8. 编程练习
1. 表示字符串和字符串I/O
首先看一下程序清单1:
#include <stdio.h>
int main(void){
char words[81]="I am a string in an array.";
const char *p1="Something is pointing at me.";
puts("Here are some strings :");
puts("I am a symbolic string constant.");
puts(words);
puts(p1);
words[8]='p';
puts(words);
return 0;
}
输出
Here are some strings :
I am a symbolic string constant.
I am a string in an array.
Something is pointing at me.
I am a spring in an array.
其中,puts()函数与printf()不同之处在于它会在字符串末尾加上换行符。
定义字符串
用双引号括起来的内容叫做字符串字面值或者字符串常量。双引号中的内容和编译器自动加入末尾的\0
字符都作为字符串存储在内存中。如果字符串中间没有间隔或者只有空白字符,C会将其视为串联起来的字符串字面值。
如char greeting[50]="hello" ",and how are you today";
字符串数组的定义和一般数组类似:
const char m1[50]="Limit yourself to one line's worth.";
const char m2[40]={'L','i','m','i','\0'};//其他元素被初始化为\0
注意标准数组初始化时一定要有最后的空字符\0
,没有它的话就只是一个字符数组而不是字符串。
字符数组名也是数组首元素地址。
编译器将数组名识别为数组首元素地址别名,以后不能更改它。随意递增、递减运算都是不允许的。但指针形式是可以改变的。所以要说指针形式和数组形式的差别,差别主要在这。
程序清单2:
#include "stdio.h"
#define MSG "I'm special"
int main(void){
char ar[]=MSG;
char const *pr=MSG;
printf("address of \"I'm special\": %p\n","I'm special");
printf("address ar: %p\n",ar);
printf("address pr: %p\n",pr);
printf("address of MSG: %p\n",MSG);
printf("address of \"I'm special\":%p\n","I'm special");
return 0;
}
address of "I'm special": 0x7fd1344c3004
address ar: 0x7fffcd36b77c
address pr: 0x7fd1344c3004
address of MSG: 0x7fd1344c3004
address of "I'm special":0x7fd1344c3004
通过程序清单2的输出可以看出,pt和MSG的地址相同,而ar不同。
2. 字符串输入
程序清单3:
#include"stdio.h"
int main(void){
char words[81];
puts("Enter a string,please.");
fgets(words,81,stdin);
printf("Your string twice:\n");
puts(words);
puts("Done.");
return 0;
}
Enter a string,please.
I want to learn about string theory.
Your string twice:
I want to learn about string theory.
Done.
其中用到的是fgets()
函数作为输入函数。它是gets()
的替代品。因为gets()
被认为存在安全隐患,所以所以在新标准中直接废除了gets()
函数。fgets()
函数需要输入3个参数,第二个参数指明读入字符的最大数量,第三个参数指明要读入的文件。从键盘读入就以stdin
作为参数。相对应的可以用fputs()
函数输出,fputs()
函数的第二个参数指明它要写入的文件,打印出来的话用stdout
作为参数。
另一个gets()
的替代品是gets_s(words,stlen)
。它只从标准输入读取数据,所以不需要第三个参数。
3. 字符串输出
- puts()
- fputs()
- printf()
4. 自定义输入/输出函数
5. 字符串函数
C库提供了很多处理字符串的函数,它们定义在头文件string.h
中。常用的有:strlen()
、strcat()
、strcmp()
、strncmp
、strcpy
、strncpy()
。另外还有sprintf()
函数定义在头文件stdio.h
中。
程序清单4:
#include"stdio.h"
#include"string.h"
int main(void){
char mesg[30]="123456789";
printf("length of mesg: %ld\n",strlen(mesg));
printf("sizeof mesg /sizeof char =%ld \n",sizeof mesg / sizeof mesg[0] );
char test[]="abcdefg";
strcat(mesg,test);//字符串拼接
puts(mesg);
puts(test);
strncat(mesg,test,3);//字符串拼接,同时指定拼接的字符数
puts(mesg);
printf("strcmp(A,A)= %d\n",strcmp("A","A"));//比较两个字符串,相等为0
printf("strcmp(A,C)= %d\n",strcmp("A","C"));
printf("strcmp(mesg,test)=%d\n",strcmp(mesg,test));
printf("strncmp(mesg,test)=%d\n",strncmp(mesg,test,6));//限定比较前几个字符
char cp[40];
strcpy(cp,"teststest");//拷贝字符串
puts(cp);
strcpy(cp,mesg);
puts(cp);
strncpy(cp,mesg,10);
puts(cp);
char f[40];
sprintf(f,"%s the world %d %.1f %%","rerorero",4396,2.2); //类似于printf,但它是将内容写入字符串变量中
puts(f);
return 0;
}
length of mesg: 9
sizeof mesg /sizeof char =30
123456789abcdefg
abcdefg
123456789abcdefgabc
strcmp(A,A)= 0
strcmp(A,C)= -1
strcmp(mesg,test)=-48
strncmp(mesg,test)=-48
teststest
123456789abcdefgabc
123456789abcdefgabc
rerorero the world 4396 2.2 %
6. 命令行参数
命令行参数是在命令行环境中用户为运行程序输入的命令行。它不是必要的,但至少要了解有这回事。如下
程序清单5:
#include<stdio.h>
int main(int argc, char** argv ){
int count;
printf("The command line has %d arguments: \n",argc-1);
for(count=1;count<argc;++count)
printf("%d: %s\n",count,argv[count]);
printf("\n");
return 0;
}
root@DESKTOP-202JI6K:/mnt/c/zd# make repeat
cc repeat.c -o repeat
root@DESKTOP-202JI6K:/mnt/c/zd# ./repeat
The command line has 0 arguments:
root@DESKTOP-202JI6K:/mnt/c/zd# ./repeat resistance is futile
The command line has 3 arguments:
1: resistance
2: is
3: futile
7. 把字符串转换为数字
用atoi()
将字母数字转换为整数,转换失败会返回0。也可以用更安全的strtol()
。atof()
和atol()
则分别是把字符串转换为double和long。strtol()
把字符串转换为long,strtoul()
把字符串转换为unsigned long,strtod()
把字符串转换为double。这些函数更智能之处在于它们识别和报告字符串中的首字符是否是数字。strtol()
和strtoul()
还可以指定数字的进制。这些函数定义在头文件stdlib.h
中。
程序清单6:
#include<stdio.h>
#include"stdlib.h"
int main(){
char numbers[50];
char *end;
long value=1;
puts("Enter a number (empty line to quit):");
fgets(numbers,50,stdin);
value=strtol(numbers,&end,10);
while(value!=0){
printf("%ld\n",value);
printf("Next number.\n");
fgets(numbers,50,stdin);
value=strtol(numbers,&end,10);
}
}
root@DESKTOP-202JI6K:/mnt/c/zd# make strcnvt
cc strcnvt.c -o strcnvt
root@DESKTOP-202JI6K:/mnt/c/zd# ./strcnvt
Enter a number (empty line to quit):
123
123
Next number.
12312
12312
Next number.
21a
21
Next number.
a
8. 编程练习
#include<stdio.h>
void store(char *ps,int n){
char ch;
int t=0;
while((ch=getchar())!=EOF &&t++<n){
*(ps+t)=ch;
}
*(ps+t)='\0';
}
int main(void){
char arr[50];
puts("Enter strings:");
store(arr,50);
puts("\nString:");
puts(arr);
return 0;
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# make prac1
cc prac1.c -o prac1
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# ./prac1
Enter strings:
alsdfkjasdklgfj;asdf skadflm mkcx.vmapsdf.;'slf;a';d'sfa'w;e
String:
alsdfkjasdklgfj;asdf skadflm mkcx.vmapsdf.;'slf;a'
#include<stdio.h>
void store(char *ps,int n){
char ch;
int t=0;
ch=getchar();
while(ch!=EOF &&ch!=' ' &&ch!='\n' &&ch!='\v' &&ch!='\t' &&t++<n){
*(ps+t)=ch;
ch=getchar();
}
*(ps+t)='\0';
}
int main(void){
char arr[50];
puts("Enter strings:");
store(arr,50);
puts("\nString:");
puts(arr);
return 0;
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# ./prac1
Enter strings:
asdfsadflkasd sadkflj slkdfawerasdfklas
String:
asdfsadflkas
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code#
- 设计一个函数从一行中读取一个单词。
#include"stdio.h"
#include<ctype.h>
void read_word(char *ps,int max){
char* pc;
char temp[50];
char ch;
int t=0;
while((ch=getchar())!='\n' &&t++<max){
*(temp+t)=ch;
}
*(temp+t+1)='\0';
//puts(temp);
pc=temp;
int i=0;
while(isspace(*pc))
*pc++;
while(*pc!='\0' && i<max){
if(*pc!='\v'&&*pc!='\t' && *pc!='\n' &&*pc!=' ')
*(ps+i++)=*pc;
else
break;
pc++;
}
*(ps+i+1)='\0';
}
int main(void){
char arr[50];
puts("Enter a word:");
read_word(arr,50);
puts("\n The word is: ");
puts(arr);
return 0;
}
Enter a word:
as dfasdf
The word is:
as
- (6)编写一个函数接受一个字符和一个字符串判读该字符是否在字符串中
#include"stdio.h"
int is_within(char ch,char *pstr){
while(*pstr++!='\0'){
if(*pstr==ch)
return 1;
}
return 0;
}
int main(){
puts("Enter a word:");
char arr[50];
fgets(arr,50,stdin);
puts("Enter a char to check:(ctrl+D to quit)");
char ch;
while((ch=getchar())!=EOF){
if(is_within(ch,arr))
puts("ch is in arr");
else
puts("ch is not in arr");
puts("Enter another word: ");
getchar();
fgets(arr,50,stdin);
puts("Enter a char to check:(ctrl+D to quit)");
}
return 0;
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# make prac6
cc prac6.c -o prac6
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# ./prac6
Enter a word:
tttssddd
Enter a char to check:(ctrl+D to quit)
d
ch is in arr
Enter another word:
assdff
Enter a char to check:(ctrl+D to quit)
s
ch is in arr
Enter another word:
asdfss
Enter a char to check:(ctrl+D to quit)
w
ch is not in arr
Enter another word:
Enter a char to check:(ctrl+D to quit)
- 拷贝字符串
#include<stdio.h>
char * mystrncpy(char *s1,char *s2,int n){
char *ps=s1;
int i=0;
while(*s2!='\0'&& i++<n){
*ps++=*s2++;
}
*ps='\0';
return s1;
}
int main(){
char arr[50];
char arr1[50];
puts("Enter string: ");
while(fgets(arr1,50,stdin)!=0){
puts(mystrncpy(arr,arr1,50));
puts("Enter string: ");
}
return 0;
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# ./prac7
Enter string:
asdfasdf
asdfasdf
Enter string:
asdfwerasdfasdf
asdfwerasdfasdf
Enter string:
asdfasdfas dfasd
asdfasdfas dfasd
Enter string:
asdfasdfas
asdfasdfas
Enter string:
asdfasdf
asdfasdf
Enter string:
s dfasdf asdf
s dfasdf asdf
Enter string:
- 编写一个函数判断一个字符串中是否包含另一个字符串
#include<stdio.h>
char * string_in(char *s1,char *s2){
char *ps2=s2,*ps1=s1;
while(*s1!='\0'){
if(*s1==*s2){
ps2=s2;
ps1=s1;
while(*ps1++==*ps2++);
if(*ps2=='\0')
return s1;
}
s1++;
}
return NULL;
}
int main(){
puts("Enter the first string :");
char str1[50],str2[50];
fgets(str1,50,stdin);
puts("Enter the second string :");
char *result=NULL;
while(fgets(str2,50,stdin)!=0){
if((result=string_in(str1,str2))!=NULL)
printf("str2 in str1,the index is at %ld\n",result-str1);
else
puts("str2 not in str1.\n");
puts("Then, enter the first string: ");
fgets(str1,50,stdin);
puts("Enter the second string :");
}
puts("Bye.");
return 0;
}
Enter the first string :
hats
Enter the second string :
at
str2 in str1,the index is at 1
Then, enter the first string:
abstact
Enter the second string :
ac
str2 in str1,the index is at 4
Then, enter the first string:
12345
Enter the second string :
3
str2 in str1,the index is at 2
Then, enter the first string:
Enter the second string :
Bye.
- 将字符串反序
#include"stdio.h"
void reverse(char *ps){
int i=0;
while(*(ps+i++)!='\0');
int len=i-2;
for(int j=0;j<len/2;j++){
char temp=*(ps+j);
*(ps+j)=*(ps+len-j-1);
*(ps+len-j-1)=temp;
}
}
int main(){
puts("Enter a string: ");
char str[50];
while(fgets(str,50,stdin)!=0){
reverse(str);
puts(str);
puts("Enter another string: ");
}
puts("Bye.");
return 0;
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# ./prac9
Enter a string:
12345
54321
Enter another string:
123456
654321
Enter another string:
LGD
DGL
Enter another string:
Bye.
- 编写一个函数删除字符串中的空格
#include"stdio.h"
void delspace(char* s){
char *ps=s;
char str[50];
int i=0;
while(*ps!='\0'){
if(*ps!=' ')
str[i++]=*ps;
ps++;
}
str[i]='\0';
ps=str;
i=0;
while(*ps!='\0')
s[i++]=*ps++;
s[i]='\0';
}
int main(){
char arr[50];
puts("Enter a string : ");
while(fgets(arr,50,stdin)!=0){
delspace(arr);
puts(arr);
puts("Enter another string: ");
}
puts("Bye.");
return 0;
}
Enter a string :
asdfasdf
asdfasdf
Enter another string:
asdfasdfasd fasdf
asdfasdfasdfasdf
Enter another string:
asdf asdf asdfa
asdfasdfasdfa
Enter another string:
123 345
123345
Enter another string:
Bye.
#include"stdio.h"
#include"string.h"
char * get_word(char *str){
char st[30];
char *pstr=st;
while(*str++==' ');
while(*str!='\0' &&*str!='\v'&&*str!='\t' &&*str!='\n'){
*pstr++=*str++;
}
char *ch=st;
return ch;
}
int main(){
int times=0;
char strings[10][30];
char str[30];
char copy[10][30];
char ch='a';
printf("请输入第 %d 个字符串:",times+1);
while(fgets(str,30,stdin)!=0 && times<10){
strcpy(strings[times++],str);
printf("请输入第 %d 个字符串:",times+1);
}
printf("共输入了 %d 个字符串。",times);
puts("select:");
puts("a. print all strings b. sort by ASCII and print all ");
puts("c. sort by length and print all d. sort by the first word of string and print all");
puts("q. exit");
while ((ch=getchar())!='q')
{
switch (ch)
{
case 'a':
puts("strings :");
for(int x=0;x<times;++x)
printf("%d: %s",x,strings[x]);
break;
case 'b':
for(int i=0;i<times;++i)
strcpy(copy[i],strings[i]);
for(int x=0;x<times-1;++x){
for(int y=x+1;y<times;++y){
if(strcmp(copy[x],copy[y])>0){
char strs[30];
strcpy(strs,copy[x]);
strcpy(copy[x],copy[y]);
strcpy(copy[y],strs);
}
}
}
puts("strings :");
for(int x=0;x<times;++x)
printf("%d: %s",x,copy[x]);
break;
case 'c':
for(int i=0;i<times;++i)
strcpy(copy[i],strings[i]);
for(int x=0;x<times-1;++x){
for(int y=x+1;y<times;++y){
if(strlen(copy[x])>strlen(copy[y])){
char strs[30];
strcpy(strs,copy[x]);
strcpy(copy[x],copy[y]);
strcpy(copy[y],strs);
}
}
}
puts("strings :");
for(int x=0;x<times;++x)
printf("%d: %s",x,copy[x]);
break;
case 'd':
for(int i=0;i<times;++i)
strcpy(copy[i],strings[i]);
for(int x=0;x<times-1;++x){
for(int y=x+1;y<times;++y){
if(strcmp(get_word(copy[x]),get_word(copy[y]))>0){
char strs[30];
strcpy(strs,copy[x]);
strcpy(copy[x],copy[y]);
strcpy(copy[y],strs);
}
}
}
puts("strings :");
for(int x=0;x<times;++x)
printf("%d: %s",x,copy[x]);
break;
default:
break;
}
}
puts("Bye.");
return 0;
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# ./prac11
请输入第 1 个字符串:asdfnasdfkj asdfa sdf
请输入第 2 个字符串:asdfasd asdf we
请输入第 3 个字符串:werq4
请输入第 4 个字符串:adf214
请输入第 5 个字符串:a12341
请输入第 6 个字符串:1241234
请输入第 7 个字符串:ghdfgh
请输入第 8 个字符串:asdf
请输入第 9 个字符串:w342
请输入第 10 个字符串:sdftg
请输入第 11 个字符串:qwrew
共输入了 10 个字符串。select:
a. print all strings b. sort by ASCII and print all
c. sort by length and print all d. sort by the first word of string and print all
q. exit
a
strings :
0: asdfnasdfkj asdfa sdf
1: asdfasd asdf we
2: werq4
3: adf214
4: a12341
5: 1241234
6: ghdfgh
7: asdf
8: w342
9: sdftg
b
strings :
0: 1241234
1: a12341
2: adf214
3: asdf
4: asdfasd asdf we
5: asdfnasdfkj asdfa sdf
6: ghdfgh
7: sdftg
8: w342
9: werq4
c
strings :
0: asdf
1: w342
2: sdftg
3: ghdfgh
4: werq4
5: adf214
6: a12341
7: 1241234
8: asdfasd asdf we
9: asdfnasdfkj asdfa sdf
d
strings :
0: asdfnasdfkj asdfa sdf
1: asdfasd asdf we
2: werq4
3: adf214
4: a12341
5: 1241234
6: ghdfgh
7: asdf
8: w342
9: sdftg
a
strings :
0: asdfnasdfkj asdfa sdf
1: asdfasd asdf we
2: werq4
3: adf214
4: a12341
5: 1241234
6: ghdfgh
7: asdf
8: w342
9: sdftg
q
Bye.
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code#
- 编写一个程序,统计读入的单词数,大写字母数、小写字母数、标点符号数和数字数。
#include<stdio.h>
#include<ctype.h>
int main(){
char ch;
char strings[50];
char *pstr=strings;
int i=0;
while((ch=getchar())!= EOF && i++<50)
*pstr++=ch;
*pstr='\0';
pstr=strings;
int word_n=0,upper_n=0,lower_n=0,punct_n=0,digit_n=0;
int not_word=0;
while(*pstr!='\0'){
if(islower(*pstr)) lower_n++;
if(isupper(*pstr)) upper_n++;
if(ispunct(*pstr))punct_n++;
if(isdigit(*pstr))digit_n++;
if(isalpha(*pstr) &¬_word++==0)word_n++;
if(!isalpha(*pstr))not_word=0;
pstr++;
}
printf("单词数:%d,大写字母数:%d,小写字母数:%d,标点符号数:%d,数字数:%d。\n",word_n,upper_n,lower_n,punct_n,digit_n);
return 0;
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# ./prac12
alskdfkasuiwr234 2342poi42p3o435,.;'.'/a'sd.f dfas352345dfg asfxzcv
单词数:8,大写字母数:0,小写字母数:26,标点符号数:9,数字数:13。
- 编写一个程序反序显示命令行参数的单词。
#include"stdio.h"
int main(int argc,char ** argv){
printf("共输入了 %d 个参数\n",argc-1);
for(int i=0;i<argc-1;i++)
printf("%s ",argv[argc-1-i]);
puts("\nBye.");
return 0;
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# ./prac13 see you again
共输入了 3 个参数
again you see
Bye.
- 编写一个程序通过命令行计算幂
#include"stdio.h"
#include"stdlib.h"
int main(int argc,char **argv){
if(argc>2){
double d=atof(argv[1]);
int n=atoi(argv[2]);
double sum=d;
if(n<0){
n=-n;
d=1/d;
}
if(n==0)sum=1.;
for(int i=1;i<n;i++)
sum*=d;
printf("%.3lf ^%d= %.3lf\n",d,n,sum);
}else
{
printf("无效输入\n");
}
return 0;
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# ./prac14 1.1 10
1.100 ^10= 2.594
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# ./prac14 2.5 10
2.500 ^10= 9536.743
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# ./prac14 2.5 1
2.500 ^1= 2.500
- 编写一个程序,用字符分类函数实现
atoi
函数。
#include"stdio.h"
#include"ctype.h"
int my_atoi(char *str){
char *pstr=str;
int I=0,k=1;
while(*pstr!='\0'&&*pstr!='\n')pstr++;
while(pstr--!=str){
if(!isdigit(*pstr))
return 0;
else{
int num=(*pstr)-'1'+1;
I+=num*k;
k*=10;
}
}
return I;
}
int main(){
char str[50];
puts("Enter a Integer:");
int val;
while(fgets(str,50,stdin)!=0){
if((val=my_atoi(str))!=0)
printf("The value is : %d\n",val);
else
puts("invalid input.");
puts("Enter another integer:");
}
return 0;
}
Enter a Integer:
123123123
The value is : 123123123
Enter another integer:
1232134
The value is : 1232134
Enter another integer:
asdf234
invalid input.
Enter another integer:
- 编写一个程序读取输入,然后根据命令行参数打印文件内容。
#include"stdio.h"
#include"ctype.h"
int main(int argc,char **argv){
char sty='p';
if(argc>1)
if(argv[1][0]='-')sty=argv[1][1];
char ch;
switch (sty)
{
case 'p':
while((ch=getchar())!=EOF){
putchar(ch);
}
break;
case 'u':
while((ch=getchar())!=EOF){
putchar(toupper(ch));
}
break;
case 'l':
while((ch=getchar())!=EOF){
putchar(tolower(ch));
}
break;
default:
break;
}
return 0;
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code# ./prac16 < text.txt -u
DON'T FORGET, A PERSON'S GREATEST EMOTIONAL NEED IS TO FEEL APPRECIATED.