C语言基础知识(学习笔记)

14 篇文章 14 订阅

1 编程初步

1.1 标识符

三种类型:保留字、标准标识符、由程序员创建的标识符。

1.1.1 保留字
编程语言为特定用途而预先定义的一个字,而且保留字只能用特定的方式用于它的原本用途。

autodefaultfloatregisterstructvolatile
breakdoforreturnswitchwhile
casedoublegotoshorttypedef
charelseifsignedunion
continueexternlongstaticvoid

1.1.2 标准标识符

是C语言中预先定义的字,它们具有预定义的用途,但程序员能够重新定义这个用途。

absfopenisalpahrandstrcpy
argcfreemallocrewindstrlen
argvfseekmemcpyscanftolower
callocgetsprintfsintoupper
fcloseisaciiputsstrcatungetc

1.1.3 有程序员创建的标识符

C语言的标识符规则:
字母、数字、下划线的任意组合
1、首字符必须是字母或下划线
2、只有字母、数字、下划线可以跟在首字母之后,不允许有空格。不能是保留字。

注意:C语言是大小写敏感的编程语言。

1.2 main()函数

每个程序都必须有一个main()函数。

int main()
{
	//函数体
	return 0;
}

1.3 头文件

预处理器命令:#include

名称函数类型
<assert.h>诊断程序
<ctype.h>单个字符测试
<errno.h>错误检测
<float.h>系统定义的浮点型界限
<limits.h>系统定义的整数界限
<locale.h>区域定义
<math.h>数学
<stjump.h>非局部的函数调用
<signal.h>异常处理和中断信号
<stdarg.h>可变长度参数处理
<stddef.h>系统常量
<stdio.h>输入/输出
<stdlib.h>多种公用函数
<string.h>字符串处理
<time.h>时间和日期函数

1.3.1 <stdio.h>

原型描述
int fclose (FILE *)关闭一个文件流
int fflush (FILE *)使任何被缓冲的但未被写入的输出数据写在输出上;没有定义输入
int fgetc (FILE *)如果遇到文件结束,从文件返回下一个字符(被转换为一个整数)或EOF
int fgets (char *s, int n, FILE * )最多读取n-1个字符到s数组中;在包含在这个数组中的一个换行符停止。这个数组自动地用\0终止
FILE *fopen (char *fname, char *mode)按指定的模式打开名为fname的文件
int fprintf (FILE * , char * format, args)在格式字符串的控制下写入这个args到这个文件流
int fputc (int c, FILE *)写入被转换为无符号字符的c到这个文件流
int fputs (char *s, FILE *)写入字符串s到这个文件流
int fscanf (FILE *, char *format, &args)在格式字符串的控制下从这个文件流读取
int fseek (FILE *, long offset, intorigin)设置这个文件的位置;这个位置被设置从原点偏移字符;这个原点可能是SEEK_SET,SEEK_CUR或SEEK_END,他们分别是这个文件的开始、当前位置或结束
long ftell (FILE *)如果有错误,返回这个当前文件的-1L的位置
int fgetc (FILE *)作为一个宏写入fgetc()
int getchar (void)与getc(stdin)相同
char *gets (char *s)读取下一个输入行到s数组中,用\0取代换行符
void perror (char *s)打印这个字符串s和一个与最后一个被报告的错误号(errno)相对应的编译器定义的错误信息
int printf (char *format, args)在格式字符串的控制下写入输出到标准的输出;相当于fprintf (stdout, char * format, args)
int putc (int c, FILE *)作为一个宏写入fputc()
int putchar (int c)与putc (c, stdout)相同
int puts (char *s)写入这个被一个换行字符跟随的字符串s到stdout
rewind (FILE *) int scanf (char *farmat, &args)在格式字符串的控制下从标准输入读取;相当于 fscanf (stdin, char *format, &args)
int sscanf (char *s, char *format, &args)除了输入被从这个s字符串读取之外,相当于scanf()
int sprintf (char *s, char *format, args)除了输出被写到这个s字符串之外,相当于prinrf();这个字符串以\0结尾并且必须足够大以容纳这个数据
int ungetc (int c, FILE *)把c(被转换成无符号字符)推回这个文件流之上

