[C语言]学习之路
阅读原文时间:2023年07月08日阅读:2

实例: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,2_int(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(; 语句;

  (2)for(;表达式2;表达式3 ) 语句;

  (3)for(表达式1;表达式2;) 语句;

  (4)for(i=1,j = n; i < j; i ++,j - - ) 语句;

  三种语句比较

  同一个问题,往往既可以用 while语句解决,也可以用 do-while或者for语句来解决,但在实际应用中,应根据具体情况来选用不同的循环语句。选用的一般原则是:

  (1) 如果循环次数在执行循环体之前就已确定,一般用 for语句。如果循环次数是由循环体的执行情况确定的,一般用 while语句或者do- while语句。

  (2) 当循环体至少执行一次时,用 do-while语句,反之,如果循环体可能一次也不执行,则选用while语句。

  C++/C循环语句中,for语句使用频率最高,while语句其次,do语句很少用。

  三种循环语句for、while、do-while可以互相嵌套自由组合。但要注意的是,各循环必须完整,相互之间绝不允许交叉。

  其他循环语句

  多重循环结构

  在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨越循环层的次数。

  一个循环体内又包含另一个完整的循环结构

  三种循环可互相嵌套,层数不限

  外层循环可包含两个以上内循环,但不能相互交叉

 c语言32个关键字
   auto :声明自动变量 一般不使用
  double :声明双精度变量或函数
  int: 声明整型变量或函数
  struct:声明结构体变量或函数
  break:跳出当前循环
  else :条件语句否定分支(与 if 连用)
  long :声明长整型变量或函数
  switch :用于开关语句
  case:开关语句分支
  enum :声明枚举类型
  register:声明积存器变量
  typedef:用以给数据类型取别名(当然还有其他作用)
  char :声明字符型变量或函数
  extern:声明变量是在其他文件正声明(也可以看做是引用变量)
  return :子程序返回语句(可以带参数,也看不带参数)
  union:声明联合数据类型
  const :声明只读变量
  float:声明浮点型变量或函数
  short :声明短整型变量或函数
  unsigned:声明无符号类型变量或函数
  continue:结束当前循环,开始下一轮循环
  for:一种循环语句(可意会不可言传)
  signed:生命有符号类型变量或函数
  void :声明函数无返回值或无参数,声明无类型指针(基本上就这三个作用)
  default:开关语句中的“其他”分支
  goto:无条件跳转语句
  sizeof:计算数据类型长度
  volatile:说明变量在程序执行中可被隐含地改变
  do :循环语句的循环体
  while :循环语句的循环条件
  static :声明静态变量

指针

1.定义方法

  形式:

  类型标识符_变量标识符;

  定义存放指定类型数据地址的指针变量。

  类型标识符是定义指针的基类型,给出指针数据对应存储单元所存放的数据的类型,一般用“指向”这个词来说明这种关系,即类型标识符给出指针所指向的数据类型,可以是简单类型,也可以是复杂类型。用“_”表示定义的是指针变量,不是普通变量。变量标识符给出的是指针变量名。

  例如:

  (1)Int _p1,_p2,_p3;

  定义指向整型数据的指针变量p1、p2、p3。

  (2)float _q1,_q2,_q3;

  定义指向实型数据的指针变量q1、q2、q3。

  (3)char_r1,_r2,_r3;

  定义指向字符型数据的指针变量r1、r2、r3。

  (4)struct date

  {int year;

  int month;

  int day;

  }_t1, *t2, *t3;

  定义指向struct date类型数据的指针变量t1、t2、t3。

2.指针变量所指向的变量特定类型的数据

  定义的指针变量用于存放指向类型数据的地址,我们可以通过指针运算“_”,引用指针变量所指向的数据。有关内容我们在指针运算中加以介绍。

  例如,对指针变量p1、p2、p3,假定已有值,*p1、_p2、*p3代表指针变量p1、p2、p3所指向的数据,也就是p1、p2、p3的值对应的存储单元里存放的数据,称为指针变量所指向的变量,简称指针指向变量。

  指针类型也是一种复杂类型,指针指向变量可以认为是指针数据的分量。指针指向变量相当于基类型变量。

  如果指针变量p1、p2、p3分别存放整型变量i、j、k的地址,则p1指向i,p2指向j,p3指向k。

#include<stdio.h>
int main()
{
    int a=100,b=10;     //定义整型变量a,b,并初始化
    int * pointer_1,* pointer_2;  //定义指向整型数据的指针变量pointer_1,pointer_2
    pointer_1=&a;   //把变量a的地址赋给指针变量pointer_1
    pointer_2=&b;    //把变量b的地址赋给指针变量pointer_2
    printf("a=%d,b=%d\n",a,b);  //输出变量a和b的值
    printf("* pointer_1=%d,* pointer_2=%d\n",* pointer_1,* pointer_2);  //输出变量a和b的值
    return 0;
}

函数

  一、无参函数的定义形式

   类型标识符 函数名()

    {

    声明部分

    语句

    }

   其中类型标识符和函数名称为函数头。类型标识符指明了本函数的类型,函数的类型实际上是函数返回值的类型。该类型标识符与前面介绍的各种说明符相同。函数名是由用户定义的标识符,函数名后有一个空括号,其中无参数,但括号不可少。

   {}中的内容称为函数体。在函数体中声明部分,是对函数体内部所用到的变量的类型说明。

   在很多情况下都不要求无参函数有返回值,此时函数类型符可以写为void。

   我们可以改写一个函数定义:

    void Hello()

    {

    printf ("Hello,world \n");

    }

   这里,只把main改为Hello作为函数名,其余不变。Hello函数是一个无参函数,当被其它函数调用时,输出Hello world字符串。

   二、有参函数定义的一般形式

   类型标识符 函数名(形式参数表列)

    {

    声明部分

    语句

    }

   有参函数比无参函数多了一个内容,即形式参数表列。在形参表中给出的参数称为形式参数,它们可以是各种类型的变量,各参数之间用逗号间隔。在进行函数调用时,主调函数将赋予这些形式参数实际的值。形参既然是变量,必须在形参表中给出形参的类型说明。

   例如,定义一个函数,用于求两个数中的大数,可写为:

    int max(int a, int b)

    {

    if (a>b) return a;

    else return b;

    }

   第一行说明max函数是一个整型函数,其返回的函数值是一个整数。形参为a,b,均为整型量。a,b的具体值是由主调函数在调用时传送过来的。在{}中的函数体内,除形参外没有使用其它变量,因此只有语句而没有声明部分。在max函数体中的return语句是把a(或b)的值作为函数的值返回给主调函数。有返回值函数中至少应有一个return语句。

   在C程序中,一个函数的定义可以放在任意位置,既可放在主函数main之前,也可放在main之后。

#include<stdio.h>
int main()
{
    void print_star();        //声明print_star 函数
    void print_message();     //声明print_message函数
    print_star();             //调用print_star 函数
    print_message();          //调用print_message函数
    print_star();             //调用print_star 函数
    return 0;
}
void print_star()
{
    printf("*************\n");  //输出一行*号
}
void print_message()         //定义print_message函数
{
    printf("How do you do!\n"); //输出一行文字信息
}

数组

1、数组的概念、定义和使用

  数组(array)是C语言中用于组合同类型数据对象的机制。一个数组里汇集一批对象(数组元素)。程序中既能从数组出发处理其中的个别元素,也能以统一方式处理数组的一批元素或所有元素。后一处理方式特别重要,是由一批成员构成的数组和一批独立命名的变量间的主要区别。数组机制要解决三个问题:)描述数组的性质,定义数组变量; )使用数组,包括通过数组变量使用元素; )实现数组,即在内存里为数组安排一种存储方式,使程序里可以方便地操作它们。当然,最后一个问题主要与语言的实现有关系,在实现C语言系统时,必须确定如何实现数组变量。了解这方面情况也有利于在编程时正确使用数组。

  2、数组变量定义

  根据数组的性质,在定义数组变量(下面简单说成 “定义数组”)需要说明两个问题: )该数组(变量)的元素是什么类型的; )这个数组里包含多少个元素。C语言规定,每个数组变量的大小是固定的,需要在定义时说明。数组定义的形式与简单变量类似,但需要增加有关元素个数的信息。在被定义变量名之后写一对方括号就是一个数组定义,指定元素个数的方式是在括号里写一个整型表达式。人们常把数组元素类型看作数组的类型,把元素类型为整型的数组说成是整型数组,类似地说双精度数组等。

