C自学笔记

数据和C

显示八进制和十六进制

/*十进制,八进制,十六进制,打印十进制数100*/
#include <stdio.h>
int main(void){
	int x=100;
	
	printf("dec=%d;octal=%o;hex=%x\n",x,x,x);
	printf("dec=%d;octal=%#o;hex=%#x\n",x,x,x);
	
	return 0;
} 

十进制%d,八进制%o,十六进制,%x。

要显示前缀必须使用%#d,%#o,%#x。

整数类型

short int类型:占用空间比int类型少,常用于较小数值场合节省空间。与int相似

long int类型:占用存储空间比int多,适用于较大数值的场合。与int类似

long long int或long long占用的存储空间可能比long多适用于更大数值的场合。至少占64位与int类似

unsigned int或unsigned 只用于非负数的场合。这种类型与有符号类型表示的范围不同。例如16位unsigned int允许取值范围是0~65535,而不是-32768~32767。可以表示更大的数。

整数溢出

/*整数溢出超出系统允许的最大int值*/
#include <stdio.h>
int main()
{
	int i=2147483647;
	unsigned int j=4294967295u;
	
	printf("%d %d %d\n",i,i+1,i+2);
	printf("%u %u %u\n",j,j+1,j+2);
	
	return 0;
 } 

编译时出现问题

1. 问题描述:

     warning: this decimal constant is unsigned only in ISO C90

2.c的标准里面描述:

The C90 rule that the default type of a decimal integer constant is either int, long, or
unsigned long, depending on which type is large enough to hold the value without overflow,
simplifies the use of constants. The choices in C99 are int, long and long long.
C89 added the suffixes U and u to specify unsigned numbers. C99 adds LL to specify long
long.
Unlike decimal constants, octal and hexadecimal constants too large to be ints are typed as
unsigned int if within range of that type, since it is more likely that they represent bit
patterns or masks, which are generally best treated as unsigned, rather than “real” numbers.
Little support was expressed for the old practice of permitting the digits 8 and 9 in an octal
constant, so it was dropped in C89.
A proposal to add binary constants was rejected due to lack of precedent and insufficient utility.
Despite a concern that a “lower-case-l” could be taken for the numeral one at the end of a
numeric literal, the C89 Committee rejected proposals to remove this usage, primarily on the
grounds of sanctioning existing practice.

C语言中常量值默认是一个32位的有符号整型数。由于2394967295无法用32位的有符号整型数表示,所以会有报警产生,即该问题通常出现在默认型存储不够的情况下。

3.解决方法:

1 在常数后面增加一个U标识,如果是long或longlong类型加UL或ULL,如4286545791U进行类型强制转换,这样就不会报警了
2 使用十六进制的数字,如0xFFFFFFFF
3 使用gcc -std=c99 用99标准来编译

                        
原文链接:https://blog.csdn.net/chilv/article/details/51859196

溢出为未定位行为。

打印short,long,long long和unsigned类型

/*更多的printf()的特性*/
#include <stdio.h>
int main(void)
{
	unsigned int un=3000000000u;/*int为32位和short为16位的系统*/
	short end=200;
	long big=65537;
	long long verybig=12345678908642;
	
	printf("un=%u and not %d\n",un,un);
	printf("end=%hd and %d\n",end,end);
	printf("big=%ld and not %hd\n",big,big);
	printf("verybig=%lld and not %ld\n",verybig,verybig);
	
	return 0; 
 } 

使用字符:char类型

声明char类型变量

char类型变量的声明方式与其他类型变量的声明方式相同。

char response;

char itable,latan;

以上声明了3个char类型变量;response,itable,和latan。

char broiled;         /*声明一个char类型变量*/

broiled='T';         /*为其赋值,正确*/

broiled=T;          /*错误,此时T是一个变量*/

broiled="T";          /*错误,此时“T”是一个字符串*/

#include <stdio.h>
//显示字符的代码编号 
int main()
{
	char ch;
	
	printf("Please enter a character.\n");
	scanf("%c",&ch);//用户输入字符
	printf("The code for %c is %d.\n",ch,ch);
	
	return 0; 
}

%c指明待打印的字符。%d转换说明打印char类型变量的值。

可移植类型:stdint.h和inttypes.h

#include <stdio.h>
#include <inttypes.h>//支持可移植类型 
int main(void)
{
	int32_t me32; //me32是一个32位有符号整型变量
	
	me32=45933945;
	printf("First,assume int32_t is int:");
	printf("me32= %d\n",me32);
	printf("Next,let's not make any assumptions.\n");
	printf("Insteak,use a \"macro\" from inttypes.h: ");
	printf("me32=%" PRId32 "\n",me32);
	
	return 0; 
 } 

        最后一个printf()中PRId32被定义在inttypes.h中的“d”替换

        该语句等价与printf(“me32=%”"d""\n",me32);

float,double和long double

1.声明浮点型变量

        浮点型变量声明和初始化和整形相同

 float noah,jonah; double trouble;float planck=6.63e-34;long double gnp;

2.浮点型常量

