title: 第十一章 字符串和字符串函数
author: HardyDragon
tags: C Notes
第十一章 字符串和字符串函数
-
使用字符串的几种方式,赋值都是字符串用双引号括起来。
- 字符数组赋值
- 字符指针赋值
- 字符串常量
- puts() 函数显示字符串,参数可以是字符数组或指针
注意puts() 函数也是stdio.h 头文件里的输入输出函数,puts() 函数只显示字符串且自动在字符串末尾加上换行符。
// strings1.c --使用字符串 #include<stdio.h> #define MSG "I am a symbolic string constant" #define MAXLENGTH 81 int main(int argc, char const *argv[]) { char words[MAXLENGTH] = "I am a string in an array."; const char* pt1 = "Something is pointing at me."; puts("Here are some strings:"); puts(MSG); puts(words); puts(pt1); words[8] = 'p'; puts(words); return 0; }
result:
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.
// strptr.c -- 将字符串看做指针 #include <stdio.h> int main(int argc, char const *argv[]) { printf("%s ,%p,%c\n", "We", "are", *"space"); return 0; }
result:
We ,0000000000404000,s
-
字符串的绝大数的操作通过指针完成。即让指针指向字符串来修改。
-
字符串输入时要先给字符串分配空间,可用数组显式指明数组大小。或者用其他C库函数分配内存。
-
使用gets() 函数,读取整行输入,直到遇到换行符,然后丢弃换行符,在最后添加一个空字符结束;gets() 经常和puts() 配合使用,puts() 显示字符串并自动换行相当于python的print()。
// getsputs.c -- 使用gets() 和 puts() #include<stdio.h> #define STLEN 81 int main(int argc, char const *argv[]) { char words[STLEN]; puts("Enter a string ,please."); gets(words); printf("Your string twice:\n"); printf("%s\n",words); puts(words); puts("Done!"); return 0; }
result:
Enter a string ,please. hello world Your string twice: hello world hello world Done!
如果给定的初始空间过小,不能容纳字符串,会爆分段错误;意思是该程序试图访问未分配的内存。所以这可能会造成系统的安全问题,C99建议不要使用,但是保留了,可以说是一把双刃剑,使用合理就比较方便。C11就不客气的删除了gets() 函数。C11 使用get_s() 代替。
fget() 函数(和fputs())
fgets() 通过第二参数指明了读入字符的最大数量,用于处理文件传输。
fgets() 读到一个换行符会把它存储在字符串中。这个和gets() 不同,因为gets() 只是单行读取,会丢弃换行符。
第三个参数指明要读入的文件。
// fgets1.c -- 使用fgets() 和 fputs() #include <stdio.h> #define STRLEN 14 int main(int argc, char const *argv[]) { char words[STRLEN]; puts("输入一个字符串!"); // 如果要从键盘读取输入用stdin作为参数 fgets(words, STRLEN, stdin); printf("Your string twice (puts(),then fputs()):\n"); puts(words); // 如果要显示在计算机显示器上使用stdout作为参数 fputs(words, stdout); puts("输入另一个字符串。"); fgets(words, STRLEN, stdin); printf("Your string twice (puts(),then fputs()):\n"); puts(words); fputs(words, stdout); puts("Done!"); return 0; }
result:
输入一个字符串! aaa Your string twice (puts(),then fputs()): aaa aaa 输入另一个字符串。 aaaaaaaaaaaaaaaaaaaaa Your string twice (puts(),then fputs()): aaaaaaaaaaaaa aaaaaaaaaaaaaDone!
注意puts() 会在带输出字符串末尾添加一个换行符,而fputs() 不会。
以上的第一个输出便是有两个换行符,fgets() 不会抛弃换行符所以读取到了便保留了下来,第二个没有读取到换行就没有空行。
// fgets2.c -- 使用fgets() 和 fputs() #include <stdio.h> #define STLEN 10 int main(int argc, char const *argv[]) { char words[STLEN]; puts("输入字符串(空行退出):"); while (fgets(words, STLEN, stdin) != NULL && words[0] != '\n') { /* code */ fputs(words, stdout); } puts("Done!"); return 0; }
result:
输入字符串(空行退出): by the way ,the gets() by the way ,the gets() also sadja k also sadja k sdaksdas sdaksdas Done!
如果需要删除存储在字符串中的换行符,或丢弃数组装不下的字符:
// fgets3.c #include <stdio.h> #define STLEN 10 int main(int argc, char const *argv[]) { char words[STLEN]; int i; puts("输入一个字符串空行退出:"); while (fgets(words, STLEN, stdin) != NULL && words[0] != '\n') { /* code */ i = 0; while (words[i] != '\n' && words[i] != '\0') { i++; } if (words[i] == '\n') { words[i] = '\0'; }else { while (getchar()!='\n') { /* code */ continue; } } puts(words); } puts("Done!"); return 0; }
result:
输入一个字符串空行退出: this this progran sdada progran s dsakkasa ldk dsakkasa Done!
遍历字符串遇到换行符或者空字符就将其替换为空字符,如果先遇到空字符就丢弃剩余的字符。
-
-
注意空指针和空字符的区别:都可以用0表示,但是两者所占字节不同,一个是字符占1字节,一个是指针占4字节。
-
gets_s() 函数和fgets() 类似,但是不会保存换行符。
-
scanf() 函数注意读取的缓冲区
-
puts() 函数独占一行
-
fputs() 不保留换行符。
#include <stdio.h> int main() { char line[81]; while (fgets(line, 81, stdin)) { /* code */ fputs(line, stdout); } puts("Done!"); return 0; }
result:
hello hello das das ^Z Done!
-
熟悉以下的判断手法
while(*string)
当指针指向空字符时为0即假。
// put2.c -- 统计打印的字符数 #include <stdio.h> int put2(const char *string); int main(int argc, char const *argv[]) { int count = 0; char *string = "hello"; count = put2(string); printf("字符数量:%d\n", count); return 0; } int put2(const char *string) { int count = 0; while (*string) { /* code */ putchar(*string++); count++; } putchar('\n'); return count; }
result:
hello 字符数量:5
-
-
字符串函数 string.h 头文件
strlen() 统计字符串长度,修改字符串时注意不要使用const
-
strcat() 连接两个字符串,将第二个字符串附加到字符串末尾,返回第一个参数的地址。
-
strncat() 函数 有第三个参数指定了两个字符合并时在加到第n个字符时停止。
-
strcmp() 函数两个字符串比较
-
strcpy() 拷贝整个字符串,相当于字符串赋值运算符。
// copy2.c -- 使用strcpy() #include <stdio.h> #include <string.h> #define WORDS "beast" #define SIZE 40 int main(int argc, char const *argv[]) { const char *orig = WORDS; char copy[SIZE] = "Be the best that you can be."; char *ps; puts(orig); puts(copy); ps = strcpy(copy + 7, orig); puts(copy); puts(ps); return 0; }
result:
beast Be the best that you can be. Be the beast beast
-
使用strncpy() 拷贝字符串较安全。
如果目标空间可以容纳字符串的副本,那么从字符串拷贝的空字符便是副本的结尾,如果装不下副本就将最后一个元素设置为空字符。 -
sprintf() 函数声明在stdio.h 中,和printf类似,但是它是把数据写入字符串一个字符串数组。
-
利用strcmp 来进行字符串排序。
-
ctype.h 字符函数和字符串
- toupper() 将字符串转换为大写
- ispunct() 统计字符串的标点符号个数
- strchr() 处理fgets() 读入字符串的换行符
-
命令行参数 是允许编译后的程序同一行的附加项例如:
fuss -r Ginger
一个C程序可以读取并使用这些附加项,例如通过main() 函数读取这些附加项
// repear.c -- 带参数的main() #include <stdio.h> int main(int argc, char const *argv[]) { int count; printf("The command line has %d aargument:\n", argc - 1); for (count = 1; count < argc; count++) { /* code */ printf("%d:%s\n", count, argv[count]); } printf("\n"); return 0; }
result:
C:\Git\c-primer-plus-notes\code>repear.c.exe a b c The command line has 3 aargument: 1:a 2:b 3:c
其中 repear.c.exe 是编译后的可执行程序,可以附带参数运行。
C编译器允许main() 没有参数或者有两个参数(有些标准扩展还可以有更多的参数),当有两个参数时,第一个参数是命令行中的字符串数量,用空格表示字符串的结束和下一个字符串的开始。
例如:repear.c.exe a b c 的argc 为4;
将每个字符串存储在指针数组,放在第二个参数中。
可以用atoi() 函数将字符串转为对应的整数,
// hello.c -- 把命令行参数转换为数字 #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int i, times; if (argc < 2 || (times = atoi(argv[1])) < 1) { /* code */ printf("Usage:%s positive-number\n", argv[0]); } else { for (i = 0; i < times; i++) { /* code */ printf("Hello,good looking!\n"); } } return 0; }
result:
C:\Git\c-primer-plus-notes\code>hello.c.exe 3 Hello,good looking! Hello,good looking! Hello,good looking! ---------------------- C:\Git\c-primer-plus-notes\code>hello.c.exe a Usage:hello.c.exe positive-number
}
else
{
for (i = 0; i < times; i++)
{
/* code */
printf(“Hello,good looking!\n”);
}
}
return 0;
}
result:
```bash
C:\Git\c-primer-plus-notes\code>hello.c.exe 3
Hello,good looking!
Hello,good looking!
Hello,good looking!
----------------------
C:\Git\c-primer-plus-notes\code>hello.c.exe a
Usage:hello.c.exe positive-number