字符串字面值
如“Hello world”等字符串常量(字面值一定是常量,但常量不一定是字面值)
三种书写方式:
int main(void){
printf("i love xixi --fp\n");
printf("i love xixi\ // \是省略换行符,但下一行的空白也算在里面
--fp\n");
printf("i love xixi"
" --fp\n");
return 0;
}
内存模型

字符串字面值所支持的操作
常量数组支持的操作字符串字面值都支持
“ABC”[0]='a' ; //“ABC”是数组名,这个操作是错误的,因为字符串字面值在代码段
char* p="ABC"+1; //c中不是拼接,而是数组名“ABC”即地址,然后+1
printf("%c\n",*p); //B
字符串变量

1.c没有字符串类型,依赖于字符数组
2.字符串必须以'\0'结尾
3.在c中求字符串长度不是O(1)的时间复杂度而是O(n)--->
char str[]="hello world\n";int len=strlen(str);
注:strlen不包含空字符'\0'的长度
声明字符串变量并赋初始值
char str1[]={'H','e','\0'};
char str2[]="He"
char str[5]="hello"不是字符串而是字符数组,字符串都是以'\0'结尾
char str[10]="Hello" :字符数组str长度10,字符串Hello长度5 ,占用6个空间
字符串读和写
1.printf+%s

注意:字符串读取可以直接在printf中写首地址---->返回的是首地址指向的内容※※
scanf+%s(读取一个单词)

char arr[MAX]=" hello world";
scanf("%s",arr);
printf("%s",arr); //hello
%s匹配规则:
忽略前置空白字符,
读取字符填入字符数组,
遇到空白字符结束(不会将换行,空格等读入内存)
缺点:1.不能读取空白字符 2.不会检查字符越界
注:用scanf读取字符串到字符数组时会自动添加'\0'。%c不会自动添加终止符,而%s会
2.puts/gets(读取一整行)

注:scanf和puts效果都是把'\n'---->'\0',然后存入内存
3.fgets(str,MAX_LINE,stdin)
和gets区别:1.会检查是否越界 2.会存储'\n'并在后面添加'\0';

字符串操作
strlen


当两个相同类型的指针相减时,编译器知道每个元素占用的字节数,从而可以正确地计算出两个指针之间相隔的元素个数,而不是简单的字节差。
strlen()不会计算字符串中的编译器自动添加的空字符'\0' ,但会计算" "
- 空格:普通字符,ASCII 32,存储为可见字符。
- '\0':终止符,ASCII 0,自动添加,不可见。
strcpy 和 strncpy(防数组越界)

这两个都会将空字符'\0'作为结束并复制'\0' ----->

但strncpy中 要复制的前n个元素最大个数为【数组 -1】且要手动 s1[数组-1]=‘\0’※※
字符串拼接strcat 和 strncat(同上)



strcmp(s1,s2)
规则:字符串长的>0 ---> ASCLL大的>0
size_t my_strcmp(const char* s1,const char* s2){
while(*s1 && *s2){
if(*s1 != *s2){
return *s1-*s2;
}
s1++; //s1+1个char地址
s2++;
}
return *s1-*s2;
}
作业
1.
void reverse_print() {
char c;
char messages[100];
int i = 0;
c = getchar();
while (c != '\n' && i != 99) {
messages[i] = c;
c = getchar();
i++;
}
for (int j = i - 1; j >= 0; j--) {
printf("%c", messages[j]);
}
}
void reverse_print() {
char c;
char messages[100];
char* p = messages;
c = getchar();
while (c != '\n' && p<p+100) {
*p = c;
c = getchar();
p++;
}
p--;
for (; p >= messages;p--) {
printf("%c", *p);
}
}
2.
考虑大小写并且不忽略任何char
bool is_pri(char messages[], int n) {
for (int i = 0; i < n / 2; i++) {
if (messages[i] != messages[n - 1 - i]) {
return false;
}
}
return true;
}
bool is_pri(char messages[], int n) {
char* start = messages;
char* end = messages + n;
while (start<end) {
if (*start != *end) {
return false;
}
}
return true;
}
3.
void remove_filename(char* url) {
char* p = url;
while (*url) {
if(*url =='/') {
p = url;
}
}
if (*p == '/') {
*p = '\0';
}
}
4.

void min_max() {
char smalllest_word[4], largest_word[4];
char curr[4];
scanf("%s", curr);
strcpy(smalllest_word, curr);
strcpy(largest_word, curr);
while (strlen(curr) != 4) {
scanf("%s", curr);
if (strcmp(curr, largest_word) > 0) {
strcpy(largest_word, curr);
}
if (strcmp(curr, smalllest_word) < 0) {
strcpy(smalllest_word, curr);
}
}
printf("min=%s,max=%s", smalllest_word, largest_word);
}
5.
统计字符串str中各个字符出现的频度,a[]存放各个不同字符,b[]存放对应的字符出现的频度,返回不同字符个数
int fun(char str[], char a[], int b[]) {
int len = strlen(str),cur=0;//cur为遍历str的不同字符·
for (int i = 0; i < len; i++) {
b[i] = 0;
}
a[0] = str[0];
b[0] = 1;
cur++;
for (int i = 1; i < len; i++) {
for (int j = 0; j < i; j++) {
if (str[i] == str[j]) {
int k;
for (k = 0; a[k] != str[i]; k++);
b[k]++;
break;
}
a[cur] = str[i];
b[cur]++;
cur++;
}
}
return cur;
}
6.
求两个字符串s和t的一个最长公共子串
//s一个个往后加,分别和t比较(t不变位置)
char com[10];//公共数组要定义在外面,定义在内部函数销毁后返回的是悬空指针
char* maxlength(char* s, char* t) {
char*m,*n;
int len=0,len1=0,i,j;
while (*s) {
//用m遍历s,n遍历t,每次s+1重置len1=0
m = s;
n = t;
while (*n) {
len1 = 0;
for (i=0; *(m+i) == *(n+i); i++) {
len1++;
}
if (len1 > len) {
len = len1;
for (j = 0; j < len1; j++) {
com[j] = *(m + j);
}
com[j] = '\0';
n += i;
}
else {
n++;
}
}
s++;
}
if (len == 0) {
return NULL;
}
else {
return com;
}
}
int main(void) {
char * p;
char s[] = "aababcabcdabcde";
char t[] = "xabcdy";
p = maxlength(s, t);
for (int i = 0; p[i]!='\0'; i++) {
printf("%c", p[i]);
}
return 0;
}
7.
输入两个英文句子,每个句子里英文单词用空格分隔,最后输出两者的最长公共单词
char* maxword(char* s1, char* s2) {
char from_s1[10],*temp,from_s2[10],com[10];
int maxlen = 0, is_cur_same = 0, i, j;
while (*s1) {
while (*s1 == ' ')s1++;
for (i = 0; *s1 != '\0' && *s1 != ' '; i++, s1++) {
from_s1[i] = *s1;
}//从左到右找到s1的某个单词存入from_s1中
from_s1[i] = '\0';
if (i > maxlen) {//is curr max but don,t know is same?
is_cur_same = 0;
temp = s2;//用temp在s2进行遍历
while (*temp && is_cur_same == 0) {
while (*temp == ' ')temp++;
for (j = 0; *temp != '\0'&&*temp!=' '; j++, temp++) {//在s2中找一个个单词存入from_s2中
from_s2[j] = *temp;
}
from_s2[j] = '\0';
if (i == j) {
if (strcmp(from_s1, from_s2) == 0) {
maxlen = i;
is_cur_same = 1;
strcpy(com, from_s1);
}
}
}
}
}
if (maxlen == 0) {
return NULL;
}
else {
return com;
}
}
int main() {
char s1[10], s2[10];
char* p;
fgets(s1,sizeof(s1),stdin);
fgets(s2, sizeof(s2), stdin);
p = maxword(s1, s2);
if (p == NULL) {
printf("没有公共单词");
}
else {
printf("最长公共单词=%s", p);
}
return 0;
}
8.
有一个2*3和3*2的整数矩阵a,b相乘,请使用指针数组实现这两个矩阵相乘,存在c中
int main(void) {
int a[2][3] = { 1,1,1, 1,1,1};
int b[3][2] = { 2,2 ,2,2 ,2,2 }, c[2][2] = { 0 };
int* p[3] = { a[0],b[0],c[0] };
int temp;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 2; k++) {
*(p[2]+2*i+k)+= *(p[0] + 3 * i + j) * (*(p[1] + 2 * j + k));//c[i][k]+=a[i][j]*b[j][k]
}
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("%d", *(p[2] + 2 * i + j));
}
}
return 0;
}
字符串数组
字符数组的数组---->二维字符数组