基本形式为有符号的数字(包括小数点)后面紧跟e或者E。不要在浮点型常量中间加空格:

1.56 E+12(错误!)

3.打印浮点值

#include <stdio.h>
int main(void)
{
	float aboat=32000.0;
	double abet=2.14e9;
	long double dip=5.32e-5;
	
	printf("%f can be written %e\n",aboat,aboat);
	printf("And it's %a in hexadecimal,powers of 2 notation\n",aboat);
	printf("%f can be written %e\n",abet,abet);
	printf("%lf can be written %le\n",dip,dip);
	
	return 0;
 } 

        %f打印十进制计数法的float和double类型浮点数,%e打印指数计数法的浮点数。打印long double类型要使用%lf,%le或者%la。

4.浮点值的上溢和下溢

 演示舍入错误

#include <stdio.h>
int main(void)
{
	float a,b;
	
	b=2.0e20+1.0;
	a=b-2.0e20;
	printf("%f\n",a);
	
	return 0;
}

计算机缺乏足够的小数位来完成正确的运算。2.0e20后面有20个0.如果把该数加1,变化在21位。

类型大小

#include <stdio.h>
int main(void)
{
	printf("Type int has a size of %zd bytes.\n",sizeof(int));
	printf("Type char has a size of %zd bytes.\n",sizeof(char));
	printf("Type long has a size of %zd bytes.\n",sizeof(long));
	printf("Type long long has a size of %zd bytes.\n",sizeof(long long));
	printf("Type double has a size of %zd bytes.\n",sizeof(double));
	printf("Tyepe long double has a size of %zd bytes.\n",sizeof(long double));
	
	return 0;
}

运行结果为

Type int has a size of 4 bytes.
Type char has a size of 1 bytes.
Type long has a size of 4 bytes.
Type long long has a size of 8 bytes.
Type double has a size of 8 bytes.
Tyepe long double has a size of 16 bytes.

参数陷阱

参数错误的情况

#include <stdio.h>
int main(void)
{
	int n=4;
	int m=5;
	float f=7.0f;
	float g=8.0f;
	
	printf("%d\n",n,m);//参数太多 
	printf("%d %d %d\n",n);//参数太少 
	printf("%d %d\n",f,g);//值的类型不匹配 
	
	return 0;
}

转义序列示例

#include <stdio.h>
int main(void)
{
	float salary;
	
	printf("\aEnter your desired monthly salary:");
	printf("$_______\b\b\b\b\b\b\b");
	scanf("%f",&salary);
	printf("\n\t$%.2f a month is $%.2f a year.",salary,salary*12.0);
	printf("\rGee!\n");
	
	return 0;
 } 

\b退格,\t水平制表,\r回车

字符串和格式化输入/输出

前导程序

演示与用户交互

#include <stdio.h>
#include <string.h> //提供strlen()函数的原型 
#define DENSITY 62.4 //人体密度 
int main(void)
{
	float weight,volume;
	int size,letters;
	char name[40]; //name是一个可以容纳40个字符的数组
	
	printf("Hi! What's your first name?\n");
	scanf("%s",name);
	printf("%s,what's you 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; 
}

使用字符串

#include <stdio.h>
#define PRAISE "You are an extraordinary being."
int main(void)
{
	char name[40];
	
	printf("What's you name? ");
	scanf("%s",name);
	printf("Hello,%s. %s\n",name,PRAISE);
	
	return 0;
}

%sgaosu printf()打印一个字符串。%s出现了两次,程序打印两个字符串:一个储存在name数组中;一个由PRAISE表示。scanf()遇到第一个空白(空格、制表符、换行符)时就不在读取输入。

strlen()函数

#include <stdio.h>
#include <string.h>//提供strlen()函数的原型
#define PRAISE "You are an extraordinary being." 
int main(void)
{
	char name[40];
	
	printf("What's your name? ");
	scanf("%s",name);
	printf("Hello,%s.%s\n",name,PRAISE); 
	printf("Your name of %zd letters occupies %zd memory cells.\n",strlen(name),sizeof name);
	printf("The phrase of praise has %zd letters ",strlen (PRAISE));
	printf("and occupies %zd memory cells.\n",sizeof PRAISE);
	
	return 0;
}

对于PRAISE strlen()得出还是字符串中的字符数,sizeof运算符给出的数字更大,因为吧字符串末尾不可见的空字符计算在内。未明确表面计算机要给字符串预留多少空间,所以必须计算双引号内的字符数。

常量和C预处理器

#include <stdio.h>
#define PI 3.14159
int main(void)
{
	float area,circum,radius;
	printf("What is the raidus of your pizza?\n");
	scanf("%f",&radius);
	area=PI*radius*radius;
	circum=2.0*PI*radius;
	printf("Your basic pizza parameters are as follows:\n");
	printf("circumference=%1.2f,area=%1.2f\n",circum,area);
	
	return 0;
}

printf()语句中的%1.2f表明,结果四舍五入为两位小数输出。

const限定符

const限定一个变量为只读。

const int MONTHS=12;//MONTHS在程序中不可更改,值为12

        MONTHS成为一个只读值。可以计算使用,可以打印,不可更改。const比#define灵活。

明示常量

使用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",FLT_MIN);
	printf("float precision=%d digits\n",FLT_DIG);
	printf("float epsilon=%e\n",FLT_EPSILON);
	
	return 0;
 } 