fopen的模式包括:
"r"为读取打开一个文件;
"w"为写入打开一个文件,如果文件存在,旧的内容被丢弃;
"a"为在这个文件末尾写入打开一个文件,如果文件不存在,创建一个新文件;
"r+"为读取和写入打开一个文本文件;
"w+"为更新创建一个文本文件,如果文件存在,旧的内容被丢弃;
"a+"为在这个文件末端写入打开一个文件;如果文件不存在,创建一个新文件

1.3.2 <ctype.h>

如果参数满足条件,则返回一个非0(真)整数;如果不满足,则返回一个0(假)数值。

原型描述
int isalnum (int c)c是文字数字的(文字或数字)
int isalpha (int c)c是一个字母
int iscntrl (int c)c是一个控制字符
int isdigit (int c)c是一个数字
int isgraph (int c)c是可打印的(排除空格)
int islower (int c)c是小写字母
int isprint (int c)c是可打印的(包括空格)
int ispunct (int c)c是可打印的(除了空格、字母或数字之外)
int isspace (int c)c是一个空格、进纸、换行、退格或制表符
int isupper (int c)c是大写字母
int isxdigit (int c)c是十六进制数字
int tolower (int c)转换c为小写字母
int toupper (int c)转换c为大写字母

1.3.3 <math.h>

原型描述
double asin (double x)x的反正弦
double acos (double x)x的反余弦
double atan (double x)x的反正切
double sin (double x)x的正弦
double cos (double x)x的余弦
double tan (double x)x的正切
double sinh (double x)x的双曲正弦
double cosh (double x)x的双曲余弦
double tanh (double x)x的双曲正切
double exp (double x)e的x次方
double fabs (double x)x的绝对值
double floor (double x)大于x的最大整数
double ceil (double x)不小于x的最小整数
double fmod (double x, double y)x/y的余数,用x的符号
double mod (double x, double * ip)x的小数部分,用x的符号,x的整数部分,用x的符号,都被ip指向x的y次方
double ldexp (x, n)x*2的n次方
double log (double x)ln(x)
double log10 (double x)log10(x)
double pow (x, y)x的y次方
double sqrt (double x)x的平方根

1.3.4 <stdlib.h>

原型描述
int abs (int n)整数的绝对值
long labs (long n)长整数的绝对值
double atof (char *s)转换s为双精度型
int atoi (char *s)转换s为整型
int atol (char *s)转换s为长整型
int rand (void)伪随机整数
void srand (unsigned int seed)伪随机整数用的种子
void *calloc (size_n, size_n)为n个对象的数组分配空间,每个大小为n,初始化所有被分配的字节为0
void *malloc (size_tn)为一个大小为n,内容保持与旧的相同,等于新的大小
void *realloc (void *p, size_n)重新分配空间到大小为n,内容保持与旧的相同,等于新的大小
void free (void *p)释放指向的空间
void exit (int status)正常程序终止

1.3.5 <string.h>