例如,下面的描述定义了两个数组:

  int a[ 0];

  double a [ 00];

  定义了一个包含有 0个元素的整型数组a和一个 00个元素的双精度数组a 。数组元素个数也称为数组的大小或数组的长度。数组定义可以与其他变量的定义写在一起,例如可以写:

  int a [ ], n, a [ ], m;

  数组变量也是变量,数组定义可以出现在任何能定义简单变量的地方。数组变量也是变量,在作用域和存在期方面与简单变量没有差别。根据定义位置不同,数组也分为外部数组和函数内的局部数组,包括函数内的静态数组(用关键字static)和普通的自动数组,定义方式(及位置)决定了它们的作用域与存在期。

  可以写出数组的外部说明。C语言规定,在写数组变量的外部说明时不必写数组大小,只要在数组变量名后写一对方括号。例如下面是两个数组的外部说明:

  extern int a[];

  extern double a [];

  这两个说明通知本源文件的其他部分,有两个数组(a和a )在其他地方定义,它们的元素类型分别是整型和双精度类型。数组元素个数必须能在编译时静态确定,因此这个表达式必须能静态求值,最简单的情况就是写一个整型字面量(整数)。根据这个规定,下面数组定义不合法

  void f(int m, int n) {

  int b[n];

  ….

  }

  此时局部数组b的大小依赖于函数的参数值,这个值在编译时无法确定。

  3、数组的使用

  使用数组的最基本操作是元素访问,对数组的使用最终都通过对元素的使用而实现。数组元素在数组里顺序排列编号,首元素的编号规定为0,其他元素顺序编号。这样,n个元素的数组的元素编号范围是0到n-1 。如果程序里定义了数组:

  int b[ ];

  b的元素将依次编号为0、 、 、 。数组元素的编号也称为元素的下标或指标。

  数组元素访问通过数组名和表示下标的表达式进行,用下标运算符[]描述。下标运算符[]是C语言里优先级最高的运算符之一,它的两个运算对象的书写形式比较特殊:一个运算对象写在方括号前面,应表示一个数组(简单情况是数组名);另一个应该是整型表达式,写在括号里面表示元素下标。元素访问是一种基本表达式,写在表达式里的b[ ]就是一个下标表达式,表示访问数组b中编号为 的元素,即上面定义的数组b的最后元素

