字符串

表示字符串和字符串组I/O

前情回顾:字符串是以空字符(\0)结尾的char类型数组
在程序中表示字符串:

 //表示字符串的一些方法
 #include <stdio.h>
 #define MSG "I am a symbolic string constant."
 #define MAXLENGTH 81
 int main(void)
 {
 char words[MAXLENGTH] = "I am a string in an array.";//char类型数组
 const char * pt1 = "Something is pointing at me.";//指向char的指针
 puts("Here are some strings:");//字符串常量
 puts(MSG);
 puts(words);
 puts(pt1);
 words[8] = 'p';
 puts(words);

 return 0;
 }

puts函数也属于stdio.h系列的输入/输出函数,但puts函数只显示字符串,而且自动在显示的字符串末尾加上换行符。

显示字符串
字符串

在程序中定义字符串

1、字符串字面量(字符串常量)
用引号括起来的内容称为字符串字面量,亦称字符量常量
从ANSI C标准起,如果字符串面量之间没有间隔,或者使用空白字符分隔,C会将其视为串联起来的字符串字面量。如:

 char greeting[50] = "Hello, and"" how are" " you"" today!";

与下面的代码等价:

 char greeting[50] = "Hello, and how are you today!";

如果要在字符串内使用双引号,必须在双引号前面加上一个反斜杠(\):

 printf("\"Run, Spot, run!\" exclaimed Dick.\n");

字符串常量属于静态存储类别,这说明如果在函数中使用字符串常量,该字符串只会被存储一次,在整个程序的生命周期内存在,即使函数被调用多次。
用双引号括起来的内容被视为指向该字符串存储位置的指针。

 /* strptr.c -- 把字符串看作指针 */
 #include <stdio.h>
 int main(void)
 {
 printf("%s, %p, %c\n", "We", "are", *"space farers");

 return 0;
 }

结果相当的amazing啊!
字符串看作指针
字符串

2、字符串数组与初始化
定义字符串数组时,必须让编译器知道需要多少空间。
一种方法是用足够空间的数组存储的数组存储字符串。

 const char m1[40] = "Limit yourself to one line's worth.";

还可以使用指针表示法创建字符串。

 const char * pt1 = "Something is pointing at me.";

3、数组形式和指针形式

 //  addresses.c  -- 字符串的地址
 #define MSG "I'm special"

 #include <stdio.h>
 int main()
 {
 char ar[] = MSG;
 const char *pt = MSG;
 printf("address of \"I'm special\": %p \n", "I'm special");
 printf("              address ar: %p\n", ar);
 printf("              address pt: %p\n", pt);
 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": 0x100000f10
               address ar: 0x7fff5fbff858
               address pt: 0x100000f10
           address of MSG: 0x100000f10
 address of "I'm special": 0x100000f10

显然pt与MSG地址相同,而ar地址不同。静态数据使用的内存与ar使用的动态内存不同,不仅值不同,特定编译器甚至使用不同的位数表示两种内存。

4、指针形式与数组形式的区别:

 char heart[] = "I love Tillie!";
 const char *head = "I love Millie!";

最主要的区别是:数组名heart是常量,而指针head是变量

4.1两者都可以使用数组表示法:

 for (i = 0; i < 6; i++)
      putchar(heart[i]);
 putchar('\n');

 for (i = 0; i < 6; i++)
      putchar(head[i]);
 putchar('\n');

输出均为:I love

4.2两者都可以进行指针加法操作

 for (i = 0; i < 6; i++)
      putchar(*(heart + i));
 putchar('\n');

 for (i = 0; i < 6; i++)
      putchar(*(head + i));
 putchar('\n');

4.3但是,只有指针表示法可以进行递增操作:

 while (*(head) != '\0')     /* 在字符串末尾处停止*/
      putchar(*(head++));    /* 打印字符,指针指向下一个位置 */

4.4可以改变heart数组中元素的信息

 heart[7]= 'M';或者*(heart + 7) = 'M';

数组的元素是变量(除非数组已经声称为const),但是数组名不是变量

5、字符串数组

 //  arrchar.c -- 指针数组,字符串数组
 #include <stdio.h>
 #define SLEN 40
 #define LIM 5
 int main(void)
 {
 const char *mytalents[LIM] = {
      "Adding numbers swiftly",
      "Multiplying accurately", "Stashing data",
      "Following instructions to the letter",
      "Understanding the C language"
 };
 char yourtalents[LIM][SLEN] = {
      "Walking in a straight line",
      "Sleeping", "Watching television",
      "Mailing letters", "Reading email"
 };
 int i;

 puts("Let's compare talents.");
 printf("%-36s  %-25s\n", "My Talents", "Your Talents");
 for (i = 0; i < LIM; i++)
      printf("%-36s  %-25s\n", mytalents[i], yourtalents[i]);
 printf("\nsizeof mytalents: %zd, sizeof yourtalents: %zd\n",
                   sizeof(mytalents), sizeof(yourtalents));

 return 0;
 }

字符串数组
字符串

显然,两者十分相似,但也有区别。mytalents数组是一个内含5个指针的数组,而yourtalents数组是一个内含5个数组的数组,每个数组内含40个char类型的值。mytalents中的指针指向初始化时所用的字符串字面量的位置,这些字符串字面量被存储在静态内存中;而yourtalents中的数组则存储着字符字面量的副本,所以每个字符都被存储两次。此外,为字符串数组分配内存的使用率较低。yourtalents中每个元素大小必须相同,而且必须是能存储最长字符串的大小

总而言之,如果要用数组表示一系列待显示的字符串,那么使用指针数组,效率更高。但是,指针数组指向的字符串字面量不能更改。

上一篇:PAT1017


下一篇:论:学习语言哪个好?python、C++还是Java?