原型描述
char *strcat (char *d, char *s)连接字符串s到字符串d
char *strncat (char *d, char *s, int n)连接字符串s中至多n个字符到字符串d
char *strcpy (char *d, char *s)复制字符串s到字符串d
char *strncpy (char *d, char *s, int n)复制字符串s中至多n个字符到字符串d;如果s少于n个字符,用\0垫上
char *strcmp (char *d, char *s)比较字符串d与字符串s;如果d<s,返回<0,如果d==s,返回0,如果d>s,返回>0
char *strncmp (char *d, char *s, int n)比较字符串d中至多n个字符与字符串s;如果d<s,返回<0,如果d==s,返回0,如果d>s,返回>0
char *strchr (char *d, char *c)返回一个指向字符串d中c第一次出现的指针,或者如果没有找到c,返回指向NULL的指针
char *strrchr (char *d, char *c返回一个指向字符串d中c第一次出现的指针,或者如果没有找到c,返回指向NULL的指针
char *strstr (char *d, char *s)返回一个指向字符串d中字符串s第一次出现的指针,或者如果没有找到s,返回指向NULL的指针
int strlen (char *d)返回字符串d的长度,不包括终止符NULL
void *memcpy (void *d, void *s, int n)从s复制n个字符到d
void *memmove (void *d, void *s, int n)和memcpy相同,但即使d和s部分相同也运行
void *memcmp (void *d, void *s, int n)比较d的首先n个字符与s;和strcmp的返回相同
void *memchr (void *d, char c, int n)返回一个指向被d指向的n个字符c第一次出现的指针,或者如果没有找到c,返回指向NULL的指针
void *memset (void *d, char c, int n)c出现的地方用n填充d

1.4 数据类型

整型数据类型:
1、int(正负整数)
2、char(单个字符)
例如:‘A’ ‘!’(由一对单引号所包围的一个字母、数字、特殊符号)

浮点数据类型:(实数)
1、浮点型(float) 4.213f
2、双精度型(double) 4.213
3、长双精度型(long double) 4.213L

1.5 转义符

转义序列符描述含义
\n换行符移到一新行
\t水平制表符移到下一水平制表位
\v垂直制表符移到下一垂直制表位
\b退格符移回一个空格
\r回车符光标返回(把光标移到当前行的开始出——用于套印)
\f换页符发出一个换页指令
\a警报发出一个警报(通常是一个铃声)
\反斜线插入一个反斜线字符
?问号插入一个问号字符
\单引号插入一个单引号字符(把一个内单引号放置在一组外单引号内)
"双引号插入一个双引号字符(把一个内双引号放置在一组外双引号内)
\nnn八进制数数字nnn(n是一个数字)被认为是八进制数
\xhhhh十六进制数数字hhhh(h是一个数字)被认为是十六进制数
\0空字符出入一个空字符,它被定义为具有数值0

1.6 算数运算

1.6.1 转换控制序列

序列符含义
%d按十进制显示一个整数
%f按小数点后六位数的小数形式显示这个浮点数
%lf双精度浮点数
%c显示一个字符
%s显示一串字符串
%o按八进制显示一个整数(023在C中是八进制数)
%x按十六进制显示一个整数(0x在C中是十六进制数)
%p地址

1.6.2 算数运算符总结

运算运算符类型操作数结果
+二元两个都是整数整数
一个操作数不是整数双精度浮点数
-二元两个都是整数整数
一个操作数不是整数双精度浮点数
*二元两个都是整数整数
一个操作数不是整数双精度浮点数
/二元两个都是整数整数
一个操作数不是整数双精度浮点数
%二元两个都是整数整数
一个操作数不是整数双精度浮点数
求反B一元整数或浮点数同操作数

1.6.3 优先级

1、括号()最高优先级
2、取反(从右到左)
3、乘法、除法、模运算(从左到右)
4、加法、减法(从左到右)

例子:

#include <stdio.h>
int main()
{
	printf("%f + %f = %f\n", 15.0, 2.0, 15.0 + 2.0);
	printf("%c\n", 'a');
 	printf("%d\n", 'a');
 	printf("%c , %d\n", 'A', 'A');
 	
 	return 0;
}

输出结果:
在这里插入图片描述

1.7 变量和声明

变量名称:

1、必须以字母或下划线开始,并且只能包含字母、下划线或数字,
不能包含任何空格、逗号或特殊字符。
2、不能是关键字

声明语句:

例:
int sum;
float grade;
char ch;
float grade1, grade2, total, average;

初始化:
int sum = 0;

符号常量(命名常量):
#define PI 3.14159
常用做法:将符号常量全部用大写字母表示。与声明语句中的变量声明区别。

1.8 赋值

1、赋值运算符=:
结合性是从右到左
a=b=c=25
即a=(b=(c=25))
即c=25;b=25;a=25;

2、自增字符++:
a = a + 1
即a++或++a

注意:
a++与++a的区别
1、a++是先取a的值做计算,再自加
2、++a是先自加,再取a的值做计算
例:int a=2,b;
b=a++;先取a的值赋值给b,则b=2,a值再自加,则a=3
b=++a;a先自加,则a=3,再赋值给b,则b=3

3、
a = a + 1;
a += 1;
a ++;
三条语句执行相同功能,存储需求一般第一条最高,第三条最低。
(a += 1; a -= 1; a *= 1; a /= 1;)
(a++; a–;)

4、
隐式类型转换:
等号右边表达式的值将被转换为等号左边变量的数据类型。

显式类型转换(强制转换):
(int) sum
若sum是一个双精度浮点型变量,则上述表达式的值是通过截去sum的小数部分获得的整数值。

2 输入和输出

2.1 交互式输入

scanf("%d %d", &num1, &num2);

注意:

两者无区别:
scanf("%f%f", &num1, &num2);
scanf("%f %f", &num1, &num2);
两者有区别:
scanf("%c%c%c, &ch1, &ch2,&ch3);
scanf("%c %c %c, &ch1, &ch2,&ch3);

输入字符串:

#include <stdio.h>
main()
{
	char fkey, skey;
	
	printf("Type in a character: ");
	scanf("%c%c", &fkey, &skey);
	printf("The keysrtoke just accepted is %d", fkey);
	printf("\nType in another character: ");
	scanf("%c", &skey);
	printf("The keystroke just accepted is %d\n", skey);
	
	return 0;
}

注意:
scanf()后按压的键都会被保留在缓冲区,直到遇到下一个scanf()直接获得剩下的。输入第一个字符后被保存,输入的回车键的数字码也被保存在缓冲区,上述程序是解决的一种办法。

用户输入验证:

处理无效数据输入,在输入数据期间或者输入之后就立即进行验证,并且如果数据无效的话,
还要为用户提供一个重新输入的途径。

2.2 格式化输出

整数:

例1:printf(“The sum of %3d and %4d is %5d.”, 3, 14, 17);
输出结果:The sum of **3 and **14 is **17.(此处表示空格)

例2:printf("%03d", 2);
输出结果:002

浮点数:
%5.2f等格式字符串一般形式为[标志][输出最小宽度][.精度][长度]

1、输出最小宽度:
用十进制整数来表示输出的最少位数。若实际位数多于定义的宽度,则按实际位数输出,若实际位数少于定义的宽度则补以空格或0。

2、精度:
精度格式以“.”开头,后跟十进制整数。如果输出数字,则表示小数的位数;如果输出字符,则表示输出字符的个数;若实际位数大于所定义的精度数,则截去超过的部分。

3、长度:
长度格式符为h、l两种,h表示按短整型量输出,l表示按长整型量输出。
例:prinrf("%10.3f", 25.67);
输出:****25.670(前面四个空格)

指定符数字显示注释
%2d1*1数字适合字段
%2d1212数字适合字段
%2d123123字段宽度被忽略
%2d2.3取决于编译器浮点数在整数字段中
%5.2f2.346*2.35字段宽度5,有2位小数位
%5.2f23.423.40数字适合字段
%5.2f123.456123.46字段宽度被忽略但小数部分指定符被使用
%5.2f123取决于编译器整数在浮点数字段中

格式修饰符:

左对齐(-):(不加-默认为右对齐)
printf("%-10d", 59);
输出:59^^^^^^^^(8个空格)

明确显示符号(+):(不加+只对负数显示符号)
printf("%+10d", 59);
输出:^^^^^^^+59(7个空格)

左对齐且明确显示符号:
printf("%±10d", 59);等价于printf("%-+10d", 59);
输出:+59^^^^^^^(7个空格)

3 选择

3.1 关系表达式

关系运算符:

关系运算符含义
<小于
>大于
<=小于等于
>=大于等于
==相等
!=不相等

关系表达式的值总是两个可能的整数值之一(0或1),真1,假0。

逻辑运算符:

AND&&
OR
NOT!

优先级:(越向下优先级越低)

运算符结合性
!,一元-,++,–从右到左
*,/,%从左到右
+,-从左到右
<,<=,>,>=从左到右
==,!=从左到右
&&从左到右
从左到右
+=,-=,*=,/=从左到右

3.2 if 语句

Created with Raphaël 2.2.0 开始 条件为真吗 语句 结束 yes no
if (表达式)
	语句1;

if (表达式)
{
	语句1;
	语句2;
	语句3;
	……;
}

3.3 if…else 语句

Created with Raphaël 2.2.0 开始 条件为真吗 语句1 结束 语句2 yes no
if (表达式)
	语句1;
else
	语句2;

if (表达式)
{
	语句1;
	语句2;
	……;
}
else
{
	语句a;
	语句b;
	……;
}

3.4 if…else 链

Created with Raphaël 2.2.0 开始 表达式1为真 语句1 结束 表达式2为真 语句2 结束1 语句3 yes no yes no
if (表达式1)
	语句1;
else
	if (表达式2)
		语句2;
	else
		语句3;

if (表达式1)
	语句1;
else if (表达式2)
	语句2;
else
	语句3;

上面两种形式是一样的意思!

if(表达式1)
	语句1;
else if(表达式2)
	语句2;
else if(表达式3)
	语句3;
……
else if(表达式nn)
	语句n;
else
	最后的语句;

3.5 switch 语句

Created with Raphaël 2.2.0 开始 case数值1 语句1 break 结束 case数值2 语句2 break case数值3 语句3 break default yes no yes no yes no
switch (整型表达式)
{
	case 数值1:
		语句1;
		语句2;
		……;
		break;
	case 数值2:
		语句m;
		语句n;
		……;
		break;
	……
	case 数值n:
		语句w;
		语句x;
		……;
		break;
	default:
		语句aa;
		语句bb;
		……;
}

4 循环

4.1 while 语句

初始化语句;
while (表达式)
{
	语句;
	……;
	表达式改变语句;
}

4.2 for 语句

for (初始化列表;被测表达式;改变列表)
{
	语句;
	……;
}

4.3 do…while 语句

do
	语句;
while (表达式);

4.4 break 语句和 continue 语句

break语句:

强制从switch语句、while语句、for语句或者do…while语句中立即退出。

continue语句:

用于while语句、for语句、do…while语句。立即开始循环的下一次迭代。
while语句中,自动转移到循环的顶部并重新计算被测表达式的值。
for语句中,迫使控制传递到改变列表,由此会重新计算被测表达式的值。

空语句:

分号前面没有任何内容的语句。

5 函数

5.1 函数声明

函数原型:

返回数据类型 函数名(参数数据类型列表)
例:int fmax(int, int);
float roi(int, char, char, float);
void display(float, float); /不返回任何值/
可以放在#include <stdio.h>前或后,可应用于文件中的所有函数;
可以放在main()里面,只可应用于main()函数。

调用函数:

例:findMax(firstnum, secnum);
函数只接收这些变量值的副本。

函数首部行:

C语言函数由两部分组成:函数首部和函数体。

函数首部:
每一个函数都必须从函数首部行开始。
在函数首部行中列出的所有参数,必须用逗号分开,且必须分别声明他们的数据类型。
例:void findMax(float x, float y)
这个函数不直接返回任何值,且只要调用它,就需要接受两个浮点值。

函数体:
{
变量声明(如果有的话)
其他C语句
}

语句的放置:

预处理命令
符号常量
函数原型可以放置在这里
int main()
{
	函数原型可以放置在这里
	变量声明;
	
	其他可执行语句;

	return 数值;
}

5.2 标准库函数

1、数学库函数(头文件<math.h>)

2、rand()函数与srand()函数(头文件<stdlib.h)
srand()函数为rand()函数提供了一个开始的“种子”值。

3、比例放缩
产生a到b之间的随机数:a+(int)(rand()%(b-a+1))

4、输入/输出库函数(头文件<stdio.h>)
printf()、scanf()
专门用于字符型数据:getchar()、putchar()
例:inChar = getchar()等价于scanf("%c",&inChar)
purchar(‘a’)等价于printf("%c",“a”)

5、字符处理函数(头文件<ctype.h>)

6、转换函数(头文件<stdlib.h>)

5.3 变量的作用域

全局变量、局部变量
除了符号常量和函数原型以外,几乎从来不应该使用全局变量。

5.4 变量存储类

局部变量:

只能是auto(自动)、static(静态)、register(寄存器)存储类的成员。
(auto为默认存储类)
auto:函数结束前都是保留的,函数结束后就销毁
static:在函数执行完成时,变量中存储的最后值在下一次它被调用时是可获得的。
静态变量初始化只执行一次,第二次调用时不初始化。没有给出明确的初始化时都被设置为0。
register:与自动变量唯一不同的是变量存储区被分配的位置。很少使用

全局变量:

只能是static(静态)、extern(外部),但不能同时声明为这两种
extern:将一个源代码文件中声明的全局变量的作用域扩展到另外的源代码文件中。

5.5 按引用传递

指针变量(指针):能够存储地址的变量

地址运算符&:&num表示“num的地址”

间接运输符*:当*符号后面紧跟一个指针时,表示这是一个地址被存储在其中的变量

按值传递与按引用传递的区别:

按值传递最多只能返回一个值,按引用传递可返回多个值。

例子:

#include <stdio.h>
int main()
{
	void calc(float, float, float, float *, float *);
	float firstnum, secnum, thirdnum, sum, product;

	printf("Enter three numbers: ");
	scanf("%f %f %f", &firstnum, &secnum, &thirdnum);

	calc(firstnum, secnum, thirdnum, &sum, &thirdnum);

	printf("\nThe sum of the entered numbers is: %6.2f", sum)
	printf("\nThe product of the entered numbers is: %6.2f\n", product);

	return 0;
}

void calc(float num1, float num2, float num3, float *sumaddr, float *productaddr)
{
	*sumaddr = num1 + num2 + num3;
	*productaddr = num1 * num2 * num3;
}

注意:C语言默认的是按值传递而不是按引用传递,从而精确地限制被调函数改变调用函数中变量的能力。因此,只要有可能,就应该坚持标准的安置调用过程,这意味着地址参数只应该用在实际要求多个返回值的极为严格的情形中。上述程序可用两个单独的函数来返回两个值。当排序一个数字列表或者名称列表,使其成为升序(增加)或降序(减少)时,返回多个值的函数是绝对必要的。

5.6 递归

直接递归:调用自身

间接递归(相互递归):函数能够调用第二个函数,反过来第二个函数也可以调用第一个函数。

递归与迭代的比较:

递归:用于解决方案可用同一问题的更简单版本表示的任何问题。
迭代:任何递归函数总是能够用一种使用迭代的非递归方法编写。
能用递归或迭代解决时,用迭代;只能用递归时,用递归。

6 数组

6.1 一维数组

声明:

声明语句给出了数组中项目的数据类型、数组(或列表)、数组中项目的个数
#define NUMELS 5
int grades[NUMELS];

注意:所有数组的开始索引值总是0。
grades[0]指的是保存在grades数组中的第一个数
grades[1]指的是保存在grades数组中的第二个数

初始化:

#define NUMGRADES 5
int grades[NUMGRADES] = {98, 87, 92, 79, 85};

#define NUMCODES 6
char codes[NUMCODES] = {'s', 'a', 'm', 'p', 'l', 'e'};

特点:当初始化值包含在声明语句中时,数组的大小可以省略。
int gallons[] = {16, 12, 10, 14, 11};
char codes[] = "sample";

数组作为函数实参:

1、将数组元素作为下标变量包含在函数调用的实参表中
findMin(grades[2], grades[6]);

2、传递一个完整的数组到函数
findMin(grades);
与传递变量不同,被调函数接收对实际数组的访问,而不是这个数组中的值的副本。
(改变被调函数中数组的值,就改变了调用函数中数组的值)

6.2 二维数组

声明:

#define NUMROWS 3
#define NUMCOLS 4
int val[NUMROWS][NUMCOLS];
数组val由3行4列组成。

初始化:

#define NUMROWS 3
#define NUMCOLS 4
int val[NUMROWS][NUMCOLS] = { {8, 16, 9, 52},
							{3, 15, 27, 6},
							{14, 25, 2, 10} };
或
int val[NUMROWS][NUMCOLS] = { 8, 16, 9, 52,
							3, 15, 27, 6,
							14, 25, 2, 10 };
或
int val[NUMROWS][NUMCOLS] = { 8, 16, 9, 52, 3, 15, 27, 6, 14, 25, 2, 10 };

传递二维数组到函数,是一个与传递一维数组相同的过程。
可以省略行长度,但列的大小必须包括。

内部数组元素定位算法:

数组元素i的地址=数组开始地址+偏移量
一维数组:偏移量=i单个元素的长度
二维数组:列索引值
单个元素的长度+行索引值在完整的一行中的字节个数
在完整的一行中的字节个数=指定的最大列数
单个元素的长度

7 字符串

7.1 输入输出

字符串输入和输出:(头文件<stdio.h>)

1、按完整单元处理字符串:gets()、puts()
2、单个字符的输入和输出:getchar()、putchar()
3、printf()、scanf()

字符串保存成由一个指定的字符串末端的名称为NULL的符号常量终止的字符型数组。
NULL常量的值是转义序列符\0,并且是标志字符串末端的标记。(要多预留一个位置保存\0)

按下回车键即产生一个换行符\n,这个字符被gets()函数解释为输入字符末端。
所有由gets()函数获得的字符,除了换行符,都被保存到数组中。
在输入时,\0取代\n;在输出时,\n取代\0

printf()总能代替puts()
scanf()不能代替gets()
scanf()遇到空格或换行符停止,gets()只有遇到换行符才停止。

注意:
scanf("%s", &message[0])等价于scanf("%s", message)
例:输入“This is a string”只有“This”被赋值给message数组。

7.2 库函数

字符串库函数:(头文件<string.h>)

strcpy()复制、strcat()附加、strlen()长度、strcmp()比较
例:
strcpy(str1, str2)
strcat(str1, str2)
strlen(string)
strcmp(str1, str2)

初始化:(下面几个声明的结果相同)

char test[5] = “abcd”;
char test[] = “abcd”;
chat test[5] = {‘a’,‘b’,‘c’,‘d’,’\0’};
chat test[] = {‘a’,‘b’,‘c’,‘d’,’\0’};

字符库函数:(头文件<ctype.h>)

int isalpha(char) 字母
int isupper(char) 大写
int islower(char) 小写
int isdigit(char) 数字
int isascii(char) ASCII字符
int isspace(char) 空格
int iscntrl(char) 控制字符
int ispunct(char) 标点字符
int toupper(char) 小写变大写(其他字符不受影响)
int tolower(char) 大写变小写(其他字符不受影响)

转换函数:(头文件<stdlib.h>)

int atoi(string) ASCII字符串转为整数
double atof(string) ASCII字符串转为双精度型数值
char[] itoa(string) 整数转为ASCII字符串

建立个人数据库:

例:头文件#include<C:\mylibrary\dataChecks.h>
注意:若dataChecks.h头文件中的函数要求stdio.h和stdlib.h函数,必须把它放在这两个之后

7.3 格式化字符串

右对齐:
printf("|%25s|", “Have a Happy Day”)
输出结果:|*********Have a Happy Day|(前面9个空格)

左对齐:
printf("|%-25s|", “Have a Happy Day”)
输出结果:|Have a Happy Day*********|(后面9个空格)

指定宽度和精度右对齐:
printf("|%25.12s|", “Have a Happy Day”)
输出结果:|*************Have a Happy|(后面13个空格)

指定宽度和精度左对齐:
printf("|%-25.12s|", “Have a Happy Day”)
输出结果:|Have a Happy*************|(后面13个空格)

指定精度不指定宽度:
printf("|%.12s|", “Have a Happy Day”)
输出结果:|Have a Happy|

内存中的字符串转换:

sprintf()、sscanf()

例:sprintf(disStrn, “%d %d”, num1, num2);
把num1和num2的数值写入disStrn中而不是在标准的输出终端上显示这些值。

例:sscanf(data, “%c%lf %d”, &dol, &price, &units);
将扫描保存到data数组中的字符串,并将它拆分为三个data项。

8 数据文件

8.1 声明、打开、关闭

文件:是保存到一个共同名称之下的数据集合,通常保存到磁盘、磁带或光盘上。
文件流:是用于连接保存到物理设备上的文件到一个程序的单向传输路径。

8.1.1 声明文件流:

FILE *inFile;
FILE *prices;
FILE *fp;
(FILE是特殊的数据结构类型,头文件<stdio.h>)

8.1.2 打开文件流:

fopen()函数(头文件<stdio.h>)
第一个参数是文件的外部名,第二个参数是使用文件的模式,必须放置在双引号中。
允许的模式有r(读)、w(写)、a(附加)。
如果外部名称首先保存到一个字符数组中或作为一个字符串被保存,
这个数组或字符串的名称不加双引号,也能够用做给fopen()函数的第一个参数。

例:
outFile = fopen(“prices.bnd”,“w”);
打开一个名称为prices.bnd的现在能够被写入的外部文件。
outFile = fopen(“prices.bnd”,“a”);
打开一个名称为prices.bnd的文件,并且使它可用于将数据添加到文件的末尾。
outFile = fopen(“prices.bnd”,“r”);
打开一个名称为prices.bnd的文件,并且使文件中的数据可用于输入。

使用完整的路径名:
fopen("\test\files\prices.dat", “r”)

注意:
用写入模式w打开的文件和用附加模式a打开的文件的唯一差别是数据被物理上放置在文件中
的位置。在w中,数据被写在文件的开始处;在a中,数据被写在文件结束处。对于新文件,两种
模式的效果相同。

模式指示符:
r 为读取(输入模式)打开一个现存的文本文件。
w 为写入(输出模式)创建一个文本文件;如果文件已存在,它的内容将丢失。
a 为写入(输出模式)打开一个文本文件,新加入的文本被写在现存文件的末尾。如果文件不存在,则会创建一个新文件。
r+ 为读和写打开一个现存的文本文件,如果文件存在,则它的内容被擦掉。
w+ 为读和写创建一个文本文件。
a+ 为读和写打开一个文本文件,文本被写在该文件的末尾,如果不存在文件,一个新文件为读和写被创建。

exit()函数:(头文件<stdlib.h>)
参数为0表示正常退出,非0表示异常退出。

注意:
调用fopen()函数时,检查它的返回值是重要的。

嵌入式文件名和交互式文件名:
用字符串保存外部文件名

8.1.3 关闭文件流:

fclose()函数:中断文件的外部名和内部名之间的连接。
参数:在文件被打开时使用的指针名。
所有的计算机在每次能够打开的最大文件数上有限制,关闭不需要的文件具有好的意义。

例:
fclose(inFile); /关闭inFile文件/

8.2 读取和写入文本文件

8.2.1 写入:

函数:(头文件<stdio.h>)
fputc(c, filename) 把一个字符写入文件
fputs(s, filename) 把一个字符串写入文件
fprintf(filename, “format”, args) 按照格式把一个参数的数值写入文件

例:
fputc(‘a’, outFile);
fputs(“Hello world!”, outFile);
fprintf(outFile, “%s %n”, descrip, price);

8.2.2 读取:

函数:(头文件<stdio.h>)
fgetc(filename) 从文件读取一个字符
fgets(stringname, n, filename) 从文件读取n-1个字符并把字符存储在给定的字符串名中
fscanf(filename, “format”, &args) 根据这个格式,从文件读取所列出的参数值

例:
fgetc(inFile);
fgets(message, 10, inFile);
fscanf(inFile, “%lf”, &price);

注意:结束标记
fgetc()、fscanf()函数返回名称为EOF的常量
fgets()函数返回一个NULL(\0)

8.3 随机文件访问

rewind(filename) 重置当前文件开始的位置,
fseek(filename, offset, origin) 允许程序员移动到文件中的任何位置
ftell(filename) 返回下一个将被读取或写入的字符的偏移量值

例:
fseek(inFile, 4L, SEEK_SET); /转向这个文件中的第5个字符/
fseek(inFile, 4L, SEEK_CUR); /向前移动5个字符/
fseek(inFile, -4L, SEEK_CUR); /向后移动5个字符/
fseek(inFile, 0L, SEEK_SET); /转向rewind()的相同文件的开始/
fseek(inFile, 0L, SEEK_END); /转向文件的结尾/
fseek(inFile, -10L, SEEK_END); /转向文件结尾之前的10个字符/

注意:fseek()的偏移量必须是一个长整数型。
fseek()函数的三个参数:文件的指针名、作为长整型的偏移量、偏移量从这个位置被计算的位置

程序:

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int ch, n;
	long int offset, last;
	FILE *inFile;
	
	inFile = fopen("text.dat", "r");
	if(inFile == NULL)
	{
		printf("\nFailed to open the test.dat file.\n");
		exit(1);
	}
	fseek(inFile, 0L, SEEK_END);	/*移到这个文件的结尾*/
	last = ftell(inFile);	/*保存最后一个字符的偏移量*/
	for(offset = 0; offset <= last; offset++)
	{
		fseek(inFile, -offset, SEEK_END);	/*向后移到下一个字符*/
		ch = getc(inFile);	/*得到这个字符*/
		switch(ch);
		{
			case '\n': printf("LF: ");
				break;
			case EOF: printf("EOF: ");
				break;
			default: printf("%c: ", ch);
				break;
		}
	}
	fclose(inFile);

	return 0;
}

假设文件text.dat包含数据:Bulbs 3.12
则输出:EOF:2:1:.:3: 😒🅱️l:u:B:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值