【计理03组01号】C语言基础知识

养成好的命名习惯

(1)函数名用大写字母开头的单词来命名。例如:

void InitPort(void);
void UpDisplay(void);

(2)变量用小写字母开头的单词来表示。例如:

uchar openLight;
uchar closeLight;

(3)常量用全大写的字母,并用下画线分隔单词。例如:

#define  MAX_TIME 10
#define  MIN_TIME 100

运算符的优先级

【计理03组01号】C语言基础知识

getchar 函数

函数 getchar 的功能是在键盘上输入一个字符并读取字符的值,其具体使用格式如下所示。

getchar();

在日常应用中,通常把输入的字符赋值给一个字符变量,构成赋值语句,例如下面的代码。

char char1;
char1=getchar();                            //输入字符并把输入的字符赋值给一个字符变量
putchar(char1);                            //输出字符

在具体使用函数 getchar 时,应该注意如下 4 点。

(1)getchar 函数只能接受单个字符,输入的数字也按字符来处理。当输入多个字符时,只接收第 1 个字符。

(2)使用 getchar 函数前程序中必须包含文件“stdio.h”。

(3)在 Tuber C 屏幕下运行含本函数的程序时,将退出 Tuber C 屏幕进入用户屏幕等待用户输入。输入完毕再返回 Tuber C 屏幕。

(4)程序的最后两行可以用下面的任意一行来代替。

putchar(getchar());
printf("%c",getchar());

函数 getchar 有一个整型返回值。当程序调用 getchar 后,程序会一直等候用户按键输入。用户输入的字符存储在键盘缓冲区中,直到用户按 Enter 键为止(回车字符也放在缓冲区中)。当用户按 Enter 键之后,getchar 才开始从 stdin 流中读入字符,每次一个。getchar 函数的返回值是用户输入的第 1 个字符的 ASCII 码,如出错则返回 −1,且将用户输入的字符回显到屏幕上。如用户在按 Enter 键之前输入了多字符,则其他字符会保留在键盘缓存区中,等待后续 getchar 函数调用读取。也就是说,后续的 getchar 调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完为后才等待用户按键。

printf语句

函数 printf 又称为格式输出函数,关键字中的最后一个字母“f”有“格式”(format)之意。printf 函数的功能是按用户指定的格式,把指定的数据显示到显示器上。在前面的实例中,已多次使用过这个函数。

printf 函数的一般形式

函数 printf 是一个标准库函数,它的函数原型包含在头文件“stdio.h”中。但作为一个特例,不要求在使用 printf 函数之前必须包含 stdio.h 文 c 件。函数 printf 的一般格式如下。

printf("格式控制字符串",输出表列)

(1)“格式控制字符串”用于指定输出格式。格式控制字符串分为格式字符串和非格式字符串两种。格式字符串是以%开头的字符串,在%后面跟随各种格式的字符,目的是说明输出数据的类型、形式、长度、小数位数等。例如下面的格式。

  • “%d”表示按十进制整型输出。
  • “%ld”表示按十进制长整型输出。
  • “%c”表示按字符型输出。

非格式字符串在输出时按原样输出,在显示中起到提示作用。

(2)“输出表列”给出了各个输出项,要求格式字符串和各输出项在数量和类型上一一对应。

scanf函数

函数 scanf 又称为格式输入函数,能够按用户指定的格式从键盘上把数据输入到指定的变量之中。

函数 scanf 的一般形式

函数 scanf 是一个标准的库函数,其函数原型包含在头文件“stdio.h”中。和函数 printf 相同,C 语言也允许在使用函数 scanf 之前不必包含 stdio.h 文件。使用函数 scanf 的一般格式如下所示。

scanf("格式控制字符串",地址列表);

其中,“格式控制字符串”的作用与函数 printfc 的相同,但是不能显示非格式字符串,即不能显示提示的字符串。地址列表给出各变量的地址。地址是由地址运算符“&”后跟变量名组成的。例如下面的代码分别表示变量a和变量b的地址。