Printf()和Scanf()

        printf()和scanf()是输出/输入函数,或者简称为I/O函数。

使用printf()

        使用转换说明

#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()函数使用%来识别转换说明,因此打印%成了问题。解决办法是使用两个%%号。

printf()的转换说明修饰符

        使用修饰符和标记的示例,字段宽度。

#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;
}

一些浮点型修饰符的组合

#include <stdio.h>

int main(void)
{
	const double RENT=3852.99;//const 变量
	
	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; 
 } 

演示一些格式标记

#include <stdio.h>
int main(void)
{
	printf("%x %X %#x\n",31,31,31);
	printf("**%d**% d**% d**\n",42,42,-42);
	printf("**%5d**%5.3d**%05d**%05.3d**\n",6,6,6,6);
	
	return 0;
 } 

字符串格式

#include <stdio.h>
#define BLURB "Authentic imitation!"
int main (void)
{
	printf("[%2s]\n",BLURB);
	printf("[%24s]\n",BLURB);
	printf("[%24.5s]\n",BLURB);
	printf("[%-24.5s]\n",BLURB);
	
	return 0;
}

        %2s字段被扩大为科荣达字符串中的所有字符,精度限制打印字符的个数。.5告诉printf()只打印5个字符。另外,-标记是的文本左对齐输出。

转换说明的意义

        转换说明把以二进制格式存储在计算机中的值转换为一些列字符便于显示。转换不是把原始值替换成转换后的值,转换说明是翻译说明,%d的意思是“把给定的值翻译成十进制整数文本并打印”。

转换不匹配

一些不匹配的的整型转换

#include <stdio.h>
#define PAGES 336
#define WORDS 65618
int main(void)
{
	short num=PAGES;
	short mnum=-PAGES;
	
	printf("num as short and unsigned short: %hd %hu\n",num,num);
	printf("-num as short and unsigned short: %hd %hu\n",mnum,mnum);
	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;
}

        num变量对应的转换说明%hd和%hu输出结果都是336,

        mnum变量对于的转换说明%u(无符号)输出结果为65200,并非期望的336.英文有符号short int类型的值在我们的参考系统中的表示方式所致。0~32767表示本身,数字32768~65535表示负数。65535表示-1,因此65200表示-336;被解释成int时,65200则代表65200,一个数字可以被解释成两个不同的值。

不匹配浮点型转换

#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;
}

        第一行,%e没有把整数转换为浮点数,%e转换说明让printf()函数认为待打印的值是double类型。当printf()查看n3时,除了查看n3的4字节除外,还会查看n3相邻的4字节,共8字节,组合解释为浮点数。因此,即使n3位数正确,%e转换说明和%ld转换说明解释的值也不同。最终得到的结果无意义。

printf()的返回值

#include<stdio.h>
int main(void)
{
	int bph2o=212;
	int rv;
	
	rv=printf("%d F is water's boiling point.\n",bph2o);
	printf("The printf() function printed %d characters.\n",rv);
	
	return 0;
}

        rv=printf()的形式把printf()的返回值赋给rv。因此该语句执行了两项任务:打印信息和赋值变量。计算针对所有字符数,包括空格和不可见换行符。

打印较长的字符串

#include <stdio.h>
int main(void)
{
	printf("Here's one way to print a ");
	printf("long string.\n");
	printf("Here's another way to print a\
 long string.\n");
	printf("Here's the newest way to print a "
	"long string.\n");//ANSI C
	
	return 0;
}

使用scanf()

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

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

#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; 
}

printf()和scanf()的*修饰符

        printf()的*修饰符。不预先指定字段宽度,通过程序指定,用*修饰符代替字段宽度。但是仍需要参数告诉函数,字段宽度应该是多少。如转换说明是%*d,参数列表包含*和d的对应值。

使用变宽输出字段

#include <stdio.h>
int main(void)
{
	unsigned width,precision;
	int number=256;
	double weight=242.5;
	
	printf("Enter a field width:\n");
	scanf("%d",&width);
	printf("The number is :%*d:\n",width,number);
	printf("Now enter a width and a precision:\n");
	scanf("%d %d",&width,&precision);
	printf("Weight=%*.*f\n",width,precision,weight);
	printf("Done!\n");
	
	return 0;
}

        变量width提供字段宽度,number是待打印的数字。因为转换说明中*在d的前面所以在printf()的参数列表中,width在number的前面。同样,width和precision提供打印weight的格式化信息。

        用户输入6,6是程序使用的字段宽度。类似地,接下来用户输入8和3,说明字段的宽度是8,小数点后面显示3位数字。一般而言,陈旭应根据weight的值来决定这些变量的值。

        scanf()中*的用法不同把*放在%和转换字符之间是,会使得scanf()跳过相应的输入项

