C Primer Plus 第四章字符串学习笔记

小结

字符串是一系列被视为一个处理单元的字符。在C语言中,字符串是以空字符(ASCII码是0)结尾的一系列字符。可以把字符串储存在字符数组中。数组是一系列同类型的项或元素。下面声明了一个名为name、有30个char类型元素的数组:

char name[30];


要确保有足够多的元素来储存整个字符串(包括空字符)。字符串常量是用双引号括起来的字符序列,如:"This is an example of astring"。

预处理器为预处理器指令(以#符号开始)查找源代码程序,并在开始编译程序之前处理它们。处理器根据#include指令把另一个文件中的内容添加到该指令所在的位置。

在程序中,最好用#define 定义数值常量,用 const 关键字声明的变量为只读变量(可以在计算中使用只读变量,可以打印只读变量,但是不能更改只读变量的值)。在程序中使用符号常量(明示常量),提高了程序的可读性和可维护性。

C 语言的标准输入函数(scanf())和标准输出函数(printf())。确保转换说明的数量和类型与函数的其余参数相匹配。对于scanf(),一定要记得在变量名前加上地址运算符(&)。另外,可以使用转换说明和修饰符控制输出的外观:字段宽度、小数位和字段内的布局。

空白字符(制表符、空格和换行符)在 scanf()处理输入时起着至关重要的作用。除了%c 模式(读取下一个字符),scanf()在读取输入时会跳过非空白字符前的所有空白字符,然后一直读取字符,直至遇到空白字符或与正在读取字符不匹配的字符。考虑一下,如果scanf()根据不同的转换说明读取相同的输入行,会发生什么情况。假设有如下输入行:

-13.45e12# 0

如果其对应的转换说明是%d,scanf()会读取3个字符(-13)并停在小数点处,小数点将被留在输入中作为下一次输入的首字符。

如果其对应的转换说明是%f,scanf()会读取-13.45e12,并停在#符号处,而#将被留在输入中作为下一次输入的首字符;然后,scanf()把读取的字符序列-13.45e12转换成相应的浮点值,并储存在float类型的目标变量中。

如果其对应的转换说明是%s,scanf()会读取-13.45e12#,并停在空格处,空格将被留在输入中作为下一次输入的首字符;然后,scanf()把这 10个字符的字符码储存在目标字符数组中,并在末尾加上一个空字符。

如果其对应的转换说明是%c,scanf()只会读取并储存第1个字符。

复习题

1.再次运行程序清单 4.1,但是在要求输入名时,请输入名和姓(根据英文书写习惯,名和姓中间有一个空格),看看会发生什么情况?为什么?

// 4-1程序
#include <stdio.h>
#include <string.h>      // for strlen() prototype
#define DENSITY 62.4     // human density in lbs per cu ft
int main()
{
    float weight, volume;
    int size, letters;
    char name[40];        // name is an array of 40 chars
    
    printf("Hi! What's your first name?\n");
    scanf("%s", name);
    printf("%s, what's your weight in pounds?\n", name);
    scanf("%f", &weight);
    size = sizeof name;
    letters = strlen(name);
    volume = weight / DENSITY;
    printf("Well, %s, your volume is %2.2f cubic feet.\n",
           name, volume);
    printf("Also, your first name has %d letters,\n",
           letters);
    printf("and we have %d bytes to store it.\n", size);
    
    return 0;
}

程序不能正常运行。第1个scanf()语句只读取用户输入的名,而用户输入的姓仍留在输入缓冲区中(缓冲区是用于存储输入的临时存储区)。下一条scanf()语句在输入缓冲区查找重量时,从上次读入结束的地方开始读取。这样就把留在缓冲区的姓作为体重来读取,导致scanf()读取失败。另一方面,如果在要求输入姓名时输入Lasha144,那么程序会把144作为用户的体重(虽然用户是在程序提示输入体重之前输入了144)。

2.假设下列示例都是完整程序中的一部分,它们打印的结果分别是什么?

a.printf("He sold the painting for $%2.2f.\n", 2.345e2);
b.printf("%c%c%c\n", 'H', 105, '\41');
c.#define Q "His Hamlet was funny without being vulgar."

   printf("%s\nhas %d characters.\n", Q, strlen(Q));
d.printf("Is %2.2e the same as %2.2f?\n", 1201.0, 1201.0);

a.He sold the painting for $234.50.

b.Hi!(注意,第1个字符是字符常量;第 2个字符由十进制整数转换而来;第 了个字符是八进制字符常量的 ASCII表示)
c. His Hamlet was funny without being vulgar.
    has 42 characters.
d.Is 1.20e+003 the same as 1201.00?

3.在第2题的c中,要输出包含双引号的字符串Q,应如何修改?

在这条语句中使用\": printf("\"%s\"\nhas %d characters.\n",strlen(Q));

4.找出下面程序中的错误。

define B booboo
define X 10
main(int)
{
    int age;
    char name;
    printf("Please enter your first name.");
    scanf("%s", name);
    printf("All right, %c, what's your age?\n", name);
    scanf("%f", age);
    xp = age + X;
    printf("That's a %s! You must be at least %d.\n", B, xp);
    rerun 0;
}
//修改的程序
#include <stdio.h>
#define B "booboo"
#define X 10
int main(int)
{
    int age;
    int xp;
    char name[40];        //把name声明为数组
    printf("Please enter your first name.");
    scanf("%s", name);
    printf("All right, %s, what's your age?\n", name);
    scanf("%d", age);
    xp = age + X;
    printf("That's a %s! You must be at least %d.\n", B, xp);
    return 0;
}