&a, &b

上述地址就是编译系统在内存中给变量acb分配的地址。在 C 语言中,地址的概念与其他语言是不同的,应该把变量值和变量地址这两个不同的概念区别开来。变量地址是由 C 编译系统分配的,用户不必关心具体的地址是多少。

例如在赋值表达式a=123中给变量赋值,则a为变量名,123是变量值,&a是变量a的地址。

在赋值符号左边是变量名,不能写地址。而函数 scanf 在本质上也是给变量赋值,但它要求写变量的地址,例如&a,这二者在形式上是不同的。单独一个&是一个取地址运算符,而&a是一个表达式,其功能是求变量的地址。

看下面的一段代码。

int main(void){
   int a,b,c;
   printf("input a,b,c\n");
   scanf("%d%d%d",&a,&b,&c);
  printf("a=%d,b=%d,c=%d",a,b,c);
}

在上述代码中,因为函数 scanf 本身不能显示提示字符,所以先用 printf 语句在屏幕上输出提示用户输入abc的值。当执行 scanf 语句后,程序会退出 Turbo C 屏幕进入用户屏幕以等待用户输入。用户输入 7   8   9 后按下 Enter 键,此时系统又将返回 Turbo C 屏幕。在 scanf 函数的格式串中,因为没有非格式字符在“%d%d%d”之间作输入时的间隔,所以在输入时要用多个空格或 Enter 键作为两个输入数之间的间隔。

格式字符串

函数 scanf 的格式字符串和函数 printf 的类似,以%开头,以一个格式字符结束,中间可以插入附加的字符。函数 scanf 的格式如下所示。

%[*][输入数据宽度][长度]格式字符

其中,方括号“[]”中的部分为可选项。在上述格式中各选项的具体说明如下所示。

  • 格式字符。

格式字符用于标识输出数据的类型,各格式字符的具体说明如下表所示。

格式 字符意义
d 输入十进制整数
o 输入八进制整数
x 输入十六进制整数
u 输入无符号十进制整数
f 或 e 输入实型数(为小数形式或指数形式)
c 输入单个字符
s 输入字符串
  • “*”字符。

用以表示该输入项,读入后不赋值给相应的变量,即跳过该输入值。例如:

scanf("%d %*d %d",&a,&b);

当输入 1、2、3 时,会把 1 赋值给a,跳过 2,3 赋值给b

  • 宽度。

用十进制整数指定输入的宽度(即字符数)。例如:

scanf("%5d",&a);

如果输入“12345678”,则会把 12345 赋值给变量a,截去其余部分。例如:

scanf("%4d%4d",&a,&b);

如果输入“12345678”,则会把 1234 赋值给a,而把 5678 赋值给b

  • 长度。

长度格式符是 l 和 h,l 表示输入长整型数据(如%ld)和双精度浮点数(如%lf);而 h 则表示输入短整型数据。

在 C 语言中使用函数 scanf 时,必须注意以下 6 点。

(1)在函数 scanf 中没有精度控制,例如scanf("%5.2f",&a);是非法的。不能用此语句输入小数位数为两位的实数。

(2)scanf 中要求给出变量地址,如给出变量名则会出错。例如scanf("%d",a);是非法的,应改为scanf("%d",&a);这才是合法的。

(3)在输入多个数据时,若格式控制字符串中没有使用非格式字符作为输入数据之间的间隔,则可用空格、制表符或回车符。在编译时如果遇到空格、Tab、Enter 或非法数据(如对“%d”输入“12A”时,A 即为非法数据),则认为该数据输入结束。

(4)在输入字符数据时,若格式控制字符串中无非格式字符,则认为所有输入的字符均为有效字符。例如:

scanf("%c%c%c",&a,&b,&c);

如果输入d``e``f,则会把d赋值给a,把空格赋值给b,把e赋值给c。只有当输入为def时,才能把d赋值给a,把e赋值给b,把f赋值给c。如果在格式控制中加入空格作为间隔,例如,