#include <stdio.h>
int main(void)
{
	int n;
	
	printf("Please enter three integers:\n");
	scanf("%*d %*d %d",&n);
	printf("The last integer was %d\n",n);
	
	return 0;
}

        程序需要读取特定列的内容是,跳过功能很有用。

printf()用法提示

printf("%d %d %d\n",val1,val2,val3);

打印的数字可能参差不齐。

使用足够大的固定字段宽度可以让输出整齐美观。

printf("%9d %9d %9d\n",val1,val2,val3);

运算符、表达式和语句

循环简介

        鞋码转换成英寸的程序。

#include <stdio.h>
#define ADJUST 7.31						//字符常量 
int main(void)
{
	const double SCALE=0.333;			//const变量
	double shoe,foot;
	
	shoe=9.0;
	foot=SCALE*shoe+ADJUST;
	printf("Shoe size (men's)   foot length\n");
	printf("%10.1f %15.2f inches\n",shoe,foot);
	
	return 0; 
 } 

引入while循环

#include <stdio.h>
#define ADJUST 7.31				//字符常量 
int main(void)
{
	const double SCALE=0.333;	//const变量
	double shoe,foot;
	
	printf("Shoe size (men's)	foot length\n");
	shoe=3.0;
	while(shoe<18.5)			//while循环开始
	{							//块开始 
		foot=SCALE*shoe+ADJUST;
		printf("%10.1f %15.2f inches\n",shoe,foot);
		shoe=shoe+1.0;
	 } 							//块结束
	 printf("If the shoe fits, wear it.\n");
	 
	 return 0; 
}

基本运算符

        基本算数运算符:=、+、-、和/ 标准数学库pow()函数用于指数运算例如pow(3.5,2.2)返回3.5的2.2次幂。

赋值运算符

         C语言中,=是赋值运算符,

        bmw=2002;

        意思是把2002赋值给bmw。

三重赋值高尔夫竞标赛计分卡

#include<stdio.h>
int main(void)
{
	int jane,tarzan,cheeta;
	cheeta=tarzan=jane=68;
	printf("		  cheeta   tarzan    jane\n");
	printf("First round score %4d %8d %8d",cheeta,tarzan,jane);
	
	return 0;
}

乘法运算符

打印数字1~20的平方

#include <stdio.h>
int main(void)
{
	int num=1;
	
	while(num<21)
	{
		printf("%4d %6d\n",num,num*num);
		num+=1;
	}
	
	return 0;
 } 

指数增长

#include <stdio.h>
#define SQUARES 64				//棋盘中的方格数 
int main(void)
{
	const double CROP=2E16;		//世界小麦年产谷粒数
	double current,total;
	int count=1;
	
	printf("square	grains  	total	");
	printf("   fraction of \n");
	printf("	added   	grains	");
	printf("   World total\n");
	total=current=1,0;			//从一颗谷粒开始
	printf("%4d %13.2e %12.2e %12.2e\n",count,current,total,total/CROP); 
	while(count<SQUARES)
	{
		count+=1;
		current=2*current;		//下一个方格的谷粒翻倍
		total=total+current;	// 更新总数
		printf("%4d %13.2e %12.2e %12.2e\n",count,current,total,total/CROP); 
	}
	printf("That's all.\n");
	
	return 0;
}

除法运算符

演示除法

#include <stdio.h>
int main(void)
{
	printf("integer division:5/4 is %d\n",5/4);
	printf("integer division:6/3 is %d\n",6/3);
	printf("integer division:7/4 is %d\n",7/4);
	printf("floating division:7./4 is %1.2f\n",7./4.);
	printf("mixed division:	  7./4 is %1.2f\n",7./4);
	
	return 0;
}

        整数除法直接丢弃整个小数部分不计入四舍五入。混合整数和浮点计算的结果是浮点数。编辑器会把他们转换成相同的类型。

运算符优先级和求值顺序

#include <stdio.h>
int main(void)
{
	int top,score;
	
	top=score=-(2+5)*6+(4+3*(2+3));
	printf("top=%d,score=%d\n",top,score);
	
	return 0;
 } 

 其他运算符

sizeof运算符和size_t类型

#include <stdio.h>
int main(void)
{
	int n=0;
	size_t intsize;
	
	intsize=sizeof(int);
	printf("n=%d,n has %zd bytes; all ints have %zd bytes.\n",n,sizeof n,intsize);
	
	return 0;
}

        sizeof返回size_t类型值,为无符号整数类型。size_t为语言定义的标准类型。

求模运算符

秒数转换成分和秒

#include <stdio.h>
#define SEC_PER_MIN 60			//1分钟等于60秒 
int main(void)
{
	int sec,min,left;
	
	printf("Convert seconds to minutes and seconds!\n");
	printf("Enter the number of seconds (<=0 to quit):\n");
	scanf("%d",&sec);			//读取秒数
	while(sec>0)
	{
		min=sec/SEC_PER_MIN;	//截断分钟数
		left=sec% SEC_PER_MIN;	//剩下的秒数
		printf("%d seconds is %d minutes,%d seconds.\n",sec,min,left);
		printf("Enter next value(<=0 to quit):\n");
		scanf("%d",&sec); 
	 } 
	 printf("Done!\n");
	 
	 return 0;
}

