第9章 字符串
- 字符串的输入与输出
int ch; char strings[80]; FILE *input;
(1)scanf(“%c”,&ch); printf(“%c \n”,ch); (输入字符串时自动添加’\0’)
(2)ch = getchar(); putchar(ch);
(3)gets( strings ); puts( strings ); (输入字符串时自动添加’\0’)
(4)fgets( strings, 80, stdin); fputs( strings, stdout);
(5)fscanf (input, “%d %d”, &a , &b );
fprintf (input, “%d %d”, a , b );
(6)ch = getc ( input ); putc ( ch, input );
(7)sprintf() 主要针对字符串操作
1)数字字符串操作:sprinf( strings, “%d%d”,124,243); 产生字符串:124243
2)控制浮点数打印格式:%f 默认保留小数点后6位,
sprintf(strings, “%f”,3.1415923); 产生:3.141593
3)连接字符串:在许多场合可以替代strcat()函数
char *who=”I”; char *whom=”English”;
sprintf(strings, “%s love %s”,who, whom);
结果:”I love English”
4)返回本次函数调用最终打印到字符缓冲区的字符数目
(8)sscanf() 可以从字符串中取出整数、浮点数和字符串等。
1)提取字符串:sscanf( “123456”, “%s”, strings); strings: 123456
2)取指定长度的字符串:sscanf( “123456”, “%4s”, strings); strings: 1234
3)取到指定字符串为止的字符串:
sscanf( “123456 abdcdef”, “%[^ ]”, strings); strings: 123456
4)取仅包含指定字符集的字符串:(取仅包含1-9和小写字母的字符串)
sscanf( “123456abdDJKJKELW”, “%[1-9a-z]”, strings); strings: 123456abd
5)取到指定字符集为止的字符串:
sscanf( “123456abdDJKJKELW”, “%[^ A-Z]”, strings); strings: 123456abd
2.复制: char *strcpy ( char * dst, char const *src ); 返回指向目标字符数组的指针,即dst。
3.连接:char *strcat ( char * dst, char const *src ); 返回指向目标字符数组的指针,即dst。
4.比较:int strcmp (char const * s1, char const *s2 ); 若s1<s2,返回负数;若s1>s2,返回正数;若s1=s2,返回0;
5.长度受限字符串函数
(1)char *strncpy( char *dst, char const *src, size_t len); //若strlen(src)小于len,dst数组就用额外的NULL字节填充到len长度。
(2)char *strncat( char *dst, char const *src, size_t len);
(3)int strncmp( char const *s1, char const *s2, size_t len);
6.查找一个字符
(1)char *strchr( char const *str, int ch); //返回str中ch第一次出现的位置
(2)char *strrchr( char const *str, int ch); // 返回str中ch最后一次出现的位置
7.查找几个字符
char *strpbrk (char const *str, char const *group);
返回str中第一个匹配group中任何一个字符的位置,若未找到匹配,返回NULL。
eg: char string [20] = “ Hello there, honey.”;
char *ans;
ans=strpbrk ( string , “aeiou”);
ans指向的位置都是string+1.
8.查找一个子串
char *strstr ( char const *s1, char const *s2 );
在s1中查找s2第1次出现的起始位置,并返回指向该位置的指针。若s2是空,返回s1.
9.查找一个字符串前缀
size_t strspn ( char const *str, char const *group ); //返回str起始部分匹配group中任意字符的字符数。
size_t strcspn ( char const *str, char const *group); //与strspn正好相反
eg:(1)
int len1, len2;
char buffer [] = “25,142,330,Smith,J,239-4123”;
len1=strspn ( buffer, “0123456789” );
len2=strspn ( buffer, “,0123456789” );
len1的值为2,len2的值为11
(2)
计算一个指向字符串中旳第一个非空白字符的指针:
ptr = buffer + strspn (buffer, “\n\r\f\t\v” );
10.查找标记
char *strtok ( char *str, char const *sep );
sep参数是个字符串,定义了用作分隔符的字符集合。第一个参数指定一个字符串,它包含0个或多个由sep中一个或多个分隔符分隔的标记。strtok找到str的下一个标记,并将其用NULL结尾,然后返回一个指向这个标记的指针。
11.C primer plus 11-7
编写一个函数string_in(),它接受两个字符串指针参数。如果第二个字符串被包含在第一个字符串中,函数就返回被包含的字符开始的地址。例如,string_in("hats","at")返回hats中a的地址,则,函数返回空指针。在一个使用循环语句为这个函数提供输入的完整程序中进行测试。
#include <stdio.h>
char *string_in(char *p1, char *p2);
int main(void)
{
char str1[81];
char str2[21];
char *p;
do
{
puts("input range string:");
gets(str1);
puts("input match string:");
gets(str2);
p = string_in(str1, str2);
if ( p )
{
puts("Find!");
puts(p);
}
else puts("Can‘t find!");
puts("input any char except q to go on.");
gets(str1);
}
while(*str1 != ‘q‘);
puts("Quit.");
return 0;
}
char *string_in(char *p1, char *p2)
{
char *p1_save = p1, *p2_save = p2;
if(*p1 == ‘\0‘ || *p2 == ‘\0‘) return NULL;
while(1)
{
if(*p1 == *p2)
{
if(*++p2 == ‘\0‘) return p1_save; //此时应用++p2
if(*++p1 == ‘\0‘) return NULL;
}
else
{
if(*++p1 == ‘\0‘) return NULL;
p1_save = p1;
p2 = p2_save; //若遇到*p1和*p2不同,且*p1不为0,则p2指向首字母,重新在p1中寻找,p1从当前位置开始向后移动。
}
}
}
12.C primer plus 11-10
.编写一个程序,读取输入,直到读入了10个字符串或遇到EOF,由二者中最先被满足的那个终止读取过程。这个程序可以为用户提供一个有5个选项的菜单:输出初始字符串列表、按ASCII顺序输出字符串、按长度递增顺序输出字符串、按字符串中第一个单词的长度输出字符串和退出。菜单可以循环,直到用户输入退出请求。当然,程序要能真正完成菜单中的各项功能。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LINE 10
#define SIZE 81
void strinit(char *strings[],int num);
void strsrt(char *strings[],int num);
void strlong(char *strings[],int num);
void strwordlen(char *strings[],int num);
void menu();
int main()
{
char input[LINE][SIZE];
char *ptr[LINE];
int ct=0;
int choose;
printf("Input up to %d lines:\n",LINE);
while(ct<LINE && gets(input[ct])!=NULL && input[ct][0]!=‘\0‘)
{
ptr[ct]=input[ct];
ct++;
}
puts(" ");
puts("Please choose the way to sort: (1-5)");
menu();
printf("Please input your choice : ");
scanf("%d",&choose);
while(choose!=5)
{
switch(choose)
{
case 1:strinit(ptr,LINE);
break;
case 2:strsrt(ptr,LINE);
break;
case 3:strlong(ptr,LINE);
break;
case 4:strwordlen(ptr,LINE);
break;
default :break;
}
puts(" ");
puts("Please choose the way to sort: (1-5)");
menu();
printf("Your choice is : ");
scanf("%d",&choose);
}
return 0;
}
void menu()
{
puts("*******************************");
puts("1.输出初始化字符串列表.");
puts("2.按照ASCII顺序输出.");
puts("3.按照长度递增输出.");
puts("4.按字符串中第一个单词长度输出.");
puts("5.退出.");
puts("*******************************");
}
void strinit(char *strings[],int num) //初始化字符串,并输出
{
for(int i=0;i<LINE;i++)
puts(strings[i]);
}
void strsrt(char *strings[],int num) //按照首字母输出字符串
{
char *temp;
int top,seek;
for(top=0;top<num-1;top++)
for(seek=top+1;seek<num;seek++)
if(strcmp(strings[top],strings[seek])>0)
{
temp=strings[top];
strings[top]=strings[seek];
strings[seek]=temp;
}
/* for(int i=0;i<num;i++)
puts(strings[i]); */
strinit(strings,num); //直接用strinit()
}
void strlong(char *strings[],int num) //按照字符串长度输出字符串
{
int i,j;
char *temp;
for(i=0;i<num-1;i++) //冒泡排序
for(j=0;j<num-1-i;j++)
{
if(strlen(strings[j])>strlen(strings[j+1]))
{
temp=strings[j];
strings[j]=strings[j+1];
strings[j+1]=temp;
}
}
//for( i=0;i<num;i++)
// puts(strings[i]);
strinit(strings,num);
}
void strwordlen(char *strings[],int num) //按照首单词长度输出字符串
{
int i,j,flag;
int number[10];
char *temp;
for(i=0;i<num;i++)
{
j=0;
while(strings[i][j]!=‘ ‘ && strings[i][j]!=‘\n‘ && strings[i][j]!=‘\0‘)
j++;
number[i]=j;
}
for(i=0;i<num;i++)
printf("the number is : %d\n",number[i]);
for(i=0;i<num-1;i++) //冒泡排序
for(j=0;j<num-1-i;j++)
{
//printf(" is : %d\n",number[j]);
// printf("number is : %d\n",number[j+1]);
if(number[j]>number[j+1])
{
flag=number[j]; //没有这段代码时,无法进行字符串交换
number[j]=number[j+1];
number[j+1]=flag;
//只有number里面的数值进行了交换,才可以引导字符串进行交换,否则就是错误的
temp=strings[j];
strings[j]=strings[j+1];
strings[j+1]=temp;
}
}
strinit(strings,num);
}
13.C primer plus 11-12
编写一个程序,按照相反的单词顺序显示命令行参数。即,如果命令行参数是see you later,程序的显示应该为later you see
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void reverse(char *input,char *output);
int main()
{
char input[80]; //input为指针常量,不能自加和自减
char *output;
output=(char *)malloc(sizeof(char *)); //很重要,指针变量不能自动分配存储空间
puts("Please input your strings:");
fgets(input,80,stdin);
reverse(input,output);
puts("Now your strings are:");
puts(output);
return 0;
}
void reverse(char *input,char *output)
{
char *pt;
pt=input;
while(*pt!=‘\0‘) 不能用while(*pt++!=‘\0‘);
pt++ ;
// putchar(*pt++);
pt--;
for( int i=0; i<strlen(input) && pt>0; i++)
{
output[i]=*pt;
// putchar(output[i]);
pt--;
}
output[strlen(input)]=‘\0‘; //一定得加上‘\0‘,因为puts默认是80,若不加,会自行乱码填充
// puts(output);
}
char * reverse(char *input) //这段代码错误原因就是局部变量在函数结束时内存已经收回,
{ //无法将指针进行传递
char *pt,*tr,*pr;
int i=0,j=0;
pt=input;
while(*pt!=‘\0‘)
pt[i++];
tr=&pt[i-1];
putchar(*tr);
while(*tr!=‘\0‘)
{
pr[j++]=*tr--;
}
return pr;
}
14.fgets和scanf区别
char *string;
char *pt;
string=(char *)malloc(sizeof(char *));
puts("Please input your string:");
scanf("%s",string); // fgets(string,80,stdin);
pt=string;
while(*pt!=‘\0‘)
pt++;
pt=pt-1; // pt=pt-2;
putchar(*pt);
用scanf(红色)输入时,输出最后一个字符只需pt-1,而用fgets(蓝色)输入时,输出最后一个字符必须用pt-2;
第10章 动态内存分配
1.malloc()分配一块连续内存,返回一个指向被分配的内存块起始位置的指针。(stdlib.h)
2.free()参数必须是NULL,或者是从malloc、calloc或realloc返回的一个值。
void free(void * pointer);
3.void *malloc(size_t size);
void *calloc(size_t num_elements,size_t element_size);
malloc和calloc区别:
(1)malloc参数是需要分配的内存字节数,calloc参数是需要分配的元素个数和每个元素的长度。
(2)calloc在返回前把内存初始化为0,而malloc返回时内存并未以任何形式进行初始化。
4.realloc函数用于修改一个原先已经分配的内存块的大小。使一块内存扩大或缩小。
5.复制字符串
#include<stdio.h>
#include<string.h>
char * strdup (char const *string)
{
char *new_string;
new_string = malloc ( strlen (string ) + 1 );
if ( new_string != NULL )
strcpy( new_string, string );
return new_string;
}