#include <stdio.h>
int main()
{
     int a[2][3]={{1,2,3},
                {4,5,6}};
     int b[3][2],i,j;
     printf("array a:\n");
     for(i=0;i<=1;i++)  //处理a数组中的一行中各元素
     {
        for(j=0;j<=2;j++)//处理a数组中的某一列元素
        {
            printf("%5d",a[i][j]); //输出a数组各元素
            b[j][i]=a[i][j];       //将a数组元素的值赋值给b数组相应元素
        }
        printf ("\n");
     }
     printf ("array b:\n");      //输出b数组各元素
     for(int n=0; n<=2; n++)
     {
         for(int m=0;m<=1;m++)
             printf("%5d",b[n][m]);
            printf("\n");
     }
     return 0;

}

#include <stdio.h>
int main()
{
    int i,j,row=0,column=0,max;
    int a[3][4]={{1,2,3,4},{9,8,7,6},{-10,10,-5,2}}; //定义数组并赋初值
     max=a[0][0];
    for(i=0;i<=2;i++)
    {
        for(j=0;j<=3;j++)
            if(a[i][j]>max)
            {
                max=a[i][j];
                row=i;
                column=j;
            }
    }

            printf(" max=%d\n row=%d\n column=%d\n",max,row,column);
     return 0;

}