递增运算符:++

#include <stdio.h>
int main(void)
{
	int ultra=0,super=0;
	
	while(super<5)
	{
		super++;
		++ultra;
		printf("super=%d,ultra=%d \n",super,ultra);
	}
	
	return 0;
 } 

        前缀和后缀的区别

#include <stdio.h>
int main(void)
{
	int a=1,b=1;
	int a_post,pre_b;
	
	a_post=a++;		//后缀递增
	pre_b=++b;		//前缀递增
	
	printf("a a_post b pre_b\n");
	printf("%ld %5d %5d %5d",a,a_post,b,pre_b);
	
	return 0; 
}

        a_post=a++后缀,使用了a的值之后,递增a

        pre_b=++b前缀,使用b之前,递增b

递减运算符:--

#include <stdio.h>
#define MAX 100
int main(void)
{
	int count =MAX+1;
	
	while(--count>0){
		printf("%d bottles of spring water on the wall,"
		"%d bottles of spring water!\n",count,count);
		printf("Take one down and pass it around,\n");
		printf("%d bottles of spring water!\n\n",count -1);
	}
	
	return 0;
}

语句

        语句是C的基本构建模块。一条语句相当于一条完整的计算机指令。

#include <stdio.h>
int main(void)				//计算前20个整数的和 
{
	int count,sum;			//声明
	
	count=0;				//表达式语句
	sum=0;					//表达式语句
	while (count++<20)		//迭代语句
		sum=sum+count;
	printf("sum=%d\n",sum);	//表达式语句 
	
	return 0;				//跳转语句 
}

类型转换

#include <stdio.h>
int main(void)
{
	char ch;
	int i;
	float f1;
	
	f1=i=ch='C';
	printf("ch=%c,i=%d,f1=%2.2f\n",ch,i,f1);
	ch=ch+1;
	i=f1+2*ch;
	f1=2.0*ch+i;
	printf("ch=%c,i=%d,f=%2.2f\n",ch,i,f1);
	ch =1107;
	printf("Now ch=%c\n",ch);
	ch=80.89;
	printf("Now ch=%c\n",ch);
	
	return 0;
}

        i=f1+2*ch;f1是浮点数,ch是字符,但是字符在表达式中被当作其ASCII值处理。所以,2*ch实际上是2乘以字符'D'的ASCII值(68),然后加到f1上。由于f1是浮点数,计算可能会导致意外的结果,因为字符和浮点数的混合运算在C语言中未定义。

        f1=2.0*ch+i;同样存在类型转换问题。2.0*ch会将字符'D'的ASCII值(68)乘以2.0,然后这个结果加上整型变量i的值。这个表达式的结果也是未定义的。

        ch =1107;:将整数值1107赋值给ch。由于1107超出了字符(通常是8位)的表示范围,这会导致ch的值被截断或转换为一个未定义的字符。

带参数的函数

#include<stdio.h>
void pound(int n);	//ANSII函数原型声明 
int main(void)
{
	int times=5;
	char ch='!';	//ASCII码是33
	float f=6.0;
	
	pound(times);	//int类型的参数
	pound(ch);		//和pound((int)ch);相同
	pound(f);		//和pound((int)f);相同
	
	return 0; 
}

void pound(int n)	//ANSI风格函数头
{
	while(n-- >0)
		printf("#");
	printf("\n"); 
 } 

C控制语句:循环

再探while循环

根据用户的键入整数求和

#include <stdio.h>
int main(void)
{
	long num;
	long sum=0L;			//把sum初始化为0
	int status; 
	
	printf("Please enter an integer to be summed");
	printf("(q to quit): ");
	status=scanf("%ld",&num);
	while(status==1)		//==的意思是等于
	{
	sum=sum+num;
	printf("Please enter next interger(q to quit): ");
	status=scanf("%ld",&num); 
	}
	printf("Those integers sum to %ld.\n",sum);
	
	return 0;
}

何时终止循环

#include <stdio.h>
int main(void)
{
	int n=5;
	
	while(n<7)
	{
		printf("n=%d\n",n);
		n++;
		printf("Now n=%d\n",n);
	}
	printf("The loop has finished.\n");
	
	return 0;
 } 

While:入口条件循环

index=10;
while(index++<5)
printf("Have a fair day or better.\n");

把第一行改成

index=3;

代码就可以运行。

语法要点

注意花括号的使用,糟糕的代码会创建无限循环

#include <stdio.h>
int main(void)
{
	int n=0;
	
	while(n<3)
	printf("n is %d\n",n);
	n++;
	printf("That's all this program does\n");
	
	return 0;
}

注意分号的位置

#include <stdio.h>
int main(void)
{
	int n=0;
	
	while(n++<3);
		printf("n is %d\n",n);
	printf("That's all this program does.\n");
	
	return 0;
}

用关系运算符和表达式比较大小

