文章目录[隐藏]
章节要点
// talkback.c --演示与用户交互
#include<stdio.h>
#include<string.h>
#define DENSITY 62.4
int main(void)
{
float weight,volume;
int size,letters;
char name[40];
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;
}
新特性:
- 用数组(array)存储字符串(character string)。在该程序中,用户输入的名被存储在了数组中,该数组占用内存中40个连续的字节,每个字节存储一个字符值。
- 使用%s转换说明来处理字符串的输入与输出。注意:scanf()中,name没有&前缀,而weight有。
- 用C预处理器把字符常量DENSITY定义为62.4
-
用C函数strlen()获取字符串长度
4.2 字符串简介
字符串(character string)是一个或多个字符的序列。如下:
"zing went the strings of my heart!"
双引号告诉编译器它括起来的是字符串,如单引号一样。4.2.1 char类型数组和null字符
末尾的\0.这是空字符(null character),C语言用它标记字符串的结束。它不是数字0,它是非打印字符,其ASCII码值是(或等价于)0.C的字符串一定要以空字符结束,意味着数组容量必须至少比存储字符串中的字符多1.name[40]有40个存储单元,只能存储39个字符。
数组可以看作为一行连续的多个存储单元,数组是同类型数据元素的有序序列。
使用字符串
// praise1.c --使用不同类型的字符串 #include<stdio.h> #define PRAISE "You are an extraordingnary being." int main(void) { char name[40]; printf("What's your name?\n"); scanf("%s",name); printf("Hello,%s.%s\n",name,PRAISE); return 0; }
(重要!)scanf()只读取了郭 安中的郭。它在遇到第1个空白(空格、制表符或者换行符)就不再读取了。
根据%s转换说明,scanf()只会读取字符串中的一个单词。而不是仪征句话
C语言中fgets()用于读取一般字符串。
4.2.3 strlen()函数
// praise1.c --使用不同类型的字符串 #include<stdio.h> #include<string.h> #define PRAISE "You are an extraordingnary being." int main(void) { char name[40]; printf("What's your name?\n"); scanf("%s",name); printf("Hello,%s.%s\n",name,PRAISE); printf("Yoour name of %d letters occupies %d memory cells.\n",strlen(name),sizeof name); printf("The phrase of praise has %d letters",strlen(PRAISE)); print("and occupies %d memory cells.\n",sizeof PRAISE); return 0; }
ANSI C之前的编译器移除#include<string.h>
string.h头文件包含多个与字符串相关的函数原型,包括strlen().
一般而言,C把函数库中相关的函数归为一类,并为每类函数提供一个头文件。
对于PRAISE,用strlen()得出的也是字符串中的字符数(包括空格标点符号)。
sizeof运算符给的数更大,因为它把末尾看不见的空字符也计算在内了,它一般计算双引号内的字符数。
C99和C11标准专门为sizeof运算符的返回类型添加了%zd对于strlen同样适用。
对于sizeof,运算对象是类型时,圆括号必不可少,特定量,可有可无。推荐所有情况都写圆括号。
对于要处理字符串的程序。strlen()很有用。4.3 常量和C预处理器
有时候,在程序中需要用到常量
- 常量名字比常量能代表的信息更多。
- 程序多出使用这个常量为了修改方便。
方法一:声明一个变量,然后为变量赋值。float taxrate; taxrate = 0.015;
这样做提供了一个符号名,但是taxrate是一个变量,程序可能会无意间改变它的值。
因此------C预处理器。#define TAXRATE 0.015
此时,编译程序时,所有的TAXRATE都会被替换成0.015.这一个过程被称为_编译时替换(compile-time substitution)_在运行程序时候,程序中所有的替换均已完成。这样定义的常量也称为明示常量(manifest constant)。
(名称与数值之间没有等号哟~)
#define NAME value
(不加分号!一般常量名字大写)
// pizza.c --在比萨饼程序中使用已定义的常量
#include<stdio.h>
#define PI 3.14159
int main()
{
float area,circum,radius;
printf(" What is the radius of your pizza?\n");
scanf("%f",&radius);
area = PI*radius*radius;
cirum = PI*2*radius;
printf("Your basic pizza parameters are as follows:\n");
printf("circumference = %1.2f,area = %1.2f\n",circum,area);
return 0;
}
%1.2f表明,结果被四舍五入为两位小数输出。
//#define指令还可定义字符和字符串常量。前者使用双引号,后者使用双引号。
#define BEEP '\a'
#define TEE 'T'
#define ESC '\033'
#define OOPS "Now you have done it!"
//错误格式
#define TOES = 20
//如果这样子,替换TOES的是= 20,而不是20
4.3.1 const限定符
C90标准新增(只读)
const int MONTHS = 12; //MONTHS在程序中不可更改,值为12.
4.3.2 明示常量
C头文件limit.h和float.h分别提供了与整数类型和浮点类型大小限制相关的详细信息。
// defines.c 使用limit.h和float头文件中定义的明示常量
#include<stdio.h>
#include<limits.h>
#include<float.h>
int main(void)
{
printf("Some number limits for this system:\n");
printf("Biggest int :%d\n",INT_MAX);
printf("Smallest long long:%lld\n ",LLONG_MIN);
printf("One byte = %d bits on this system.\n",CHAR_BIT);
printf("Largest double:%e\n",DBL_MAX);
printf("Smallest normal float :%e\n",ELT_MIN);
printf("float precision = %d digits \n",ELT_DIG);
printf("float epsilon = %e\n",ELT_EPSILOW);
return 0;
}
4.4 printf()和scanf()
_I/O_函数
4.4.1 printf()函数
%d/%c:整数/字符;这些符号称为转换说明(conbersion specification),它们指定了如何把数据转换成可现实的形式。
4.4.2 使用printf()
// printout.c --使用转换说明
#include<stdio.h>
#define PI 3.141593
int main(void)
{
int number = 7;
float pies = 12.75;
int cost = 7800;
printf("The %d contestants ate %f berry pies.\n",number,pies);
printf("The value of pi is %f.\n",PI);
printf("Farewell! thou art too dear for my possessing,\n");
printf("%c%d\n",'$',2*cost);
return 0;
}
注意:格式字符串中的转换说明一定要与后面的每个项相匹配。
// %号的打印
printf("It's 90%% of my love for you");
4.4.3 printf()的转换说明修饰符
注意:类型可移植性。stddef.h头文件(在包含stdio.h头文件时已包含其中)把size_t定义成系统使用sizeof返回的类型值,这被称为底层类型(underlying type)printf()使用z修饰符表表示打印相应的类型。同样C还定义了ptrdiff_t类型和t修饰符来表示系统使用两个地址差值的底层有符号整数类型。
- float自动转换成double类型
- 使用修饰符和标记
// width.c --字段的宽度
#include<stdio.h>
#define PAGES 959
int main(void)
{
printf("*%d*\n",PAGES);
printf("*%2d*\n",PAGES);
printf("*%10d*\n",PAGES);
printf("*%-10d*\n",PAGES);
return 0;
}
第一个正常输出;第二个两个空格长度输出但是因为要3个数字,所以自动补齐到3,第四个10个字符,第5个10个但是结果位于最左侧。
// float.c --一些浮点型修饰符的组合
#include<stdio.h>
int main(void)
{
const double RENT = 3852.99;
printf("*%f*\n",RENT);
printf("*%e*\n",RENT);
printf("*%4.2f*\n",RENT);
printf("*%3.1f*\n",RENT);
printf("*%10.3f*\n",RENT);
printf("*%10.3E*\n",RENT);
printf("*%+4.2f*\n",RENT);
printf("*%010.2f*\n",RENT);
return 0;
}
如果修改const变量
// flags.c --演示一些格式的标记
#include<stdio.h>
int main(void)
{
printf("%x %X %#X\n",31,31,31);
printf("**%d**% d**% d**\n",42,42,-42);
printf("**%5d**%2.3d**%05d**%05.3d**\n",6,6,6,6);
return 0;
}
// stringf.c --字符串格式
#include<stdio.h>
#define BLURB "Authentic imitation!"
int main()
{
printf("[%2s]\n",BLURB);
printf("[%24s]\n",BLURB);
printf("[%24.5s]\n",BLURB);
printf("[%-24.5s]\n",BLURB);
return 0;
}
.x告诉计算机只打印x个字符。
4.4.4 转换说明的意义
转换说明把以二进制格式存储在计算机中的值转换成一系列字符(字符串)以便于显示。
例如:76的存储格式为01001100.%d转换说明将其转换成字符7和6,并显示76;%x转换成16进制4c;%c转换说明把01001100转换成字符L。
转换不是替换。而是换成某种格式打印出来。
-
转换不匹配
// intconv.c -- 一些不匹配的整型转换 #include<stdio.h> #define PAGES 336 #define WORDS 65618 int main(void) { short num = PAGES; short munm = -PAGES; printf("num as short and unsiged short:%hd %hu\n",num,num); printf("-num as short and unsigned short:%hd %hu\n",munm,munm); printf("num as int and char:%d %c\n",num,num); printf("WORDS as int,short,and char:%d %hd %c\n",WORDS,WORDS,WORDS); return 0; }
别期望用%u转换说明能把数字和符号分开。
犯傻了~~~
// floatcnv.c --不匹配的浮点型转换 #include<stdio.h> int main(void) { float n1 = 3.0; double n2 = 3.0; long n3 = 2000000000; long n4 = 1234567890; printf("%.le %.le %.le %.le\n",n1,n2,n3,n4); printf("%ld %ld\n",n3,n4); printf("%ld %ld %ld %ld\n",n1,n2,n3,n4); return 0; }
- 参数传递(留坑)
-
printf()的返回值
sqrt()函数,接受一个数作为参数,并返回该数的平方根。// prntval.c --printf()的返回值 #include<stdio.h> int main(void) { int a = 212; int rv; rv = printf("%d is a pig\n",a); printf("%d\n",rv); return 0; }
注意计算针对所有的字符数,包括空格和不可见的换行符。 -
打印较长的字符串
给字符串断行有三种方法// longstrg.c --打印较长的字符串 #include<stdio.h> int main(void) { printf("My name is "); printf("Guo an\n"); printf("My name is \ xiaoan\n"); printf("my name is " "Guoan2\n"); return 0; }
4.4.5使用scanf()
printf()函数使用变量、常量和表达式,而scanf()函数使用指向变量的指针。
- 如果使用scanf()读取基本变量类型的值,在变量名前面加一个 &;
- 如果scanf()把字符串读入字符数组中,不要使用&。
// input.c --何时使用&
#include<stdio.h>
int main(void)
{
int age;
float assets;
char pet[30];
printf("Enter your age,assets,and favorite pet.\n");
scanf("%d %f",&age,&assets);
scanf("%s",pet);
printf("%d $%.2f %s.\n",age,assets,pet);
return 0;
}
输入空格输出不会键入空白字符。
唯一例外的是%c转换的说明。根据%c,scanf()会读取每个字符,包括空白。
对于float类型和double类型,printf()都使用%f,%e,%E,%g和%G转换说明。而scanf()只把它们用于float类型,对于double类型要使用l修饰符。
叨叨几句... NOTHING