用户自己建立数据类型

  结构(struct)

   结构是由基本数据类型构成的、并用一个标识符来命名的各种变量的组合。

   结构中可以使用不同的数据类型。

   1.结构说明和结构变量定义

   在Turbo C中,结构也是一种数据类型,可以使用结构变量,因此,象其它类型的变量一样,在使用结构变量时要先对其定义。

   定义结构变量的一般格式为:

   struct 结构名

   {

   类型 变量名;

   类型 变量名;

   …

   } 结构变量;

   结构名是结构的标识符不是变量名。类型为第二节中所讲述的五种数据类型(整型、浮点型、字符型、指针型和无值型)。构成结构的每一个类型变量称为结构成员,它象数组的元素一样,但数组中元素是以下标来访问的,而结构是按变量名字来访问成员的。

   下面举一个例子来说明怎样定义结构变量。

  struct string  {  char name[8];  int age;  char sex[2];  char depart[20];  float wage1, wage2, wage3, wage4, wage5;  } person;

   这个例子定义了一个结构名为string的结构变量person, 如果省略变量person, 则变成对结构的说明。用已说明的结构名也可定义结构变量。这样定义时上例变成:

  struct string  {  char name[8];  int age;  char sex[2];  char depart[20];  float wage1, wage2, wage3, wage4, wage5;  };  struct string person;

   如果需要定义多个具有相同形式的结构变量时用这种方法比较方便, 它先作结构说明, 再用结构名来定义变量。

   例如:

   struct string Tianyr, Liuqi, …;

   如果省略结构名, 则称之为无名结构, 这种情况常常出现在函数内部, 用这种结构时前面的例子变成:

  struct  {  char name[8];  int age;  char sex[2];  char depart[20];  float wage1, wage2, wage3, wage4, wage5;  } Tianyr, Liuqi;

   2.结构变量的使用

   结构是一个新的数据类型, 因此结构变量也可以象其它类型的变量一样赋值、运算,不同的是结构变量以成员作为基本变量。

   结构成员的表示方式为:结构变量.成员名如果将"结构变量.成员名"看成一个整体, 则这个整体的数据类型与结构中该成员的数据类型相同, 这样就可象前面所讲的变量那样使用。

#include"string.h"
#include"stdio.h"

struct Person
{
    char name[20];        //候选人姓名
    int count;            //候选人得票数
}leader[3]={"Li",0,"Zhang",0,"Sun",0};//定义结构体数组并初始化

int main()
{
    int i,j;
    char leader_name[20]; //定义字符数组
    for(i=1;i<=10;i++)
    {
        scanf("%s",leader_name); //输入所选的候选人姓名
        for(j=0;j<3;j++)
            if(strcmp(leader_name,leader[j].name)==0)
                leader[j].count++;
    }
    printf("\nResult:\n");
    for(i=0;i<3;i++)
        printf("%5s:%d\n",leader[i].name,leader[i].count);
    return 0;
}

文件的输入与输出