scanf ("%c %c %c",&a,&b,&c);

则输入时可在各数据之间加空格。

看下面的一段代码。

int main(void){
   char a,b;
   printf("input character a,b\n");
   scanf("%c%c",&a,&b);
   printf("%c%c\n",a,b);
}

在上述代码中,因为在 scanf 函数"%c%c"中没有空格,所以输入“M   N”后,输出结果中只有 M。而输入改为 MN 时才可以输出 MN 两个字符。

(5)如果格式控制字符串中有非格式字符,则输入时也要输入该非格式字符。例如:

scanf("%d,%d,%d",&a,&b,&c);

其中,用非格式符“,”作为间隔符时,应为 5、6、7。例如:

scanf("a=%d,b=%d,c=%d",&a,&b,&c);

此时输入应该为a=5b=6c=7

(6)如果输入的数据与输出的类型不一致时,虽然编译能够通过,但结果将不正确。

puts 函数

函数 puts 的头文件是 stdio.h,其功能是向标准输出设备写字符串并自动换行,直至接收到换行符或 EOF 时停止,并将读取的结果存放在由 str 指针所指向的字符数组中。换行符不作为字符串的内容,读取的换行符转换为空值,并由此来结束字符串。

使用函数 puts 的语法格式如下所示。

puts(字符串参数)

其中,“字符串参数”可以是字符串数组名或字符串指针,也可以是字面字符串,并且该字符串参数可以包含转义字符,但是不能包含格式字符串。具体说明如下所示。

  • 函数 puts 只能输出字符串,而不能输出数值或进行格式变换。
  • 可以将字符串直接写入到函数 puts 中。
  • 由于函数 puts 可以无限读取,却不会判断上限,所以程序员应该确保 str 的空间足够大,以便在执行读操作时不会发生溢出。

C11 标准函数 gets_s

函数 gets_s 的功能是,从标准输入设备(stdin)上读取 1 个字符串(可以包含空格),并将其存储到字符数组中去,并用空字符(\0)代替输入字符串中的换行符。在 C11 标准之前,此函数名为 gets。函数 gets_s 读取的字符串的长度没有限制,程序员要保证字符数组有足够大的空间,以存放输入的字符串。如果调用成功则返回字符串参数 s;如果遇到文件结束或出错,则返回空值。该函数输入的字符串中允许有空格,而函数 scanf()则不允许。

使用函数 gets 的语法格式如下所示。

gets(字符数组)
gets_s 函数和 scanf 函数的区别

scanf 函数和 gets_s 函数都可用于输入字符串,但在功能上有所区别。若想从键盘上输入字符串“hi hello”,则应该使用 gets_s 函数。gets_s 可以接收空格,而 scanf 遇到空格、回车符和制表符都会认为输入结束,所以它不能接受空格。例如:

char string[15]; gets_s (string); /*遇到回车符为认为输入结束*/
scanf("%s",string); /*遇到空格会认为输入结束*/

在输入字符串中包含空格时,应该使用 gets 输入。

在 C 语言中,至少有两个能够获取字符串的函数:scanf 和 gets_s。二者的不同点如下所示。

  • scanf 不能接受空格、制表符、回车符等。
  • gets_s 能够接受空格、制表符和回车符等。

二者的相同点如下所示:

  • 在字符串结束后会自动加'\0'。
  • 当 scanf 函数遇到回车符、空格和制表符后会自动在字符串后面添加'\0',但是回车符、空格和制表符仍会留在输入的缓冲区中。
  • gets_s 可以接受 Enter 键之前输入的所有字符,并用'\n'替代 '\0',回车符不会留在输入缓冲区中。
  • 用 gets_s 读取字符串,用 Enter 结束输入。
  • scanf 可以读取所有类型的变量。

克服 gets_s 函数的缺陷