#include <math.h>
#include <stdio.h>
int main(void)
{
	const double ANSWER=3.14159;
	double response;
	
	printf("What is the value of pi?\n");
	scanf("%lf",&response);
	while(fabs(response-ANSWER)>0.0001)
	{
		printf("Try again!\n");
		scanf("%lf",&response);
	}
	printf("Close enough!\n");
	
	return 0;
 } 

什么是真

        C中的真和假的值

#include <stdio.h>
int main(void)
{
	int true_val,false_val;
	
	true_val=(10>2);			//关系为真的值
	false_val=(10==2);	//关系为假的值
	printf("true=%d;false=%d\n",true_val,false_val);
	
	return 0; 
}

        对c而言表达式为真的值是1,表达式为假的值是0。

其他真值

#include <stdio.h>
int main(void)
{
	int n=3;
	
	while(n)
		printf("%2d is true\n",n--);
	printf("%2d is false \n",n);
	
	n=-3;
	while(n)
		printf("%2d is true\n",n++);
	printf("%2d is false\n",n);
	
	return 0;
}

一般而言所有的非零值视为真,只有零被视为假。

真值的问题

#include <stdio.h>
int main(void)
{
	long num;
	long sum=0L;
	int status;
	
	printf("Please enter an integer to be summed ");
	printf("(q to quit): ");
	status=scanf("%ld",&num);
	while (status=1)
	{
		sum=sum+num;
		printf("Please enter next integer(q to quit): ");
		status=scanf("%ld",&num);
	}
	printf("Those integers sum to %ld.\n",sum);
	
	return 0;
}

while里status==1错误写成status=1,造成无限循环

新的Bool类型

#include <stdio.h>
int main(void)
{
	long num;
	long sum=0L;
	_Bool input_is_good;
	
	printf("Please enter and integer to be summed ");
	printf("(q to quit): ");
	input_is_good=(scanf("%ld",&num)==1);
	while(input_is_good)
	{
		sum=sum+num;
		printf("Please enter next integer(q to quit): ");
		input_is_good=(scanf("%ld",&num)==1);
	}
	printf("Those integers sum to %ld.\n",sum);
	
	return 0;
}

不确定循环和计数循环

#include <stdio.h>
int main(void)
{
	const int NUMBER=22;		//初始化 
	int count=1;
	
	while(count<=NUMBER)		//测试
	{
		printf("Be my Valentine!\n");	//行为
		count++;				//更新计数 
	 } 
	 
	 return 0; 
}

for循环

#include <stdio.h>
int main(void)
{
	const int NUMBER=22;
	int count;
	
	for(count=1;count<=NUMBER;count++)
		printf("Be my Valentine!\n");
		
	return 0;
 } 

使用for循环建立一个立方表

#include <stdio.h>
int main(void)
{
	int num;
	
	printf("    n   n cubed\n");
	for(num=1;num<=6;num++)
		printf("%5d %5d\n",num,num*num*num);
		
	return 0;
 } 

利用for的灵活性

可以使用递减运算符来递减计数器

#include <stdio.h>
int main(void)
{
	int secs;
	
	for(secs=5;secs>0;secs--)
		printf("%d seconds!\n",secs);
	printf("We have ignition!\n");
	return 0;
}

让计数器递增2,10等等

#include <stdio.h>
int main(void)
{
	char ch;
	
	for(ch='a';ch<='z';ch++)
		printf("The ASCII value for %c is %d.\n",ch,ch);
	return 0;
}

让递增量几何增长

#include <stdio.h>
int main(void)
{
	double debt;
	for (debt=100.0;debt<150.0;debt=debt*1.1)
		printf("Your debt is now $%.2f.\n",debt);
	return 0;
 } 

使用任意合法的表达式,无论什么表达式每次迭代都会更新表达式

#include <stdio.h>
int main(void)
{
	int x;
	int y=55;
	
	for(x=1;y<=75;y=(++x*5)+50)
		printf("%10d %10d\n",x,y);
	return 0;
}

可以省略一个或多个表达式

#include <stdio.h>
int main(void)
{
	int x;
	int y=55;
	
	for(x=1;y<=75;y=(++x*5)+50)
		printf("%10d %10d\n",x,y);
	return 0;
}

表达式不一定是变量赋初值,也可以使用printf()在执行循环的其他部分之前,支队第一个表达式求值一次或者执行一次。

#include <stdio.h>
int main(void)
{
	int x;
	int y=55;
	
	for(x=1;y<=75;y=(++x*5)+50)
		printf("%10d %10d\n",x,y);
	return 0;
}

逗号运算符

#include <stdio.h>
int main(void)
{
	const int FIRST_OZ=46;		//2013邮资
	const int NEXT_OZ=20;		//2013邮资
	int ounces,cost;
	
	printf(" ounces cost\n");
	for(ounces=1,cost=FIRST_OZ;ounces<=16;ounces++,cost+=NEXT_OZ)
		printf("%5d $%4.2f\n",ounces,cost/100.0);
	return 0; 
 } 

当zeno遇到for循环