C语言是通过将一个文件类型指针与文件关联起来来对文件进行打开、关闭、输入、输出。

  文件类型为FILE(实际上是一个结构体)。定义一个文件指针为FILE *fp;就可以将fp和某个文件关联起来进行操作了。例如要打开一个文件:

  FILE *fp;fp=fopen("filename",“打开方式”);//fopen的返回值为NULL或指向文件的指针或者直接FILE *fp=("filename","打开方式");如果要重定向只需将指针fp和另一个文件关联。意思是可用一个文件指针操作多个文件。

  文件使用完后要及时关闭。这是个好习惯。关闭函数为fclose(fp);这样fp就不在和之前指向的文件关联了。

  1.判断文件是否打开成功: www.2cto.com

  判断文件是否打开成功可用fopen的返回值if((fp=fopen("filename","r"))NULL)则打开失败。

  2.判断文件是否结束:

  判断ASCII文件是否结束fgetc()会返回结束标志EOF(即-1)由于二进制文件数据会出现-1所以必须用函数feof(fp)判断,feof(fp)1则已结束。

  3.单个字符的输入输出:fgetc()和fputc()

  ch=fgetc(fp);fp为文件指针,且fgetc()不会忽略空格和回车符,只能用于读入字符。相应的fputc(ch,fp);向文件输出字符时也不会忽略空格,回车符因为fgetc()返回字符所以fgetc()和fputc()通常嵌套使用:fputc(fgetc(in),out)。

  fputc()的返回值为输入的字符或EOF(-1)(失败的情况下)

  fgetc()的返回值为读入的字符(包括文件结束标志EOF(-1))

  4.数据块的输入输出:fread(buff,size,count,fp)和发fwrite(buffer,size,count,fp)buffer是一个指针,对于fread,它是读入数据的存放地址,对于发fwrite它是要输出数据的地址,size是指要读写的字节数,count是要进行读写多少个size字节的数据项。

  如果成功fread和fwrite都返回成功输入和读取的数据块个数有可能比count小;

  注意:fread参数buffer指向的空间必须大于或等于要读入的数据块大小。

  fread和fwrite一般用于二进制文件的输入输出。用于ASCII文件字符发生转换的情况下可能出现与原设想的情况不同。

  5.putw()和getw()用来对磁盘文件读写一个整数。

  例如putw(10,fp);//返回值为输出的数字(int)

  int i=getw(fp);//失败则返回-1

  但注意putw()和getw()都是按二进制输入输出的。

  所以如果你用putw()输入数据到文件后以文本的方式打开看到的将都是乱码。

  同样如果你在文本文件中输入了数字并保存,用getw()来读入的话读入的结果并不是你想象的那样。因为它是按二进制读的

r

打开一个已有的文本文件,允许读取文件。

w

打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为零长度,重新写入。

a

打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。

r+

打开一个文本文件,允许读写文件。

w+

打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。

a+

打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。

注意:请确保您有可用的 tmp 目录,如果不存在该目录,则需要在您的计算机上先创建该目录。

/tmp 一般是 Linux 系统上的临时目录,如果你在 Windows 系统上运行,则需要修改为本地环境中已存在的目录,例如: C:\tmpD:\tmp等。

#include <stdio.h>

int main()
{
   FILE *fp = NULL;

   fp = fopen("D:\\CC\\test.txt","w+");
   fprintf(fp, "this is test fprinttf ……\n");
   fputs("This is testing fputs……\n", fp);
   fclose(fp);
   return 0;
}

首先,fscanf() 方法只读取了 This,因为它在后边遇到了一个空格。其次,调用 fgets() 读取剩余的部分,直到行尾。最后,调用 fgets() 完整地读取第二行。

#include <stdio.h>

int main()
{
   FILE *fp = NULL;
   char buff[500];

   fp = fopen("D:\\CC\\test.txt", "r");
   fscanf(fp, "%s", buff);
   printf("1: %s\n", buff );

   fgets(buff, 500, (FILE*)fp);
   printf("2: %s\n", buff );

   fgets(buff, 500, (FILE*)fp);
   printf("3: %s\n", buff );
   fclose(fp);

}

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
    FILE * fp = NULL;
    char str[3][10],temp[10]; //str是用来存放字符串的二维数组,temp是临时数组
    int i,j,k,n=3;
    printf("Enter strings:\n");  //提示输入字符串
    for(i=0;i<n;i++)
        gets(str[i]); //输入字符串
    for(i=0;i<n-1;i++)   //用选择法对字符串排序
    {
        k=i;
        for(j=i+1;j<n;j++)
            if(strcmp(str[k],str[j])>0)
                k=j;
        if(k!=i)
        {
            strcpy(temp,str[i]);
            strcpy(str[i],str[k]);
            strcpy(str[k],temp);
        }
     fp=fopen("D:\\CC\\test.txt","w");
        printf("\nThe new sequence:\n");
        for(i=0;i<n;i++)
        {
            fputs(str[i],fp);fputs("\n",fp); //向磁盘文件写一个字符串,然后输出一个换行符
            printf("%s\n",str[i]);       //在屏幕上显示
        }
    }
    return 0;
}

总结

因为之前学过类似语言,基础学习起来比较快。