1.浪费内存空间
2.交换字符串很不方便
3.注:planets[0]和planets[1]的长度为7和5,但两个所占内存空间都为8
4.里面存的可以改变
字符指针数组

1.里面的“Mercury”等是字符串字面值,即本身内容的地址,是 char*
2.不可以直接 *(planets[i])="mercury" 进行修改.
3.要修改{.....}里的内容要创建一个字符串变量(一维字符数组),然后用指针指向那个一维数组
char a[]="hello";planets[i]=a;or char*p="hello";planets[i]=p; //注意“hello”是字符串字面值不能p[i]='d'修改
程序题(二维字符数组)
1.输入若干字符串,找出其中最长的字符串并输出,要求采用指针数组存放这些字符串
char* findmax(char* str[],int n,int* len) {//n是字符串个数,len是最长字符串长度
int temp, max = 0;
char* p;
for (int i = 0; i < n; i++) {
temp = strlen(str[i]);
if (temp > max) {
max = temp;
p = str[i];
}
}
*len = max;
return p;
}
int main(void) {
char* s[5],*p;
for (int i = 0; i < 5; i++) {
s[i] = (char*)malloc(20);
scanf("%s", s[i]);
}
return 0;
}
2.求三个字符串的最长公共子串
不能以其中一个为母串,遍历寻找第二个串中的子串这种方法:这种只适合两个串找最长公共子串,其实也可以但更麻烦
要采用“求n个字符串的最长公共子串”通用的方法:如下以其中一个为子串,对比其余串找
char* copy(char* s, int start, int count) {
static char str[20];
for (int i = start; i < start + count; i++) {
str[i - start] = s[i];
}
str[start + count] = '\0';
return str;
}
char* common_str(char* str[],int n) {
int len = strlen(str[0]);//这个作为子串
int max_str = 0,index,is_true;
char* temp;
char result[10];
for (int i = 0; i < len; i++) {
for (int j = 1; j < len - i; j++) {
temp=copy(temp, i, j);
index = 0;
is_true = 1;
while(index<2){
index++;
if (strstr(str[index], temp) == 0) {//判断temp是否为str[index]的子串
is_true = 0;
}
}
if (is_true == 1 && strlen(temp) > max_str) {
max_str = strlen(temp);
strcpy(temp, temp);
}
}
}
if (max_str == 0) {
return NULL;
}
else {
return result;
}
}



!!!&spm=1001.2101.3001.5002&articleId=147352663&d=1&t=3&u=04977f68e27445d4824c41b8d10df16e)
1万+

被折叠的 条评论
为什么被折叠?



