一起啃书(C Primer Plus 第六版)--字符串和格式化输入输出<附大量编程题>

270 阅读7分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

一、字符串简介

字符串是一个或多个字符的序列

双引号仅告知编译器它括起来的是字符串,单引号用于标识

单个字符

1.1 char类型数组和null字符

C语言没有专门用于储存字符串的变量类型,字符串都被储存在char类型的数组中。数组由连续的存储单元组成,字符串中的字符被储存在相邻的存储单元中,每个单元储存一个字符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EGEzE6D2-1633312565209)(E:\Typora\Image\image-20211003104024589.png)]

1.2 什么是数组

可以把数组看作是一行连续的多个存储单元

数组是同类型数据元素的有序序列

char name[40]

name后面的方括号表民这是一个数组,方括号后面的40表明该数组中的元素数量

在这里插入图片描述

1.3 字符和字符串

字符串常量"x"和字符常量'x'不同。区别之一在于**' x '是基本类型(char),而"x"是派生类型(char数组);区别之二是"x"实际上由两个字符组成: 'x'和空字符\0**

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3YcyqwYx-1633312565221)(E:\Typora\Image\image-20211003104354536.png)]

1.4 strlen()和sizeof()区别

上一章提到了sizeof运算符,它以字节为单位给出对象的大小。strlen ()函数给出字符串中的字符长度

#include <stdio.h>

#include <string.h> //提供strlen()函数原型

#define PRAISE "Hello World!" //定义常量



int main(void)

{

  char name[40];

  //java中的数组是int[] arr;括号换了个位置



  printf("Name:");

  scanf("%s",name);

  printf("%zd %zd",strlen(name),sizeof(name));



  return 0;

}


结果为:
Name:pyy
3 40
PS D:\Code\C>

sizeof运算符报告,name数组有40个存储单元。但是,只有前11个单元用来储存Serendipi所以strlen ()得出的结果是1l。name数组的第12个单元储存空字符,strlen()并未将其计入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e7wdMXyc-1633312565226)(E:\Typora\Image\image-20211003105426561.png)]

二、常量和C预处理器

有时,在程序中要使用常量。例如,可以这样计算圆的周长:circumference = 3.14159 * diameter;

这里3.1415926代表常量pi(Π)

这种情况最好用符号常量,如下计算机会自动进行替换

circumference = pi * diameter;

常量比数字表达的信息更多

owed = 0.015 * housevalue;

owed = taxrate * housevalue; 如果阅读一个很长的程序,第2条语句所表达的含义更清楚。

如何创建符号常量?

float taxrate;

taxrate = 0.015;

这样做提供了一个符号名,但是taxrate是一个变量,程序可能会无意间改变它的值。

C语言还提供了一种预处理器的方式,只需在顶部添加一行

#define TAXRATE 0.015

编译程序时,程序中所有的TA.XRATE都会被替换成0.015。这一过程被称为编译时替换(compile-timesubstitution)。在运行程序时,程序中所有的替换均已完成

2.1 const限定符

C90标准新增了const关键字,**用于限定一个变量为只读。**其声明如下:const int MONTHS = 12; ll MONTHS在程序中不可更改,值为12

这使得MONTHS 成为一个只读值。也就是说,可以在计算中使用MONTHS,可以打印 MONTHs,但是不能更改MONTHs的值。const用起来比#define更灵活

const修饰的是变量,为只读

三、printf()和scanf ()

虽然printf ()是输出函数,scanf()是输入函数。工作原理几乎一致

3.1 printf()

请求printf()函数打印数据的指令要与待打印数据的类型相匹配。例如,打印整数时使用%d,打印字符时使用%c。这些符号被称为转换说明(conversion specification),它们指定了如何把数据转换成可显示

转换说明及打印的输出结果 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AGXCR3C0-1633312565232)(E:\Typora\Image\image-20211003111739030.png)]

格式字符串中的转换说明一定要与后面的每个项相匹配!

3.1.1 printf ()的转换说明修饰符

在%和转换字符之间插入修饰符可修饰基本的转换说明

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oaFo7pBd-1633312565234)(E:\Typora\Image\image-20211003111751384.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SsYtGRDw-1633312565235)(E:\Typora\Image\image-20211003113842373.png)]

常见的:

.数字:表示的就是精度

5.2f意思是字段宽度为5,小数点后两位数字

数字:代表的是字段宽度如%4d

3.2 scanf ()

如果用scanf ()读取基本变量类型的值,在变量名前加上一个&;

如果用scanf()把字符串读入字符数组中,不要使用&。

3.2.1 scanf ()的转换说明修饰符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sqEnE8Nr-1633312565236)(E:\Typora\Image\image-20211003114152284.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ectEScG-1633312565238)(E:\Typora\Image\image-20211003114234646.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J2l86oAC-1633312565239)(E:\Typora\Image\image-20211003114241728.png)]

简单了解一下...

这本书也太tm难学了!!!

四、关键概念

字符串是一系列被视为一个处理单元的字符。

char name [ 30]; 要确保有足够多的元素来储存整个字符串(包括空字符)

strlen()函数(声明在string.h头文件中)可用于获得字符串的长度(末尾的空字符不计算在内)。scanf ()函数中的转换说明是%s时,可读取一个单词。

