[C语言]学习之路
Posted 孤桜懶契
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[C语言]学习之路相关的知识,希望对你有一定的参考价值。
实例:C语言编程题
求100到300之间所有素数
#include <stdio.h>
int main(void)
{
int i,j;
for(i = 100;i <= 300; i++)
{
for(j = 2; j <= i; j++)
if(i%j == 0)
break;
if(j == i)
printf("%-4d",i); //-4d是左对齐
}
return 0;
}
预备计算机知识
汇编语言是最低级的语言,它可以直接与硬件打交道。高级语言有Pascal、Basic、Fortran等等。高级语言的一条语句对应低级语言的很多条语句,任何高级语言编写的程序都要经过编译程序的编译、连接才能成为可以运行的程序。
编译连接的过程也就是把高级语言翻译成机器语言(二进制机器码)的过程,而汇编语言是基本上与机器语言一 一对应的一种语言。这个翻译过程是由编译程序自动完成的。把C语言定为中级语言是有它的道理的,因为C语言既有汇编语言的存取底层硬件的能力,又具有高级语言的许多特点。熟练掌握了C语言,学习其它的各种编程语言应该是很轻松的了。C语言的书写格式:
1) 一个C语言编写的源程序,必定有一个主程序(称为main()函数,在C语言中子程序称为“函数”(当然,不要理解成为数学里面的“函数”)。但是决不能有一个以上的main函数(即只能有一个)。
2) 函数语句块用‘{’括号开始, 以‘}’反括号结束。这样的花括号必须成对出现。
3) 表达式写在小括号里面,以‘(’括号开始,以‘)’反括号结束。
4) 函数不能嵌套,即函数里面不能再套函数。(每一个函数是完成一个特定功能的函数模块)C语言的组成:
C语言是由许多函数组成的。其中只有一个主函数(main()函数)。C程序执行时总是从main函数的‘{’处开始,至main函数的反大括号\'}\'处结束。当然还有其它一些规则,这将在以后的学习中去熟悉它。C语言的书写规则:
C语言在书写时有它自身的特点:书写格式比较自由,在一行里可以写多条语句,一个语句也可以分写在多行上。虽然如此,在书写源程序时还是要注意哪些可以自由书写,而哪些必须要按照书写规则来书写。
几条规则写在下面:
1) 一行内可以写几个语句,建议一行不超过两条语句;
2) 一条语句可以写在多行上;
3) C语句不需要写行标号;
4) 每条语句及数据定义的后面要写上分号以表示该语句结束;
5) C语言中注释用 //来表示;
6) 建议书写时采用缩进格式;
7) 花括号、小括号都是成对出现的。一个最简单的C程序的编写:
/程序代码/ /注释部分/
main() /main是主函数名。紧跟在main后面的括号是放参数的。
括号里面为空说明main函数不需要参数/
{ /正写的大花括号表示main函数从这里开始/} /反写的大花括号表示main函数到这里结束/
说明:由于是一个演示程序,在函数体内并没有任何可以执行的语句,也就是这个程序什么事也不做。
这个程序就是这么简单: 写在一行上就是 main() { }
你在TC的编辑环境下把这段代码输入进去,按F9键编译连接,按CTRL_F5运行,一定很正常。但是什么结果也不会有,因为在main函数里面什么代码也没有。下面再举一个可以向屏幕上输出一条信息的例子:
main()
{
printf("这就是C语言编写的程序!"); /这一条语句的作用是向屏幕输出一条信息
”这就是C语言编写的程序!"/
}
在这个程序中,main函数只有一条语句:printf("这就是C语言编写的程序!");这个语句的作用是向屏幕输出一个字符串。有关这个语句的知识以后再讲。现在要注意的是一个C语言程序的框架是怎样组成的。C语言程序的几种文件格式:
1、 源程序---在TC集成环境中输入的程序文本称为源程序。源程序是一种文本文件。它是我们看得见并认识的一种文件。其扩展名为.C。例如你把文件保存为TEST,那么在磁盘上应看得到TEST.C这个文件。这样的文件可以用记事本打开。
2、二进制文件---写完了源程序后接着要做的是编译这个文件。在TC集成环境里是按ALT_F9键,编译后生成了一个二进制文件,这个二进制文件名为TEST.OBJ,也就是扩展名为OBJ的目标文件。
3、运行文件---最后一步是make(或Link),在TC集成环境里是按F9键Make之后生成了一个可以在DOS下运行的文件,其扩展名为EXE。如TEST.EXE。这个EXE文件是由第2步中的OBJ文件生成的。
OBJ文件虽然是二进制文件,而电脑又是可以运行二进制文件的,为什么还要把OBJ文件Link为EXE文件才能运行?这里的知识就比较多了,这里不能多讲。
但是要明白一点,在DOS下仅仅有了一个二进制文件还不能运行,因为操作系统要把这些二进制文件加以规划,把相应的数据、程序代码放到应该放的内存位置,这样的经过严密规划和组织好了的二进制文件才能运行。而这些只有在生成的EXE文件里面才做完了这些工作。
#include <stdio.h>
int main(void)
{
int i=015; //0开头的是八进制
printf("%d\\n",i);
return 0;
}
输出结果13
#include <stdio.h>
int main(void)
{
int x = 47;
printf("%x\\n",x);
printf("%X\\n",x);
printf("%#X\\n",x);
printf("%#x\\n",x);
return 0;
}
输出结果
2f
2F
0X2F
0x2f
%a,%A 读入一个浮点值(仅C99有效) %c 读入一个字符 %d 读入十进制整数 %i 读入十进制,八进制,十六进制整数 %o 读入八进制整数 %x,%X 读入十六进制整数 %s 读入一个字符串,遇空格、制表符或换行符结束。 %f,%F,%e,%E,%g,%G 用来输入实数,可以用小数形式或指数形式输入。 %p 读入一个指针 %u 读入一个无符号十进制整数 %n 至此已读入值的等价字符数 %[] 扫描字符集合 %% 读%符号 x是1~f,X是1~F #是带格式输出 例如0x代表十六进制
C语言常见误区
1.书写标识符时,忽略了大小写字母的区别。
main() { int a=5; printf("%d",A); }
编译程序把a和A认为是两个不同的变量名,而显示出错信息。C认为大写字母和小写字母是两个不同的字符。习惯上,符号常量名用大写,变量名用小写表示,以增加可读性。
2.忽略了变量的类型,进行了不合法的运算。
main() { float a,b; printf("%d",a%b); }
%是求余运算,得到a/b的整余数。整型变量a和b可以进行求余运算,而实型变量不允许进行“求余”运算。
3.将字符常量与字符串常量混淆。
char c;
c="a";
在这里就混淆了字符常量与字符串常量,字符常量是由一对单引号括起来的单个字符,字符串常量是一对双引号括起来的字符序列。C规定以“\\”作字符串结束标志,它是由系统自动加上的,所以字符串“a”实际上包含两个字符:‘a\'和‘\',而把它赋给一个字符变量是不行的。
4.忽略了“=”与“”的区别。
在许多高级语言中,用“=”符号作为关系运算符“等于”。如在BASIC程序中可以写if (a=3) then …但C语言中,“=”是赋值运算符,“”是关系运算符。如:
if (a==3) a=b;前者是进行比较,a是否和3相等,后者表示如果a和3相等,把b值赋给a。由于习惯问题,初学者往往会犯这样的错误。
5.忘记加分号。
6.多加分号。
7.输入变量时忘记加地址运算符“&”。
int a,b;
scanf("%d%d",a,b);
这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将a、b的值存进去。“&a”指a在内存中的地址。
8.输入数据的方式与要求不符。
①scanf("%d%d",&a,&b);输入时,不能用逗号作两个数据间的分隔符,如下面输入不合法:3,4输入数据时,在两个数据之间以一个或多个空格间隔,也可用回车键,跳格键tab。
②scanf("%d,%d",&a,&b);C规定:如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时应输入与这些字符相同的字符。下面输入是合法的:
3,4此时不用逗号而用空格或其它字符是不对的。
3 4 3:4
又如:scanf("a=%d,b=%d",&a,&b);输入应如以下形式:a=3,b=4
9.输入字符的格式与要求不一致。
在用“%c”格式输入字符时,“空格字符”和“转义字符”都作为有效字符输入。
scanf("%c%c%c",&c1,&c2,&c3);如输入a b c字符“a”送给c1,字符“ ”送给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。
10.输入输出的数据类型与所用格式说明符不一致。
例如,a已定义为整型,b定义为实型,a=3;b=4.5;printf("%f%d\\n",a,b);编译时不给出出错信息,但运行结果将与原意不符。这种错误尤其需要注意。
11.输入数据时,企图规定精度。scanf("%7.2f",&a);这样做是不合法的,输入数据时不能规定精度。
12.switch语句中漏写break语句。
例如:根据考试成绩的等级打印出百分制数段。
switch(grade) { case \'A\':printf("85~100\\n"); case \'B\':printf("70~84\\n"); case \'C\':printf("60~69\\n"); case \'D\':printf("<60\\n"); default:printf("error\\n");
由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如case \'A\':printf("85~100\\n");break;
13.忽视了while和do-while语句在细节上的区别。因为while循环是先判断后执行,而do-while循环是先执行后判断。
14.定义数组时误用变量。
int n; scanf("%d",&n); int a[n];
数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。
15.在定义数组时,将定义的“元素个数”误认为是可使的最大下标值。
main() {static int a[10]={1,2,3,4,5,6,7,8,9,10}; printf("%d",a[10]); }
C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。
16.在不应加地址运算符&的位置加了地址运算符。scanf("%s",&str);C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:scanf("%s",str);
17.同时定义了形参和函数中的局部变量。
int max(x,y) int x,y,z; {z=x>y?x:y; return(z); }
形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:
int max(x,y) int x,y; {int z; z=x>y?x:y; return(z); }
#include <stdio.h>
int main()
{
int iNumber1=1;
printf("%d\\n",iNumber1);
if(iNumber1>0)
{
int iNumber1=2;
printf("%d\\n",iNumber1);
if(iNumber1>0)
{
int iNumber1=3;
printf("%d\\n",iNumber1);
}
printf("%d\\n",iNumber1);
return 0;
}
}
1
2
3
2
1.在主函数main中,定义了第一个整形变量,为其赋值为1,赋值后使用printf函数输出变量。在程序的运行结果中可以看到,此时的iNumber的值为1
2.使用if语句进行判断,这里使用if语句的目的在于划分出一段语句块。因为位于不同作用域的变量可以使用相同的标示符,所以在if语句块中也定义一个iNumber变量,并为其赋值为2.再次使用printf函数输出变量,观察运行结果,发现第二个输出的值为2.此时值为2的变量在此作用域中就将值为1的变量屏蔽掉。
IF语句
语法格式为:
if(表达式) 语句1; else 语句2; 语句3;
NS图表示如下:
|------------| | 表达式 | |------|-----| | 真 | 假 | |------|-----| |语句1 |语句2| |------------| | 语句3 | |------------|
语句解释:对表达式1进行判断,结果为真(非0)时则执行语句1,若为假(为0)则执行语句2,完成执行后退出if并执行if后的语句3。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a=3,b=2,c=1; //输入a,b,c三个数
system("cls");
printf("[1]: %d, %d, %d\\n", a, b, c);
{
int b=5;
int c=12;
printf("[2]: %d,%d,%d\\n",a,b,c);
}
printf("[3] %d,%d,%d,",a,b,c);
return 0;
}
[1]: 3, 2, 1
3,5,12
[3] 3,2,1
基本的输入与输出
int scanf(const char \\*format, arg_list)
scanf主要从标准输入流中获取参数值,format为指定的参数格式及参数类型,如scanf("%s,%d",str,icount);
它要求在标准输入流中输入类似"son of bitch,1000"这样的字符串,同时程序会将"son of bitch"给str,1000给icount.
scanf函数的返回值为int值,即成功赋值的个数,在上例中如果函数调用成功,则会返回2,所以我们在写程序时,可以通过
语句if(scanf("%s,%d",str,icount) != 2){...}
来判断用户输入是否正确.
int printf(const char *format, arg_list)
printf主要是将格式化字符串输出到标准输出流中,在stdio.h头文件中定义了标准的输入和输出,分别是stdin,stdout.
arg_list可以是变量名,也可以是表达式,但最终都会以值的形式填充进format中.
int getc(FILE \\*fp)
getc主要是从文件中读出一个字符.常用的判断文件是否读取结束的语句为:(ch = getc(fp)) != EOF
,EOF为文件结束标志,定义在stdio.h中,就像EXIT_SUCCESS,EXIT_FAILURE
定义在stdlib.h中一样,文件也可以被理解为一种流,所以当fp为stdin时,getc(stdin)
就等同于getchar()了.
int putc(int ch,FILE \\*fp)
putc主要是把字符ch写到文件fp中去.如果fp为stdout,则putc就等同于putchar()了.
int getchar(void)
getchar主要是从标准输入流读取一个字符.默认的标准输入流即stdio.h中定义的stdin.但是从输入流中读取字符时又涉及到缓冲的问题,所以并不是在屏幕中敲上一个字符程序就会运行,一般是通过在屏幕上敲上回车键,然后将回车前的字符串放在缓冲区中,getchar就是在缓冲区中一个一个的读字符.当然也可以在while循环中指定终止字符,如下面的语句:while ((c = getchar()) != \'#\')
这是以#来结束的.
int putchar(int ch)
putchar(ch)主要是把字符ch写到标准流stdout中去.
char * gets(char \\*str)
gets主要是从标准输入流读取字符串并回显,读到换行符时退出,并会将换行符省去.
int puts(char \\*str)
puts主要是把字符串str写到标准流stdout中去,并会在输出到最后时添加一个换行符.
char *fgets(char \\*str, int num, FILE \\*fp)
str是存放读入的字符数组指针,num是最大允许的读入字符数,fp是文件指针.fgets的功能是读一行字符,该行的字符数不大于num-1.因为fgets函数会在末尾加上一个空字符以构成一个字符串.另外fgets在读取到换行符后不会将其省略.
int fputs(char \\*str, file *fp)
fputs将str写入fp.fputs与puts的不同之处是fputs在打印时并不添加换行符.
int fgetc(FILE \\*fp)
fgetc从fp的当前位置读取一个字符.
int fputc(int ch, file \\*fp)
fputc是将ch写入fp当前指定位置.
int fscanf(FILE \\*fp, char \\*format,...)
fscanf按照指定格式从文件中出读出数据,并赋值到参数列表中.
int fprintf(FILE \\*fp, char \\*format,...)
fprintf将格式化数据写入流式文件中.
#include<stdio.h>
int main()
{
//定义3个字符变量并初始化
char a=\'B\',b=\'0\', c=\'Y\';
//向显示器输出字符B
putchar(a);
putchar(b);
putchar(c);
putchar(\'\\n\');
//向显示器输出字符O
//向显示器输出字符Y
//向显示器输出一个换行符
return 0;
}
#include <stdio.h>
int main()
{
char a,b,c; //定义字符变量a,b,c
a=getchar(); //从键盘输入一个字符,送给字符变量a
b=getchar(); //从键盘输入一个字符,送给字符变量b
c=getchar(); //从键盘输入一个字符,送给字符变量c
putchar(a); //将变量a的值输出
putchar(b); //将变量b的值输出
putchar(c); //将变量c的值输出
putchar(\'\\n\'); //换行
return 0;
}
ASCII码
ASCII ((American Standard Code for Information Interchange): 美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最通用的信息交换标准,并等同于国际标准ISO/IEC 646。ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符。
ASCII 码使用指定的7 位或8 位二进制数组合来表示128 或256 种可能的字符。标准ASCII 码也叫基础ASCII码,使用7 位二进制数(剩下的1位二进制为0)来表示所有的大写和小写字母,数字0 到9、标点符号,以及在美式英语中使用的特殊控制字符 。其中:
0~31及127(共33个)是控制字符或通信专用字符(其余为可显示字符),如控制符:LF(换行)、CR(回车)、FF(换页)、DEL(删除)、BS(退格)、BEL(响铃)等;
通信专用字符:SOH(文头)、EOT(文尾)、ACK(确认)等;
ASCII值为8、9、10 和13 分别转换为退格、制表、换行和回车字符。它们并没有特定的图形显示,但会依不同的应用程序,而对文本显示有不同的影响。
32~126(共95个)是字符(32是空格),其中48~57为0到9十个阿拉伯数字。
65~90为26个大写英文字母,97~122号为26个小写英文字母,其余为一些标点符号、运算符号等。
同时还要注意,在标准ASCII中,其最高位(b7)用作奇偶校验位。所谓奇偶校验,是指在代码传送过程中用来检验是否出现错误的一种方法,一般分奇校验和偶校验两种。奇校验规定:正确的代码一个字节中1的个数必须是奇数,若非奇数,则在最高位b7添0;偶校验规定:正确的代码一个字节中1的个数必须是偶数,若非偶数,则在最高位b7添1。
后128个称为扩展ASCII码。许多基于x86的系统都支持使用扩展(或“高”)ASCII。扩展ASCII 码允许将每个字符的第8 位用于确定附加的128 个特殊符号字符、外来语字母和图形符号。
#include<stdio.h>
int main(void)
{
char ch = \'A\';
printf("%d\\n",ch);
return 0;
}
65
不同数据类型之间的赋值问题
- 各类数值型数据间混合运算时的类型转换规则
整型、实型、字符型数据间可以混合运算。在这种情况下,需要将不一致的数据类型转
换成一致的数据类型,然后进行运算。为了保证运算精度,系统在运算时的转换规则是将存储长度较短的运算对象转换成存储长度较长的类型,然后再进行处理。
如float型数据必先转换为double型数据,然后与其他操作数进行运算。与此类似,char型或short型数据必先转换为int型数据,然后进行运算。
如int型数据与unsigned型数据进行运算,int型转换为unsigned型后方可进行运算。int型数据与double型数据进行运算,int型直接转换为double型后进行运算,不能理解为先转换为unsigned int型,然后转换为long int型,最后再转换为double型。
赋值时的类型转换
当赋值运算符两侧的类型不同时,需进行类型转换,这种转换也是系统自动进行的。具体转换原则如下:
1)float、double型赋值给int型:直接截断小数。
例如:int i=f+0.6; f的值4.0,右边算术表达式运算后的结果为一个值为4.6的double型数据,根据上述转换原则,直接舍弃小数,所以i的值为4。
2)int、char型赋值给float、double型:补足有效位以进行数据类型转换。
例如:float f=4; float为7位有效数字,所以f的值为4.000000。
3)char型(1字节)赋值给int型(2字节):数值赋给int的低8位,高8位补0。
4)long int型赋值给int型:long int截断低字节给int型。
5)int 型赋值给long int:赋给long int的低16位,如果int的最高位是0,则long int的高16位全为0;如果int的最高位是1,则long int的高8位全为1(称为“符号扩展”)。
6)unsigned int型赋值给int型:直接传送数值。
7)非unsigned数据型赋值给位数相同的unsigned 数据:直接传送数值
强制类型转换
除了以上的两种自动类型转换外,在C语言中,允许强制类型转换,将某一数据的数据类型转换为指定的另一种数据类型。强制转换是用强制转换运算符进行的,强制转换运算符为:(类型名),强制转换运算符组成的运算表达式的一般形式为:
(类型名)(表达式)
例如:
(int)(x + y) //将x+y的值转换成整型,即取整数部分。
(float)x + y //将x转换成单精度型。
强制转换运算符优先级比算术运算符高。同表达式中数据类型的自动转换一样,强制类型转换也是临时转换,对原运算对象的类型没有影响。
例如,已知有变量定义:int b=7;float a=2.5,c=4.7;求下面算术表达式的值。
a+(int)(b/3(int)(a+c)/2.0)%4;
根据运算符结合性规则,上述表达式要自左之右执行,b/3为2,2int(a+c)为14,14/2.0为7.0,强制类型转换后为7,7%4为3;a的值2.5与3相加,最终结果为5.5。**
#include<stdio.h>
int main()
{
float a,b,c,t;
scanf("%f,%f,%f",&a,&b,&c);
if(a>b)
{
t=a;
a=b;
b=t;
}
if(a>c)
{
t=a;
a=c;
c=t;
}
if(b>c)
{
t=b;
b=c;
c=t;
}
printf("%5.2f,%5.2f,%5.2f\\n",a,b,c); //顺序输出a,b,c的值
return 0;
}
#include <stdio.h>
int power(int n) // 编写计算16的n次方的函数
{
int i;
int s=1;
for(i=1;i<=n;i++)
{
s=s*16;
}
return s;
}
void main()
{
int m;//定义变量m存放16进制数
int n;//定义变量n存放10进制数
int i;//定义变量i记录指数
int r;//定义变量r记录16进制数的某位的数
printf("please enter a hexadecimal number 16:"); //请输入一个16进制数:
scanf("%d",&m);//用m接受用户输入的16进制数
n=0;
i=0;
while(m)
{
r=m%10;
n=n+r*power(i);
m=m/10;
i++;
}
printf("16 hexadecimal number%d correspinding to 10 hexadecimal numbe is :%d\\n",m,n); //16进制数%d对应的10进制数是
}
#include<stdio.h>
int main()
{
int i=1,sum=0; //定义变量i的初始值为1,sum的初始值为0
while(i<=100) //当i>100,条件表达式i<=100的值为假,不执行循环体
{ //循环体开始
sum=sum+i; //第一次累加后,sum的值为1
i++; //加完后,i的值加1,为下次累加做准备
} //循环体结束
printf("sum=%d\\n",sum);//输出1+2+3+...+100的累加和
return 0;
}
while
C语言循环控制语句提供了 while语句、do-while语句和for语句来实现循环结构。
while循环语句
一般形式如下:
while(表达式)
语句
do-while语句
一般形式如下:
do语句while(表达式);
do-while循环是先执行语句,然后对表达式求值。若值为真,则再次执行语句,如此反复执行,否则将结束循环。语句可以是简单语句,也可以是复合语句。
for语句
for语句是循环控制结构中使用最广泛的一种循环控制语句,特别适合已知循环次数的情况。
一般形式如下:
for ( [表达式 1]; [表达式 2 ]; [表达式3] )语句
其中:
表达式1:一般为赋值表达式,给控制变量赋初值;
表达式2:关系表达式或逻辑表达式,循环控制条件;
表达式3:一般为赋值表达式,给控制变量增量或减量;
语句:循环体,当有多条语句时,必须使用复合语句。
其执行过程如下:首先计算表达式1,然后计算表达式 2。若表达式2为真,则执行循环体;否则,退出 for循环,执行for循环后的语句。如果执行了循环体,则循环体每执行一次,都计算表达式3,然后重新计算表达式2,依此循环,直至表达式 2的值为假,退出循环。
for语句的三个表达式都是可以省略的,但分号“;”绝对不能省略。for语句有以下几种格式:
(1)for(;以上是关于[C语言]学习之路的主要内容,如果未能解决你的问题,请参考以下文章
我的C语言学习进阶之旅解决 Visual Studio 2019 报错:错误 C4996 ‘fscanf‘: This function or variable may be unsafe.(代码片段
我的C语言学习进阶之旅解决 Visual Studio 2019 报错:错误 C4996 ‘fscanf‘: This function or variable may be unsafe.(代码片段
[原创]java WEB学习笔记61:Struts2学习之路--通用标签 property,uri,param,set,push,if-else,itertor,sort,date,a标签等(代码片段