#include <stdio.h>
int main(void)
{
	int t_ct;		//项计数
	double time, power_of_2;
	int limit;
	
	printf("Enter the number of terms you want: ");
	scanf("%d",&limit);
	for(time=0,power_of_2=1,t_ct=1;t_ct<=limit;t_ct++,power_of_2*=2.0)
	{
		time+=1,0/power_of_2;
		printf("time=%f when terms=%d.\n",time,t_ct);
	 } 
	return 0;
}

出口条件循环:do while

#include <stdio.h>
int main(void)
{
	const int secret_code=13;
	int code_entered;
	
	do
	{
		printf("To enter the triskaidekaphobia therapy club,\n");
		printf("please enter the secret code number: ");
		scanf("%d",&code_entered);
	}while(code_entered!=secret_code);
	printf("Congratulations!You are cured!\n");
	
	return 0;
}

入口条件循环

#include <stdio.h>
int main(void)
{
	const int secret_code=13;
	int code_entered;
	
	printf("To enter the triskaidekaphobia therapy club,\n");
	printf("please enter the secret code number: ");
	scanf("%d",&code_entered);
	while(code_entered!=secret_code)
	{
		printf("To enter the triskaidekaphobia therapy club,\n");
		printf("please enter the secret code number: ");
		scanf("%d",&code_entered);
	}
	printf("Congratulations!You are cured!\n");
	
	return 0;
}

下面是do while循环的通用形式:

do
    statement
while(expression);

嵌套循环

#include <stdio.h>
#define ROWS 6
#define CHARS 10
int main(void)
{
	int row;
	char ch;
	
	for(row=0;row<ROWS;row++)
	{
		for(ch='A';ch<('A'+CHARS);ch++)
			printf("%c",ch);
		printf("\n");
	}
	return 0;
 } 

嵌套变式

#include <stdio.h>
int main(void)
{
	const int ROWS=6;
	const int CHARS=6;
	int row;
	char ch;
	
	for(row=0;row<ROWS;row++)
	{
		for(ch=('A'+row);ch<('A'+CHARS);ch++)
			printf("%c",ch);
		printf("\n");
	}
	
	return 0;
}

数组简介

        数组是按顺序存储的一些列类型相同的值,如10个char类型或者15个int类型的值,整个数组有一个数组名,,通过整数下标访问数组中单独的项或元素。

float debts[20];

        debt是一个内含20个元素的数组,每个元素都可以存储float类型的值。注意,数组元素的编号从0开始,不是从1开始。可以给每个元素赋float类型的值。

        潜在的陷阱:C不会检查下标是否正确。

debts[20]=88.32;        //该数组元素不存在
debts[33]=828.12;       //该数组元素不存在

        编译器不会查找错误,运行程序时,会导致数据被放置在已被其他数据占用的地方,可能会破坏程序结果或者直接导致程序中断。

        数组类型可以是任意数据类型。

int nannies[22];    //可存储22个int类型整数的数组
char actors[26];    //可存储26个字符的数组
long big[500];      //可存储500个long类型的整数的数组

在for循环中遍历数组

#include <stdio.h>
#define SIZE 10
#define PAR 72
int main(void)
{
	int index,score[SIZE];
	int sum=0;
	float average;
	
	printf("Enter %d golf scores:\n",SIZE);
	for(index=0;index<SIZE;index++)
		scanf("%d",&score[index]);		//读取10个分数
	printf("The scores reed in are as follows:\n");
	for(index=0;index<SIZE;index++)
		printf("%5d",score[index]);			//验证输入
	printf("\n");
	for(index=0;index<SIZE;index++)
		sum+=score[index];					//求总分数
	average=(float) sum/SIZE;				//求平均分
	printf("Sum of scores=%d,average=%.2f\n",sum,average);
	printf("That's a handicap of %.0f.\n",average-PAR);
	
	return 0; 
}

使用函数返回值的循环示例

