C语言简介
Q:您好,能大体介绍下C语言吗?
A:当然可以。C语言是一种计算机语言,它主要被用在系统编程里,可以说,C语言的产生就和操作系统的编写密不可分。
【C语言简要历史】
1978年由美国电话电报公司(AT&T)的贝尔实验室正式发表了C语言。同时由B.W.Kernighan和D.M.Ritchie合著了著名的“THE C PROGRAMMING LANGUAGE”一书。通常简称为《K&R》,也有人称之为《K&R》标准。但是,在《K&R》中并没有定义一个完整的标准C 语言,后来由美国国家标准协会(American National Standards Institute)在此基础上制定了一个C 语言标准,于1983年发表。通常称之为ANSI C。
【什么是系统编程】
系统编程就是在系统级别进行程序设计。什么是系统级别?这里的系统可以把它理解成把计算机软件分为两类(系统软件和应用软件)中的系统软件,它是应用软件得以正常执行的依托。
Q:学习它有什么作用吗?
A:刚刚也说了,C语言是系统级程序设计语言,您可以用它编写操作系统和Shell,做你自己的编译器;当然,它也可以用于应用程序的设计。
【什么是操作系统】
操作系统,简单地说,就是一些程序的集合,它提供了一个基本环境,可以让您编写的应用程序得以方便地执行。比如说,你的程序中有个printf函数要打印一句话,这个时候就会进行系统调用,而操作系统就会在这个时候处理里面的细节;可以说,它方便了程序员。
【什么是Shell】
Shell,英文翻译为壳的意思,在操作系统中,它一般被称作外壳。它和内核组成了操作系统。
它有什么用呢?它提供了一个接口,供用户和操作系统的内核程序进行交互。举个例子,Windows下的命令提示符cmd.exe就是Shell,比如您在C盘位置输入了 dir ,就可以看到C盘包含的文件夹和文件。
那么,什么又是内核呢?
它是操作系统中最基本的部分,它存在的必要性在于它屏蔽了硬件的复杂性,为应用程序提供了一个统一的接口,方便了程序设计。其实,上面所说的外壳中的各种命令就是在通过内核来完成的。
【什么是编译器】
编译器,从它的名字看,就知道它的作用是编译。编译是做什么的?从源代码的角度说,它是对源代码进行分析,得到计算机硬件能理解的二进制代码的。为什么要得到这样的二进制代码?原因很简单,计算机硬件看不懂您的源代码,它只能明白0和1组成的指令,想要你的程序能执行,当然需要这个转化过程了。
Q:能举个C语言很实际的一个应用?
A:可以啊。当年的Unix系统开始是用汇编写的,但是后来发现很多场合需要移植,而汇编的可移植性很差,于是就用可移植性较好的C语言改写了。
【Unix系统是什么】
它是历史较悠久的操作系统,在1969年,由贝尔实验室的Ken Thompson、Dennis Ritchie等人开发出来。之后,此操作系统越来越成熟,在服务器市场占据较大比例。当然如今,Linux操作系统在服务器市场有更响亮的声音,不过它和Unix是兼容的,它的思想源于Unix.
【什么是Linux操作系统】
Linux的出现,最早开始于一位名叫Linus Torvalds的计算机业余爱好者,当时他是芬兰赫尔辛基大学的学生。他的目的是想设计一个代替Minix(这个操作系统是当时一个操作系统示教系统,Linux对此操作系统的功能不满,所以才想要设计新的)的操作系统,它和Unix的一大区别就是Linux的内核源代码是开放免费的,任何人还可以根据需要对源代码进行修改。
【什么是汇编语言】
汇编,英文为 "assemble",意为组装、装配。可以把它看做是机器语言的另外一种形式。当然,它使用了大量的助记符,这个也使得程序员摆脱了机器语言那样的01代码,使得程序设计变得相应更简单点。当然,它不能让硬件直接执行,得通过一个叫汇编器的工具把汇编代码转化成机器代码这样才可以。在程序设计早期,汇编很流行,尤其是高级语言没有出现前。而在高级语言出现之后(如C出现之后),汇编的地位变得弱了,因为毕竟汇编还是和硬件有较大关系,这不方便程序员的程序设计。但是,在一些对速度要求极高的场合(如操作系统中与硬件打交道中的某些地方),汇编还是有可以发辉的场地。
【什么是机器语言】
机器语言,顾名思义,就是机器能看明白的语言。它就是0和1的序列,可以让硬件直接执行;当然,它有自己的规则。在程序语言最开始,就是用的这种语言,然而,可想而知,如果程序员每天都在和0和1打交道,这会是多么乏味和棘手的事情。也正是这个原因,之后的汇编语言诞生了。
Q:C++和C有什么区别和联系吗?
A:C是C++的子集,C++是扩展了的C。它增加了比如面向对象思想中的类的概念等。C写的代码一般可以当作C++代码去编译,当然反过来就不一定成立了。
【C++简要介绍】
C++是美国的贝尔实验室的Bjarne Stroustrup博士在20世纪80年代初期发明并实现的,最开始C++是被称作"带类的C",以后才被正式称作C++的。
Q:还有很多种程序设计语言,比如Java,C#等等,它们和C语言的区别是什么?
A:程序设计语言一般来说都有共同的特征,这个就像汉语和英语同为人类交流的语言,都有主语、谓语、宾语一样;当然,程序设计语言又各有不同:因为就在于它们是被设计用作不同用途而导致有所区别。
举个很简单的例子,你和你的同事工作于一个机密场合,你们为了防止你们的对话被别人截取,你们两个设计了一套语言规则:
说 BB ,就等于告诉对方 再见(ByeBye) ;
说 HL ,就等于告诉对方 您好 (Hello) ;
说 SP ,就等于告诉对方 停止 (Stop) ;
或者说,在你们的范围内,这些是成立的;当然对于别人看来,可能一点都不明白了。程序设计语言也是,C#语言中有个foreach关键字,而这在C语言中就是不可理解的。
另外,Java最注重网络的应用和跨平台特性,c#和Java类似,它们都为了使得程序能在不同平台更方便地移植而设计的。
【Java简要介绍及与C的一些不同】
Java语言最初并不是为了能使得程序可以在不同平台方便移植而设计的,只是后来发现它可以在这方面有所作为,Sun公司才把Java向这方向推动的。它为什么可以在不同平台很方便地移植?原因在于它有一个虚拟机,它负责在不同计算机硬件平台之间进行中间转换,使得Java程序可以在不同平台可以不加修改地执行。而正因为如此,Java的程序首先被编译成了中间状态的代码,也被称作字节码,即.class格式文件,这种文件可以被Java的虚拟机执行,它根据不同平台,然后再把真正要执行的指令传给计算机的硬件去执行。这和C语言的程序不同,C语言程序是被编译成机器码而被执行的,这当然有硬件相关性,也是造成C语言不能像Java那样非常方便地移植。可是,之前说过C语言比汇编的优点就在于它的可移植性,在这里怎么又说它的移植性不太好了?其实,说到底,问题就在于,想要可以在Windows环境下运行的C语言的程序也能在Linux下环境,就必须把它的源代码在Linux平台上的C编译器上再进行编译(当然这里排除一些Windows和Linux下极不兼容的地方),这样基本就可以执行了。然而也正是这个原因,它在这个方面没有Java有优势。
【C#简要介绍】
C#语言是微软公司推出的和Java语言竞争的一门新语言,它和Java酷似。它综合了VB的高生产率和Java的跨平台性,为了实现在.NET环境下代码的可移植性。当然,如今Java依然占据着跨平台的领头羊的位置,C#将会扮演什么角色,我们拭目以待。
Hello World!程序
Q:举个“Hello World!”的例子吧。
A:
#include<stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
运行结果如下(是用VC6.0编译的,后面的代码如果没有特别说明,均是用此编译器编译的):
Q:好像我能看明白有个printf似乎是打印的意思;然后后面有要打印的"Hello World!"的字符。为什么它的两边要有花括号括起来呢?VB中的print没有这个括号,这里是什么语法规定吗?
A:是的,这是语法规定。这里的printf是个函数名,它后面是要加参数的,而参数就放在括号内。您现在就把括号理解成函数的必要组成部分好了。
Q:函数?和我在初中、高中学的函数是一个意思吗?
A:呵呵。在意义上很相似,在实际上也基本上一个意思。
Q:那我只是想打印一条语句,为什么要用到函数呢?这又不像我想求平方根一样,用一个函数
来表示。
A:问的好。应该说,C语言为了统一模式吧,把任何一个过程都得看成是函数模式,所以在这里的打印也得用上个函数。但是,不要小看这个打印过程,在硬件上可是要进行很多操作的,如果这么想来,把它当作个函数也不为过。
Q:那它的函数名是什么?是 " int main()" 吗?
A:你想呢?
Q:我想应该是这样。但是要是我想,用一个单词就应该表示了。
正如以前学的y=f(x)函数一样,函数名就一个字母f,够简洁的了。
A: 说的好。其实这里的函数名就是main,后面的 return 0;就是配合这里的int的。int代表了main函数的返回值类型。数学中学的y=f(x)函数不会对返回值做太多的限制,而在计算机中这个问题就是重要问题了,因为返回值类型决定了用多少个字节来保存这个数据等等作用。
Q: 哦。那int是什么?
A: 它代表整型。
Q: 就是数学中的整型数吗?
A: 应该说,只是数学中整数的子集,而且是整数集合中很小的一部分。
Q: 啊?为什么这么说呢?计算机不是可以为我们计算很多事情的吗?怎么它还表示不了所有的整数?
A:是的,它表示不了所有的整数。其实这个问题你得从以前的思维中转变过来:以前我们要表达一个很大的数,比如100亿,你可以写10000000000,但是如果遇到您的纸张大小不够,您也写不了。计算机的各种计算是在CPU中计算的,而要为被操作的数留个位置,这些位置被称作寄存器,但是寄存器的存储容量是有限的,这也决定了光用计算机的硬件可以表达的数是有限的。
当然,我们可以通过软件的方式来扩展数,达到我们想要的大小和范围。
Q: 好像我明白了一些。那么有int类型的返回值,也有别的类型吧?
A: 对。还有比如float,double之类的浮点类型。不过基本类型不多,很快你就会接触了。
Q: int是integer的缩写吧?
A: 是的。还比如有一种叫字符型的,被写作char,它就是character的简写。在程序设计语言里,简写是个很常见的事情了,毕竟简便多了。不同语言的简写方式也可能有所不同,就像Basic语言中的整型被简写成Integer.
Q: 哦。那么main之后的括号的作用是什么? 哦!对了!它和y=f(x)的括号的意义是一样的吧?
A: 是的。
Q:可是它里面怎么什么也没有啊?数学中的函数可一般都有参数的!
A:呵呵……那你想在里面放什么呢?
Q:让我想想……
我在想,如果只是打印这句"Hello World!"这句话,那么不如把"Hello World!"放进main后面的括号中,就当作是默认在后面就直接打印它就结束,不用再在后面写那个printf的打印语句了,这样不行吗?
A:嗯!好想法!不过C语言的设计者不是你这么想的。他们只把这个main函数后面的参数限定为两种参数模式:
一种是无参,也就是这里的什么都没有;
另外一种是类似如下的形式:int argc,char *argv[]
.
Q:那这后面一种是什么意思?好古怪啊!
A:是啊。挺古怪,不过这是有道理的。应该说,在C语言诞生那个年代,人们用的操作系统是命令行式的系统,也就是输入一段数据,然后得到我们要的结果;不像我们现在用的更多的是GUI界面。命令行,您可以在MS-DOS中的CMD里获得体验。
输入dir,回车,然后就会显示出您所在目录下的文件及文件夹。
输入dir /s,回车,然后就会显示出您所在目录下的文件和子文件的文件。
dir 和 dir /s的区别是什么?
一个字符多,一个字符少。而在程序语言中,这就被称作参数个数的不同,也就是argc的值;
显然,第一个的argc等于1,第二个等于2.
后面的char *argv[]就是指参数的值:第一个指dir,而第二个指dir和/s .
不过这个现在说了有点早了,以后您会体会地更深刻的。
Q:那么main()后面的 { 和最后的 } 也被看做是函数的一部分了?不能不要它们吗?
#include<stdio.h>
int main()
printf("Hello World!");
return 0;
把这个作为一个文件,我想计算机也可以看得明白写的是什么意思呀。
A:需要加两个花括号当然有它的原因了,至少能使程序更美观,可以让一个程序员较为清楚地知道这个函数的范围。当然,程序代码中并不一定只有一个函数,当有别的函数时,如果没有可以表明函数结束的标记,那么怎么知道一个函数已经结束了?
Q:那么最上面的#include<stdio.h>是做什么的?
A:您看到printf()这个形式的东西了吗?它是什么?
Q:它是个函数。
A:它从何而来?
Q:我不知道。
A:那就对了。它正是#include后面的stdio.h文件包含的。有了这个语句,后面就可以直接使用print函数了。
Q:前面给的是C的基本输出程序,能给个C++的基本输出程序吗?
A:如下代码:
#include <iostream>
using namespace std;
int main()
{
cout<<"Hello "<<endl;
return 0;
}
执行结果是:
Q:C中是用函数输出的,这里没有括号,这里不是用函数输出的吗?
A:呵呵,其实这里也用函数了,就是 << ,它是运算符重载的效果,以后会具体介绍的。
Q:在C++中,只要把要输出的放到cout<<后面的双引号中,就可以按双引号中的样子输出了是吧?
A:是的,这和C中把它们放到printf后输出列表的双引号中是一个道理。
Q:cout是什么意思?
A:你得把它分开看:开始是c,代表了C++语言;后面是out,代表是"输出"的意思。
Q:#include <iostream>这也是个头文件包含吧,这个头文件怎么没.h的标示了呢?
A:其实有没有.h并不重要,只要这个文件里面确实有我们所要的一些函数、宏定义等信息就可以了。
如下是此文件所在文件夹里的位置(头文件一般位于Include文件夹下):
Q:那么using namespace std; 是什么意思?
A:这个是表明使用标准命名空间的意思。关于命名空间,以后会有更具体地介绍。
Q:<<endl 代表什么?
A:这个代表输出换行;
【此程序的另外一个形式】
#include <iostream>
int main()
{
std::cout<<"Hello "<<std::endl;
return 0;
}
执行结果是:
执行是一样的;但代码的区别是什么?是第一个程序多了
using namespace std;
而第二个没有这个,但是把函数的前面加了std这个修饰符,当然起到了同样的作用!
而若是没有,那就错了:
#include <iostream>
int main()
{
cout<<"Hello "<<endl;
return 0;
}
编译错误:
错误表明是那个叫cout的系统不认识它,这也就是命名空间应该起到的作用;
【深入编译错误】
看到上面的error C2065这样的东西,表示编译的错误代号是2065,C大概代表是Compile,
在VC的MSDN中,输入C2065就可以查看到关于此种编译错误的具体内容。
如下为示例:
【C++的一个简洁之处】
假设定义了3个整型变量a,b,c:
也许曾几何时你还在为这种表达感到麻烦的时候:
printf("%d /n%d/n%d/n",a,b,c);
【/n的作用】
/n代表换行,即在控制台窗口中另起一行输出。
在C++中用这个就可以了:
cout<<a<<endl<<b<<endl<<c<<endl;
一气呵成,当然写的时候也挺畅快!
当然,printf也有一些简洁的地方:
char c='a';
printf("%d",c)
现在就打印了字符的整型表达方式;
而用cout就得:
char c='a';
cout<<(int)c<<endl;
尤其是在需要改变的格式多的时候,cout就显得力不从心了,而printf函数只需要简单地改下那个%后面的字符就可以方便用不同格式显示出来!
【关于以后程序的基本输出】
鉴于C++的cout在表达输出方面有较多的简洁性,以后的程序代码如果没有特别说明,都以cout来输出。
【深入一段代码的汇编形式】
代码如下:
#include<stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
代码的文件名是: hello.c
在这里,我们使用VC6.0编译器,得到此代码的汇编形式
(使用的编译命令是:cl /Fahello.asm hello.c):
TITLE hello.c
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC _main
EXTRN _printf:NEAR
_DATA SEGMENT
$SG336 DB 'Hello World!', 00H
_DATA ENDS
_TEXT SEGMENT
_main PROC NEAR
; File hello.c
; Line 3
push ebp
mov ebp, esp
; Line 4
push OFFSET FLAT:$SG336
call _printf
add esp, 4
; Line 5
xor eax, eax
; Line 6
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
我们看到了例如Line 3之类的文字,它们正是源代码的位置,其下的汇编即是源代码所在位置被编译过程中生成的汇编形式代码。关于汇编形式的代码,以后将深入探讨。
【得到汇编代码的机器码格式】
正如上的代码,在VC6.0编译器下查看反汇编(在调试状态,单击“查看”菜单,再单击“调试窗口”菜单,再进入“Disassembly”子菜单):
最左侧的以0040开头的代表的是虚拟地址;
后面有一些十六进制的格式的数即是机器码的格式;
再后面就是汇编格式的代码,和刚刚的机器码对应;
对于机器码,并不是本书会详细解释的内容。
简单的加法程序
Q:哦!明白了。现在我想知道怎么编写一个计算加法的程序。
A:如果现在让你自己设计计算加法的步骤,你会怎么设计?
Q:我会设定两个量,一个叫x,一个叫y,它们分别代表着给定的值1和2,然后把这两个量加起来得到我要的和。
A:您的意思就是类似如下伪代码:
x=1
y=2
print x+y
是吗?
Q:是的!
A:嗯!想得很好。C中的代码如下:
#include<stdio.h>
int main()
{
int a=1;
int b=2;
int c;
c=a+b;
printf("%d",c);
return 0;
}
执行为:
但是它只能限定是计算两个整数的和,而且两个数的值已经在代码中给定了,别的类型和别的值是不可以计算的。
Q:我有个问题:我看在花括号里的每一行最后都有个分号 ; ,它就是为了标明一句话的结束吗?
A:嗯!是的。前面我们说C语言的基本组成部分是函数,而这些以分号结尾的一句话就是函数的基本组成部分,也可以说是C程序就是由语句组成的了。
Q:哦!是这样呀。我看VB中一条语句都不带分号结束的,它们之间有什么本质的区别吗?
A:这个其实没什么太本质的区别,只是不同语言的语法规定不一样了;VB中可以用回车代表一条语句结束,C中以分号表明。
Q:那也就是说,下面也是可以的了?
int a=1; int b=2; int c;
A:是的!
Q:我看刚刚的那句话好麻烦:既然都是整型,用一个int标明不就可以了?
A:嗯。您说的对,C中可以在一条语句中声明或定义好几个变量。如果我不说C中怎么设计的,您能想出一个方式来表达你的想法吗?
Q:让我想想……
int a=1 b=2 c; 这样行吗?
A:呵呵。好像也行。不过感觉有点不舒服,中间的空格让我有很悬乎的感觉。而他们是怎么设计的呢?
如下:
int a=1,b=2,c;
他们只是在你想到基础上加了几个逗号隔开不同的变量,应该看起来更清楚。
Q:哦!那么它们的声明顺序对程序有影响吗?
A:应该说,在这个程序里没影响。不过要是更复杂的了,就可能要考虑变量声明顺序的影响了。
Q:那么c=a+b; 的意思就是c等于a和b的和吧?
A:可以这么想。不过这个 "="和我们平常数学中用的等于号还是有区别的。这里的符号叫"赋值操作符",这条语句的意思是把a和b的和赋值给c.其实说到底,还是等于的意思,这个以后会具体讲解的。
Q:我看
int c;
c=a+b;
分开写挺浪费行数的,可以合在一起写吧?
A:可以!您觉得应该怎么合?
Q:和前面说的声明类似: int c=a+b; 这样可以吗?
A:可以。我想学到这里你应该有一些感触了吧:
C语言,是一种计算机语言,不过得能让计算机先看得懂,计算机才能知道如何去做代码想要做的事情。正如上面:
把c=a+b; 这种格式理解成把a和b的和放置到c中,不仅程序员或是别的人可以较容易明白,计算机也能较容易理解,当然这里所说的计算机指的是编译器了。应该说,这就是好的程序设计语言的标志之一。
Q:编译器?能介绍下编译器吗?
A:编译器就是编译这些源代码的工具。比如有Microsoft Visual C++编译器,还有gcc编译器,还有Turbo C编译器。它们的作用都是去分析源代码,得出源代码的意思,然后用类似机器代码或者就是机器代码描述源代码的意思,然后交给计算机去处理。可以说,它们是源代码和机器的接口,也可以看成是程序员和机器的接口,没有它们您的代码也就失去了可以执行的意义了,所以它们是很重要的哦。
Q:那能举个具体的例子说明下编译器是如何工作的吗?
A:可以。比如就刚刚这个程序:
#include<stdio.h>
int main()
{
int a=1;
int b=2;
int c;
c=a+b;
printf("%d",c);
return 0;
}
首先,编译器看到了第一句话 #include<stdio.h>,当然它就把这句话当作是一个包含文件的意思,当然它的内部还很复杂;
接着,看到了int 这个单词,它把它理解成整型,当然它的后面可以跟上我们说过的函数名,表示返回值为整型的函数,也可以说我们说的变量名,表示声明或是定义变量了。到后面,它看到了main,当然它也就把这个当作是函数声明了;再接着,编译器发现了 { 符号,那么也就把函数声明增强为函数定义了。
再朝下,就到了一些变量的声明,以及简单地计算了,编译器可以很轻松地把这些都转换成汇编代码、机器代码,在后面可以让计算机顺利而准确地执行。
当然,上面所说的只是一种简单地理解方式,实际上编译器的工作并不是这样的,它是先大致浏览所有代码,得出代码中基本结构,然后才进一步细致地分析的。
编译是一门学问,编译原理是一门单独地课程,还是很有研究价值的。
Q:printf("%d",c); 中的c应该就是要被打印的那个和的值,那么前面的那个双引号里面还有个%d代表什么?
A:它代表是打印的是整型值,它正对应着后面的变量c.
d是decimal(十进制)的简写,% 号是为了与 d在一起表面后面要有个整型值代表它的内容。
双引号的意思是要把双引号中的内容按原文输出,当然遇到上面说的%d之类的符号就要特殊对待了。
Q:哇!好麻烦!既然前面都声明c是int类型的了,为什么这里还要有个%d代表它是整型的呢?
A:那您认为怎么写就可以了呢?
Q:printf(c); 这样就可以呀?
A:够简洁!不过实际上C语言这么设计是为了能表达更多的数据类型。
我们知道,数据的类型不是只有int这一种,还可以有float类型等等,那么想用别的类型格式打印您的变量值,就只需要改动双引号中的格式了。如下:
printf("%c",c); 这个就代表用字符类型打印c的值。实际的运行效果是:
Q:还有个问题。就是printf("%d",c); 中的c能直接用a+b替换吗?这样不更简洁吗?
A:是的。你说的是可以的。当然前面声明的变量c也就可以省略了。
#include<stdio.h>
int main()
{
int a=1;
int b=2;
printf("%d",a+b);
return 0;
}
Q:能给个关于输入的程序吗?
A:
#include <stdio.h>
int main()
{
int a;
scanf("%d",&a);
printf("%d",a);
return 0;
}
Q:scanf函数就是输入函数,那么也就可以计算两个数输入的数的和了吧?
A:当然可以。如下:
#include<stdio.h>
int main()
{
int a,b,c;
scanf("%d%d",&a,&b);
c=a+b;
printf("%d",c);
return 0;
}
输入: 1 2 (回车)
结果: 3
Q:这个scanf就是输入函数吧?
A:是的。后面的两个%d就分别代表要输入的两个整型数。
Q:那a和b前面为什么要加 & 号呢?
A:这应该是最容易犯错误的地方了,现在就要记住它:scanf函数后面输入变量参数一定得是变量的地址格式,关于为什么,将在以后介绍。 & 是取地址运算符,关于此运算符,以后会具体介绍。
Q:哦。那这里的scanf函数也可以分开写吧,就是写成:
scanf("%d",&a);
scanf("%d",&b);
这样也可以吧?
A:当然。
Q:可是如果用您刚刚写的程序,为什么输入了 1,2 (回车),而之后会得不到正确的结果呢?
A:呵呵。这是因为scanf函数要求输入一定要按照双引号里面的方式来输入,不能随便改动,否则计算机可看不明白你的输入。
Q:哦。
A:你可以输入
1 2 (回车)
或
1 (回车)
2 (回车)
都可以,当scanf函数中两个要输入的数的格式间什么也没有的时候,就默认采用空格或回车当作分隔符(当然用TAB键也可以)。
但是如果程序改为:scanf("%d,%d",&a,&b);
看到没?输入的数间加了个逗号,那么您输入的时候也要加这个逗号!不加就得不到您要的结果了。
如下为输入的时候没有加逗号得到的结果(得到了错误的结果):
如下为输入的时候加了逗号得到的结果(得到了正确的结果):
Q:有个问题:为什么用这个程序在TC中输入了10000和30000,会得到一个错误的值;而在VC6.0中就得到了正确的值呢?
TC下的执行:
VC下的执行:
A:这就是发生溢出了。如果您的机器是16位的,也就是CPU中数据寄存器是16位的,那么int默认是16位的,它的取值范围为-32768~32767.如果超过这个范围的,都可能得到一个错误的结果。而,如果是32位的,这个程序的执行结果就不会错,因为int的范围在大约正负21亿。
Q:也就是计算机不能保证计算的加法得到的一定就是对的了? 没有可以检测是否发生溢出的吗?
A:目前看来,计算机在计算发生溢出的时候并不提示,除了一个除数为0的情况;别的情况只能程序员自己写检测程序来判断是否发生溢出了。
Q:那么在执行这个程序的时候,为什么一定就出现个小黑框框,你的是个白框框,然后可以在里面输入数据?有别的形式的输入环境吗?
A:你如果用的是Windows,那么在执行这个程序的时候一定是出现这个了,因为这个叫命令提示符的程序就是这种程序默认执行的环境。
Q:能说的更具体吗?
A:就是在Windows下写的EXE程序,大体可以被分成两类:
一类是Console应用程序,也就是控制台应用程序,就像我们前面写的程序一样;它们默认就是控制台应用程序,它们的执行环境就是cmd.exe.
另一类就叫Application,是有窗体等GUI图形的,比如Windows自带的计算器calc..exe这样的程序。
Q:能给个C++的加法程序吗?
A:如下:
#include <iostream>
using namespace std;
int main()
{
int a=1;
int b=2;
int c;
c=a+b;
cout<<c;
return 0;
}
Q:cout<<后面直接跟上变量c就可以输出c的值了?
A:是的。它不像printf函数那样让人觉得有点麻烦。
【深入cout<<】
这里的cout其实是个输出流对象,<< 是一个运算符,在这里被重载了,这些在以后将会有介绍。
Q:我看cout的这个样子,如果要打印别的变量,也可以直接跟在后面了?
A:是的。比如,你还要打印c+1的值,那么你就:
cout<<c<<c+1;
Q:C++中的换行用什么?
A:除了可以用C中的'/n'之外,还可以在 cout<< 流对象输出中直接用endl函数。
如果把上面程序中cout<<c; 这句话改为:
cout<<c<<endl<<c;
那么执行结果如下:
Q:那么给个有输入存在的程序吧。
A:
#include <iostream>
using namespace std;
int main()
{
int a;
cin>>a;
cout<<a;
return 0;
}
Q:cin>> 就是输入函数?
A:是的。在它后面直接跟上要输入的变量名就可以了。
Q:这比scanf函数要简洁多了,scanf还要个取地址符号呢。
A:嗯,是的。C++在输入输出方面的简化做的不错。
Q:那么也就可以再来写个输入两个数并求它们和的程序了。
A:对。
#include <iostream>
using namespace std;
int main()
{
int a,b,c;
cin>>a;
cin>>b;
c=a+b;
cout<<c;
return 0;
}
Q:cin>>a;
cin>>b;
可以和到一起写吧?
A:是的。可以用 cin>>a>>b; 这样更方便。