C预处理器为预处理器指令(以#符号开始)查找源代码程序,并在开始编译程序之前处理它们。

printf()和scanf ()函数对输入和输出提供多种支持。两个函数都使用格式字符串,其中包含的转换说明表明待读取或待打印数据项的数量和类型。另外,可以使用转换说明控制输出的外观:字段宽度、小数位和字段内的布局。

五、编程练习

代码和结果都放在代码块中了!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t9DV1fYe-1633312565241)(E:\Typora\Image\image-20211003113050091.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xyBW0FTr-1633312565243)(E:\Typora\Image\image-20211003113121481.png)]

1.c

#include <stdio.h>



int main(void)

{

  char fname[20], lname[20];



  printf("Please enter your first name: ");

  scanf("%19s", fname); //19是字段长度

  printf("Please enter your last name: ");

  scanf("%19s", lname);

  printf("Hello! %s, %s.\n", fname, lname);



  return 0;

}

2.c

#include <stdio.h>

#include <string.h>



int main(void)

{

  int len = 0;

  char name[20];



  printf("Please enter your name:");

  scanf("%19s", &name);

  len = strlen(name);

  printf("Print your name:\n");

  printf("a.\"%s\"\n", name);//正常的打印

  printf("b.\"%20s\"\n", name); //在宽度为20的字段右端打印name,包括双引号

  printf("c.\"%-20s\"\n", name); //从字段的左侧开始打印该项

  printf("d.%*s\n", len + 3, name);



  return 0;

}





Please enter your name:pyy
Print your name:
a."pyy"
b."                 pyy"
c."pyy                 "
d.   pyy

3.c

#include <stdio.h>



int main(void)

{

  float num;



  printf("Please enter a float number:");

  scanf("%f", &num);

  printf("The input is %.1f or %.1e.\n", num, num);//表达两种计数法.1f表示小数点后两位
    //.1e表达浮点数的计数法



  return 0;

}


   
Please enter a float number:2.3
The input is 2.3 or 2.3e+000.
  
    
这是C语言的浮点数常量的科计数法
2.3e+02
    2.3*10的二次方
1.0e+003
    1.0*10的三次方

4.c

#include <stdio.h>
#define LEN 30

int main(void)
{
    float heigh;
    char name[LEN];

    printf("Please enter your name:");
    scanf("%29s", &name);//接受name
    printf("Hello! %s, how tall you are(inch):", name);
    scanf("%f", &heigh);//接受height
    printf("%s, you are %.3f feet tall.\n", name, heigh / 12.0);

    return 0;
}






Please enter your name:pyy
Hello! pyy, how tall you are(inch):178
pyy, you are 14.833 feet tall.

5.c

#include <stdio.h>

#define BIT 8



int main(void)

{

  float speed, size, time;



  printf("Please enter net speed(Mbit/s):");

  scanf("%f", &speed);

  printf("Please enter file size(MB):");

  scanf("%f", &size);

  time = size * BIT / speed; //b和B转换单位是8
    

  printf("At %.2f megabits per secnod, ", speed);

  printf("a file of %.2f megabytes ", size);

  printf("downloads in %.2f seconds.\n", time);



  return 0;

}
简单不作详细解释
    Please enter net speed(Mbit/s):10
Please enter file size(MB):20
At 10.00 megabits per secnod, a file of 20.00 megabytes downloads in 16.00 seconds.

6.c

#include <stdio.h>

#include <string.h>



int main(void)

{

  int x, y;

  char fname[20], lname[20];



  printf("Please enter your first name: ");

  scanf("%19s", &fname);

  printf("Please enter your last name: ");

  scanf("%19s", &lname);

  x = strlen(fname);

  y = strlen(lname);

  printf("%s %s\n", fname, lname);

  printf("%*d %*d\n", x, x, y, y);//后面会详细解释*的作用,作用是与尾对齐

  printf("%s %s\n", fname, lname);

  printf("%-*d %-*d\n", x, x, y, y);



  return 0;

}


Please enter your first name: pyy
Please enter your last name: caq
pyy caq
  3   3
pyy caq
3   3

7.c

#include <stdio.h>

#include <float.h>



int main(void)

{

  float f_value = 1.0 / 3.0;

  double d_value = 1.0 / 3.0;

//1、%lf  双精度浮点型,也就是double型的格式,默认保留6位小数。
//2、%.2lf  同上,不过限制了,值保留2位小数。


  printf("1.0 / 3.0 display 6 decimal places:\n");

  printf("f_value = %.6f\nd_value = %.6lf\n", f_value, d_value);

  printf("\n1.0 / 3.0 display 12 decimal places:\n");

  printf("f_value = %.12f\nd_value = %.12lf\n", f_value, d_value);

  printf("\n1.0 / 3.0 display 16 decimal places:\n");

  printf("f_value = %.16f\nd_value = %.16lf\n", f_value, d_value);

  printf("\nfloat and double maximum significant digits:\n");

  printf("FLT_DIG = %d, DBL_DIG = %d\n", FLT_DIG, DBL_DIG);

  //↑FLTDIG代表float有效十进制数字位数;

  //↑DBL_DIG代表double有效十进制数字位数;



  return 0;

}





1.0 / 3.0 display 6 decimal places:
f_value = 0.333333
d_value = 0.333333

1.0 / 3.0 display 12 decimal places:
f_value = 0.333333343267
d_value = 0.333333333333

1.0 / 3.0 display 16 decimal places:
f_value = 0.3333333432674408
d_value = 0.3333333333333333

float and double maximum significant digits:
FLT_DIG = 6, DBL_DIG = 15