#include <stdio.h>
double power(double n,int p);		//ANSI函数原型 
int main(void)
{
	double x,xpow;
	int exp;
	printf("Enter a number and the postive integer power");
	printf("to which\nthe number will be raised.Enter q");
	printf("to quit.\n");
	while(scanf("%lf%d",&x,&exp)==2)
	{
		xpow=power(x,exp);			//函数调用
		printf("%.3g to the power %d is %.5g\n",x,exp,xpow);
		printf("Enter next pair of numbers or q to quit.\n"); 
	 } 
	 printf("Hope you enjoyed this power trip--bye!\n");
	 
	 return 0;
 } 
 double power(double n,int p)		//函数定义
 {
 	double pow=1;
 	int i;
 	
 	for(i=1;i<=p;i++)
 		pow*=n;
 	
 	return pow;						//返回pow的值 

C控制语句:分支和跳转

if语句

#include <stdio.h>
int main(void)
{
	const int FREEZING=0;
	float temperature;
	int cold_days=0;
	int all_days=0;
	
	printf("Enter the list of daily low temperatures.\n");
	printf("Use Celsius,and enter q to quit.\n");
	while(scanf("%f",&temperature)==1)
	{
		all_days++;
		if(temperature<FREEZING)
			cold_days++;
	}
	if(all_days!=0)
	printf("%d days total:%.1f%% were below feezing.\n",all_days,100.0*(float)cold_days/all_days);
	if(all_days==0)
		printf("No data entered!\n");
	
	return 0;
 } 

        while循环的条件利用scanf()的返回值来结束,因为scanf在读到非数字字符时会返回为0.temperature的类型是float而不是int,这样可以接受-2.5这样的值,也可以接受这样的值,

        while循环中的语句如下

if(temoerature<FREEZING)
    cold_days++;

        if语句指示计算机,如果读取的值小于0,就把cold_days递增1;如果temperature不小于0,就跳过cold_days++;语句,while循环继续读下一个温度值。

        接着程序又使用了两次if语句控制程序的输出。如果有数据,就打印结果:如果没有数据则打印消息。

        if语句被称分支语句或选择语句,因为它相当于一个交叉点,程序要在两条分支语句中选择一条执行。if语句的通用形式如下

if(expression)
    statement

        statement部分可以是一条简单语句,如本例,或者用花括号括起来的复合语句。

if(score>big)
    printf("Jackpot!\n");    //简单语句

if(joe>ron)
{                            //复合语句
    joecash++;
    printf("You lose,Ron.\n");
}

if else 语句

        if else可以在两条语句之间作选择。我们用if else形式修正

if(all_days!=0)
    printf("%d days total:%.1f%% were below freezing.\n",
            all_days,100.0*(float) clod_days/all_days);
if(all_days==0)
    printf("No data entered!\n");

另一个示例:介绍getchar()和putchar()

#include<stdio.h>
#define SPACE ' '				//SPACE表示单引号-空格-单引号 
int main(void)
{
	char ch;
	
	ch=getchar();				//读取一个字符
	while(ch!='\n')				//当一行未结束时
	{
		if(ch==SPACE)			//留下空格
			putchar(ch);		//该字符不变
		else
			putchar(ch+1);		//改变其他字符
		ch=getchar();			//获取下一个字符 
	 } 
	putchar(ch);				//打印换行符
	
	return 0; 
 } 

ctype.h系列的字符函数

#include <stdio.h>
#include <ctype.h>					//包含isalpha()的函数原型
int main(void)
{
	char ch;
	
	while((ch=getchar())!='\n')
	{
		if(isalpha(ch))				//如果是一个字符,
			putchar(ch+1);			//显示该字符的下一个字符
		else						//否则,
		    putchar(ch);			//原样显示 
	}
	putchar(ch);
	
	return 0; 
 } 

多重选择else if

#include <stdio.h>
#define RATE1 0.13230				//首次使用360kwh的费率 
#define RATE2 0.15040				//接着再使用108kwh的费率 
#define RATE3 0.30025				//接着再使用252kwh的费率 
#define RATE4 0.34025				//使用超过720kwh的费率
#define BREAK1 360.0				//费率的第一个分界点
#define BREAK2 468.0				//费率的第二个分界点
#define BREAK3 720.0    			//费率的第三个分界点
#define BASE1 (RATE1*BREAK1)		//使用360kwh的费用
#define BASE2 (BASE1+(RATE2*(BREAK2-BREAK1)))  //使用468kwh的费用
#define BASE3 (BASE2+(RATE3*(BREAK3-BREAK2)))  //使用720kwh的费用
int main(void)
{
	double kwh;						//使用的千瓦时
	double bill;					//电费
	
	printf("Please enter the kwh used.\n");
	scanf("%lf",&kwh);				//%lf对应double类型
	if(kwh<=BREAK1)
		bill=RATE1*kwh;
	else if (kwh<=BREAK2)			//360~468kwh 
		bill= BASE1 +(RATE2*(kwh-BREAK1));
	else if (kwh<=BREAK3)			//468~720kwh
		bill=BASE2+(RATE3*(kwh-BREAK2));
	else
		bill=BASE3+(RATE4*(kwh-BREAK3));
	printf("The charge for %.1f kwh is $%1.2f.\n",kwh,bill);
	
	return 0;
 } 

else与if配对

if(条件1)
    语句

if(条件2)
    语句

    else
    语句

else与条件2的语句匹配

if(条件)
{
    语句
    if(条件)
    语句
}
    else
    语句

else与条件1的语句匹配

多层嵌套的if语句

#include <stdio.h>
#include <stdbool.h>
int main(void)
{
	unsigned long num;				//待测试的数
	unsigned long div;				//可能的约数
	bool isPrime;					//素数标记
	
	printf("Please enter an integer for anlysis;");
	printf("Enter q to quit.\n");
	while(scanf("%lu",&num)==1)
	{
		for(div=2,isPrime=true;(div*div)<=num;div++)
		{
			if(num%div==0)
			{
				if((div*div)!=num)
				printf("%lu is divisible by %lu and %lu.\n",
						num,div,num/div);
				else
					printf("%lu is divisible by %lu.\n",
							num,div);
				isPrime=false;		//该数不是素数 
			}
		}
		if(isPrime)
			printf("%lu is prime.\n",num);
		printf("Please enter another integer for anlysis; ");
		printf("Enter q to quit.\n"); 
	 } 
	printf("Bye.\n");
	
	return 0;
 } 

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值