在 C 语言中函数 gets_s 是从 stdin 流中读取字符串的函数,此函数接受从键盘上输入的字符直到遇到 Enter 键时终止。函数 gets_s 的原型是:

char* gets(char *buff);

例如:

#include <stdio.h>
int main(void)
{
       charstr[30];
       while(!str!= gets_s (str));
       printf("%s\n",str);
       return 0;
}

如果读取成功,gets_s 函数的返回值是和 str 值相同的指针,否则返回空指针。

函数 gets_s 是一个危险的函数,原因是用户在键盘上输入的字符个数可能大于缓冲区的最大值,而函数 gets_s 并不对其检查。当用户在键盘上输入多个数据时,程序有可能会发生崩溃。解决方法是重写一个新的函数 gets_s,原型是:

char* Gets(int maxlen)

这个函数可让程序员指定输入字符的最大个数,在函数中为字符分配存储空间,函数返回 char*。

这个函数是针对动态数组而编写的,例如:

int main(void)
{
       char*p;
   p=Gets(18);
}

函数 gets_s 中的参数舍弃传入指针的原因是传入函数的指针可能不可靠,这样会造成程序崩溃,比如传入一个野指针。

另一个 gets_s 函数的原型是:

char* const Gets(char* const array,int maxlen);

这个函数针对固定长度的字符数组进行输入,例如:

int main(void)
{
    charstr[20];
    Gets(str,20);
    return 0;
}

此时函数 gets_s 中的有一个参数是 char* const 类型,原因是它允许程序员修改这个类型指针所指向的内容,但不能修改指针本身。具体实现代码如下。

#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <io.h>
char* Gets(int maxlen)
//最多从键盘上读入maxlen个字符,返回字符串指针类型
{
       int i;
       staticchar* str;
       char c;
       str=(char*)malloc(sizeof(char) *maxlen);
       if(!str)
       {
              perror("memeoryallocation error!\n");
              return0;
       }
       else
       {
              for(i=0;i<maxlen;i++)
              {
                      c=getchar();
                      if(c!='\n')str[i]=c;
                      elsebreak;
              }
              str[i]='\0';
              returnstr;
       }
}

char* const Gets(char* const array,int maxlen)
{
       int i;
       char c;
       for(i=0;i<maxlen;i++)
       {
             c=getchar();
             if(c!='\n')array[i]=c;
             elsebreak;
       }
       array[i]='\0';
       returnarray;
}

int main(void)
{
       char s[8];
       Gets(s,8);
       puts(s);
fflush(stdin); //刷新输入缓冲区,这很重要,否则会影响下一个Gets函数
    char*p=Gets(8);
       puts(p);
       return 0;
}

C 语言的输入和输出问题

请看下面的代码。

#include<stdio.h>
int main(void)
{
    putchar(getchar());
    putchar(getchar());
    putchar(getchar());
    putchar('\n');
}

输入a,按下 Enter 键,输入b,按下 Enter 键后,运行就结束了。运行结果为:

a
a
b
b

这是因为当你输入a并按下 Enter 键时,系统得到两个字符,一个是a,另一个是 Enter 键。所以系统会输出a和回车符,这是第 2 个a的由来。第一个a以及紧接着的 Enter 回车符都是用户输入的,它们作为 getchar 的返回值返回给 putchar。所以第 2 个a和紧接着的 Enter 键就是 putchar 的两次返回值。b的产生过程同理。其实,b后面还有个 Enter 键,只是没在意而已。

造成上述问题的原因是没有清空缓冲区里数据,我们可以将程序修改为如下形式。

#include<stdio.h>
int main(void)
{
    putchar(getchar());
    fflush(stdin);
    putchar(getchar());
    fflush(stdin);
    putchar(getchar());
    putchar('\n');
}

这样当每次输入后,会强制清空标准输入流。

 

上一篇:【c语言】大数相加、高精度加法


下一篇:C语言---课程设计【学生成绩管理系统】