1-1 变量与算术表达式
编写程序,使用公式打印华氏温度与摄氏温度对照表
#include <stdio.h>
int main() {
//定义华氏,摄氏温度
float fah, cel; //fah= Fahrenheit 华氏温度 cel= celsius 摄氏温度
//定义表的下限,上限和步长
int lower, upper,step;
//定义初始值
lower = 0;
upper = 300;
step = 20;
fah = lower;
//根据公式,循环打印结果
while (fah <=upper) {
cel =(5.0 / 9.0) * (fah - 32.0);
printf("%3.0f%6.1f\n", fah, cel);
fah = fah + step;
}
return 0;
}
以上printf中的转换说明%3.0f表明待打印的浮点数(既fah)至少占3个字符宽,且不带小数点和小数部分;%6.1f表明另一个待打印的数(cel)至少占6个字符宽,且小数点后面有1位数字。
%d 按照十进制整型数打印
%6d 按照十进制整型数打印,至少6个字符宽
%f 按照浮点数打印
%6f 按照浮点数打印 至少6个字符宽
%.2f 按照浮点数打印,小数点后有两位小数
%6.2f 按照浮点数打印,至少6个字符宽,小数点后俩位小数
在c语言中,所有变量都必须先声明后使用,声明通常放在函数起始处,在任何可执行语句之前。声明用于说明变量的属性,它由一个类型名和一个变量表组成,例如:
int fah,cel;
int lower,upper,step;
其中,类型int表示其后所列变量为整数,与之相对应的,float表示所列变量为浮点数(既,可以带有小数部分的数)。int与float类型的取值范围取决于具体的机器。对于int 类型,通常为16位,其取值范围在-32768~+32767之间,也有用32位表示的int类型,float类型通常是32位,它至少有6位有效数字。
除int与float类型之外,c语言还提供了其他的一些基本数据类型,例如
char 字符—一个字节
short 短整型
long 长整型
double 双精度浮点型
练习:
1.修改温度转换程序,使之能在转换表的顶部打印一个标题。
方法1
#include <stdio.h>
int main() {
float fah, cel; //fah= Fahrenheit 华氏温度 cel= celsius 摄氏温度
int lower, upper,step;
lower = 0;
upper = 300;
step = 20;
fah = lower;
printf("************************");
printf("我的第一个程序—温度转换表");
printf("************************\n");
while (fah <=upper) {
cel =(5.0 / 9.0) * (fah - 32.0);
printf("%3.0f%6.1f\n", fah, cel);
fah = fah + step;
}
}
方法2
#include <stdio.h>
void staroutput() {
printf("*******************");
}
void wordoutput() {
char arr[] = "我的练习程序-温度转换表";
printf("%s", arr);
}
void title() {
staroutput();
wordoutput();
staroutput();
}
int main() {
//定义华氏,摄氏温度
float fah, cel; //fah= Fahrenheit 华氏温度 cel= celsius 摄氏温度
//定义表的下限,上限和步长
int lower, upper,step;
//定义初始值
lower = 0;
upper = 300;
step = 20;
fah = lower;
title();
printf(" \n");
//根据公式,循环打印结果
while (fah <=upper) {
cel =(5.0 / 9.0) * (fah - 32.0);
printf("%3.0f%6.1f\n", fah, cel);
fah = fah + step;
}
return 0;
}
2.编写一个程序打印摄氏温度转换为相应的华氏温度的转换表
摄氏温度转换为华氏温度 华氏度(°F)等于温度 以摄氏度(℃)倍9/5加上32: T (°F) = T (°C) ×9/5 + 32
#include <stdio.h>
int main() {
//定义华氏,摄氏温度
float fah, cel; //fah= Fahrenheit 华氏温度 cel= celsius 摄氏温度
//定义表的下限,上限和步长
float lower;
int upper, step;
//定义初始值
lower = -7;
upper = 148;
step = 11;
cel = lower;
//根据公式,循环打印结果
while (cel<=upper) {
fah =(5.0 / 9.0) * (cel + 32.0);
printf("%3.0f%6.1f\n", cel, fah);
cel= cel+ step;
}
return 0;
}
1-2 for语句
#include <stdio.h>
int main() {
int fah; //定义华氏度
for (fah=0;fah<= 300;fah=fah+20) //循环条件
printf("%3d %6.1f\n", fah, (5.0 / 9.0) * (fah - 32.0));
return 0;
}
它去掉了大部分代码,只使用了一个int类型的变量fah,在新引入的for语句中,温度的下限,上限和步长都是常量,而计算摄氏温度的表达式现在变成了printf函数的第三个参数,它不再是一个单独的赋值语句
练习:
修改温度转换程序,要求以逆序(既按照从300度到0度的顺序)打印温度转换表
#include <stdio.h>
int main() {
int fah;
for (fah=300;fah>= 0;fah=fah-20)
printf("%3d %6.1f\n", fah, (5.0 / 9.0) * (fah - 32.0));
return 0;
}
1-3符号常量
在以上程序中使用300,20等类似的“幻数”并不是个好习惯,它们几乎无法向以后阅读该程序的人提供什么信息,而且使程序的修改变的困难/处理这种幻数的一种方法是赋予他们有意义的名字。
#define指令可以把符号名(或称符号常量)定义为一个特定的字符串
#define 名字 替换文本
#include <stdio.h>
#define LOWER 0
#define UPPER 300
#define STEP 20
int main() {
int fah;
for (fah=LOWER;fah<= UPPER;fah=fah+STEP)
printf("%3d %6.1f\n", fah, (5.0 / 9.0) * (fah - 32));
return 0;
}
其中,LOWER,UPPER与STEP都是符号常量,而非变量,因此不需要出现在声明中。符号常量名通常用大写字母拼写,这样可以很容易与用小写字母拼写的变量名相区别。注意,#define指令行的末尾没有分号。
1-4字符输入-输出
标准库提供的输入/输出模型非常简单,无论文本从何处输入,输出到何处,其输入/输出都是按照字符流的方式处理。文本流是由多行字符构成的字符序列,而每行字符则由0个或多个字符组成,行末是一个换行符。标准库负责使每个输入/输出流都能够遵守这一模型。
标准库提供了一次读/写一个字符的函数,其中最简单的是getchar和putchar俩个函数。每次调用时,getchar函数从文本流中读入下一个输入字符,并将其作为结果值返回。
getchar
和 putchar
是 C 语言标准库中的两个函数,用于字符的输入和输出。
getchar
函数:
getchar
函数用于从标准输入(通常是键盘)读取一个字符。
它的使用方式如下:
#include <stdio.h>
int main() {
char c;
c = getchar();
// 在此处可以对读取到的字符 'c' 进行处理
return 0;
}
例如,如果用户输入字符 'A'
,那么 c
的值就会被赋值为 'A'
。
putchar
函数:
putchar
函数用于向标准输出(通常是屏幕)输出一个字符。
#include <stdio.h>
int main() {
char c = 'B';
putchar(c);
return 0;
}
在上述示例中,会在屏幕上输出字符 'B'
。
以下是一个综合使用 getchar
和 putchar
的简单示例:
#include <stdio.h>
int main() {
char c;
printf("请输入一个字符: ");
c = getchar();
printf("您输入的字符是: ");
putchar(c);
return 0;
}
在这个例子中,先提示用户输入一个字符,然后将用户输入的字符输出显示。
1-4-1文件复制
借助与getchar与putchar函数,把输入一次一个字符地复制到输出
#include <stdio.h>
int main() {
int c; //定义字符为整型
c = getchar(); //将用户输入赋值给c
while(c != EOF){ //EOF文件结束符 Ctrl + D 或 Ctrl + Z 来表示输入结束(即 EOF )
putchar(c); //输出c
c = getchar(); //再次让用户输入
}
}
#include <stdio.h>
int main() {
int c; //定义字符为整型
while((c = getchar()) != EOF) //EOF文件结束符 Ctrl + D 或 Ctrl + Z 来表示输入结束(即 EOF )
putchar(c); //输出c
}
练习:
1.验证表达式getchar()!=EOF的值是0还是1
#include <stdio.h>
int main(void) {
int c;
printf("请输入字符:\n");
c = (getchar()!= EOF);
printf("%d\n", c);
return 0;
}
2.编写一个打印EOF值的程序
#include <stdio.h>
int main() {
printf("EOF 的值是: %d\n", EOF);
return 0;
}
1.4.2字符计数
#include <stdio.h>
int main() {
double nc;
for (nc = 0; getchar() != EOF; ++nc);
printf("%.0f\n", nc);
}
1.4.3 行计数
以下程序用于统计输入中的行数,标准库保证输入文本流以行序列的形式出现,每一行均以换行符结束,统计行数等价于统计换行符的个数
#include <stdio.h>
int main() {
int c, n1;
n1 = 0;
while ((c = getchar()) != EOF)
if (c == '\n')
++n1;
printf("%d\n", n1);
}
练习:
编写一个统计空格,制表符与换行符个数的程序
#include <stdio.h>
int main() {
int countspacesnumb=0;//初始值统计空格个数
int tabsnumb=0; //初始值制表符个数
int linenumb=0; //初始化换行符个数
int c = 0;
while ((c = getchar()) != EOF) { //当用户返回EOF(end of file 文件结束)则跳出循环
if (c == ' ') {
countspacesnumb++; //如果满足条件 个数累计加一
}
else if (c == '\t ') {
tabsnumb++;
}
else if (c == '\n') {
linenumb++;
}
}
printf("统计表格个数为%d\n",countspacesnumb);
printf("制表符个数为%\n", tabsnumb);
printf("换行符个数为%d\n", linenumb);
return 0;
}
编写将输入复制到输出的程序,并将其中连续的多个空格用一个空格代替
#include <stdio.h>
int main() {
char c;
char prevChar = '\0'; // 用于记录前一个字符
printf("请输入内容:\n");
while ((c = getchar())!= EOF) { // 直到输入结束
if (c =='') { // 如果是空格
if (prevChar!='') { // 且前一个字符不是空格
putchar(' '); // 输出一个空格
}
} else { // 如果不是空格
putchar(c); // 直接输出
}
prevChar = c; // 更新前一个字符
}
return 0;
}
编写一个将输入复制到输出的程序,并将其中的制表符替换成 \ t,把回退符替换成 \ b,
把反斜杠替换成 \ \ 。这样可以将制表符和回退符以可见的方式显示出来
#include <stdio.h>
int main() {
int c;
while ((c = getchar())!= EOF) {
if (c == '\t') {
printf("\\t");
} else if (c == '\b') {
printf("\\b");
} else {
putchar(c);
}
}
return 0;
}
1.4.4单词计数
该程序用于统计行数,单词数和字符数
#include <stdio.h>
#define IN 1 //定义符号常量,表示在单词内的初值为1
#define out 0 //表示在单词外的初值为0
int main() {
int n;
int linenumb; //定义行数
int wordnumb; //定义单词数
int characnumb;//定义字符数
int state; //定义单词位置
linenumb = wordnumb = characnumb = state = 0; //将变量赋值为0
while ((n = getchar()) != EOF) {
++characnumb; //记录字符数 字符数每次循环加1,直到用户输入结束符
if (n == '\n') //记录用户输入有换行,则行数加1
++linenumb;
if (n == ' ' || n == '\n' || n == '\t') //如果n为换行符,或空值或制表符,则将state定义为out,表示不在单词内
state = out;
else if (state == out) {//如果state值为out,表示单词外
state = IN; //则将state的值表示在单词内,并计数
++wordnumb;
}
}
printf("%d %d %d\n",linenumb,wordnumb,characnumb);
return 0;
}
程序执行时,每当遇到单词的第一个字符,它就作为一个新单词加以统计,state变量记录程序当前是否正位于一个单词之中,它的初值是“不在单词中”,既初值被赋为out。
练习:
编写一个程序,以每行一个单词的形式打印并输入
#include <stdio.h>
#define TRUE 1
#define FALSE 0
main()
{
// 1.定义一个变量c用以获取字符,定义一个变量用来确定是否在单词中,赋值为false
int c;
int state = FALSE;
int count = 1;
// 2.采用while循环对输入行进行遍历
while((c = getchar()) != EOF)
{
if(c == ' ' || c == '\t' || c == '\n'){
state = FALSE;
}else if(state == FALSE) {
state = TRUE;//需要满足第一个条件方可进入第二个条件
putchar('\n');
}
putchar(c);
}
}
1-5 函数
c语言中的函数等价于Fortran语言中的子程序或函数,也等价于Pascal语言中的过程或函数。函数为计算的封装提供了一种简便的方法,此后使用函数时不需要考虑它是如何实现的。使用设计正确的函数,程序员无需考虑功能是如何实现的,而只需知道它具有哪些功能就够了
到目前为止,我们所使用的函数(如printf,getchar和putchar等)都是函数库中提供的函数,我们可以自己动手编写一些函数。
c语言没有像Fortran语言一样提供类似于**求幂运算符,我们现在通过编写一个求幂的函数power(m,n)来说明函数定义的方法。power(m,n)函数用于计算整数m的n次幂,其中n是正整数。对函数调用power(2,5)来说,其结果值为32。该函数并非一个实用的求幂函数,它只能处理较小的整数的正整数次幂,但对于说明问题足够了
下面是函数power(m,n)的定义及调用它的主函数
#include <stdio.h>
//power函数求底数的n次幂
int power(int x, int y) { //定义函数求幂次power
int i;
int result = 1 ;
for (i = 1; i <= y; i++) { //限制y的循环次数
result *=x; //y循环几次,x就乘几次,达到x的y次方乘积并将每次结果赋值给变量
}
return result; //返回值
}
int main()
{
int i = 0;
for (i = 0; i <= 10;i++) { //循环几次 便是几次幂
printf("%d次幂 2的%d次幂为%d -5的%d次幂为%d\n", i,i,power(2, i),i, power(-5, i));//power为自定义函数,需先定义
}
return 0;
}
main函数向power函数传递俩个参数,在调用执行完成时,power函数向main函数返回一个格式化的整数并打印
printf("%d次幂 2的%d次幂为%d -5的%d次幂为%d\n", i,i,power(2, i),i, power(-5, i));
出现在main函数之前的声明语句
int power(int x, int y) ;
表明power函数有两个int类型的参数,并返回一个int类型的值,这种声明称为函数原型,它必须与power函数的定义和用法一致,如果函数的定义,用法与函数原型不一致,将出现错误
函数原型与函数声明中参数名不要求相同。合适的参数名能够起到很好的说明性作用,因此我们在函数原型中总指明参数名,如果没有声明某个参数的类型,则默认为int类型
练习:
重新编写温度转换程序,使用函数实现温度转换计算
float fahrToCelsius(float fahr);
int main()
{
printf("%3s %6s\n", "fahr", "Celsius");//打印标题到首部
for (float fahr = 0; fahr <= 300; fahr += 20)
printf("%3.0f %8.1f\n", fahr, fahrToCelsius(fahr));
return 0;
}
float fahrToCelsius(float fahr)
{
//返回摄氏温度值
return 5.0 * (fahr - 32.0) / 9.0;
}
1-6 字符数组
字符数组是c语言中最常用的数组类型,我们通过编写程序,来说明字符数组以及操作字符数组的函数用法,该程序读入一组文本行,并把最长的文本行打印出来
#include <stdio.h> //预处理指令,用于包含标准输入输出头文件,以便能够使用诸多printf和getchar等标准输入输出函数
#define MAXLINE 1000 //定义了一个常量MAXLINE,其值为1000,表允许最大输入行长度
int getline(char line[], int maxline); //获取输入并返回最长长度
void copy(char to[], char from[]); //复制字符数组
//函数声明,告诉编译器后面会有getline和copy这两个函数
//主函数
int main() {
int len; //用于存储当前输入行的长度
int max; //用于存储目前为止发现的最长行的长度
char line[MAXLINE]; //用于存储当前读取的输入行。
char longest[MAXLINE];//用于存储最长的输入行
max = 0;//初始化最大长度为0
while ((len = getline(line, MAXLINE)) > 0) //这是一个循环,不断强调getline函数读取输入行,并将返回的长度赋值给len,,只要读取的行长度大于0(不是空行)就执行循环体
if (len > max) { //如果当前行大于max
max = len; //则更新最大长度
copy(longest, line);//调用copy函数将当前行复制到longest中,以保存最长的行
}
if (max > 0) //如果存在这样的行
printf("%s", longest); //打印出最长的行
return 0;
}
//getline函数用于读取一行输入并获取最长长度
int getline(char s[], int lim) {
int c, i;
for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
/*
通过一个循环读取字符,直到达到输入行的最大长度减1(为了留一个位置给字符串结束符'\0'), 或者遇到文件结束符
EOF,或者遇到换行符’\n‘。将读取到的字符存储到s数组中
*/
s[i] = c;
if (c == '\n') { //如果读取到的最后一个字符是换行符
s[i] = c; //将换行符存入数组
++i; //增加长度计数
}
s[i] = '\0';//在字符串末尾添加结束符
return i; //返回输入行长度
}
void copy(char to[], char from[]) {
int i;//初始化索引变量i为0
i = 0;
while ((to[i] = from[i]) != '\0')//通过一个循环,逐个字符地将原数组的内容复制到目标数组,直到遇到字符串结束符‘\0’
++i;//增加索引,以便处理下一个字符
}