5.假设一个程序的开头是这样:
#define BOOK "War and Peace"
int main(void)
{
float cost =12.99;
float percent = 80.0;
请构造一个使用BOOK、cost和percent的printf()语句,打印以下内容:
This copy of "War and Peace" sells for $12.99.
That is 80% of list.

printf("This copy of \"%S\" sells for $%0.2f.\n",BOOK,cost);
printf("That is %0.0f%% of list.\n",percent);//要打印%必须用%%

6.打印下列各项内容要分别使用什么转换说明?
a.一个字段宽度与位数相同的十进制整数
b.一个形如8A、字段宽度为4的十六进制整数

c.一个形如232.346、字段宽度为10的浮点数
d.一个形如2.33e+002、字段宽度为12的浮点数
e.一个字段宽度为30、左对齐的字符串

a. %d

b. %4X

c. %10.3f

d. %12.2e

e. %-30s

7.打印下面各项内容要分别使用什么转换说明?
a.字段宽度为15的unsigned long类型的整数
b.一个形如0x8a、字段宽度为4的十六进制整数
c.一个形如2.33E+02、字段宽度为12、左对齐的浮点数
d.一个形如+232.346、字段宽度为10的浮点数
e.一个字段宽度为8的字符串的前8个字符

a. %lu

b. %#4X

c. %-12.2E

d. %+10.3f


8.打印下面各项内容要分别使用什么转换说明?
a.一个字段宽度为6、最少有4位数字的十进制整数
b.一个在参数列表中给定字段宽度的八进制整数
c.一个字段宽度为2的字符
d.一个形如+3.13、字段宽度等于数字中字符数的浮点数
e.一个字段宽度为7、左对齐字符串中的前5个字符

a. %6.4d

b. %*o

c. %2c

d. %+0.2f

e. %-7.5s

9.分别写出读取下列各输入行的scanf()语句,并声明语句中用到变量和数组。
a.101
b.22.32 8.34E−09

c.linguini
d.catch 22
e.catch 22 (但是跳过catch)

//a.
int dalmations;
scanf("%d",&dalmations);
//b.
float kgs,share;
scanf("%f%f"&kgs,&share);
(注意:对于本题的输入,可以使用转换字符e、f和g。另外,除了%c之外,在%和转换字符之间加空格不会影响最终的结果)
//c.
char pasta[20];scanf("%s",pasta);
//d.
char action[20];
int value;
scanf("%s %d",action,&value);
//e.
int value;
scanf("%s %d",&value);

10.什么是空白?

空白包括空格、制表符和换行符。C语言使用空白分隔记号。scanf()使用空白分隔连续的输入项。

11.下面的语句有什么问题?如何修正?
printf("The double type is %z bytes..\n", sizeof(double));

%z中的z是修饰符,不是转换字符,所以要在修饰符后面加上一个它修饰的转换字符。可以使
用%zd 打印十进制数,或用不同的说明符打印不同进制的数,例如,%zx打印十六进制的数。


12.假设要在程序中用圆括号代替花括号,以下方法是否可行?

#define ( {
#define ) }

可以分别把(和)替换成1和)。但是预处理器无法区分哪些圆括号应替换成花括号,哪些圆括号不能替换成花括号。因此,

#define( {
#define) }
int main(void)
(
    printf("Hello,0 Great One!\n");
)

将变成:
int main{void}
{
    printf{"Hello,O Great One!\n"};
}

编程练习

1.编写一个程序,提示用户输入名和姓,然后以“名,姓”的格式打印出来。

#include <stdio.h>
int main(void)
{
	char fname[40];
	char lname[40];
	printf("Enter your first name: ");
	scanf("%s", fname);
	printf("Enter your last name: ");
	scanf("%s", lname);
	printf("%s, %s\n", lname, fname);
	return 0;
}

4.编写一个程序,提示用户输入身高(单位:英寸)和姓名,然后以下面的格式显示用户刚输入的信息:
Dabney, you are 6.208 feet tall
使用float类型,并用/作为除号。如果你愿意,可以要求用户以厘米为单位输入身高,并以米为单位显示出来。

#include <stdio.h>
int main(void)
{
	float height;
	char name[40];
	printf("Enter your height in inches: ");
	scanf("%f", &height);
	printf("Enter your name: ");
	scanf("%s", name);
	printf("%s, you are %.3f feet tall\n", name, height / 12.0);
	return 0;
}

7.编写一个程序,将一个double类型的变量设置为1.0/3.0,一个float类型的变量设置为1.0/3.0。分别显示两次计算的结果各3次:一次显示小数点后面6位数字;一次显示小数点后面12位数字;一次显示小数点后面16位数字。程序中要包含float.h头文件,并显示FLT_DIG和DBL_DIG的值。1.0/3.0的值与这些值一致吗?

#include <stdio.h>
#include <float.h>
int main(void)
{
	float ot_f = 1.0 / 3.0;
	double ot_d = 1.0 / 3.0;
	printf(" float values: ");
	printf("%.6f %.12f %.16f\n", ot_f, ot_f, ot_f);
	printf("double values: ");
	printf("%.6f %.12f %.16f\n", ot_d, ot_d, ot_d);
	printf("FLT_DIG: %d\n", FLT_DIG);
	printf("DBL_DIG: %d\n", DBL_DIG);
	return 0;
}
  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值