C语言复习总结——易错点归纳

写在最前面!

1、C语言每一行最好只写一句!每一句语法后面基本上都要有分号作为这一句的结尾!
2、主函数main() 最好写成int类型的返回值,并在函数结尾加上return 0;虽然不加返回语句不一定会报错,但是要保持良好的代码编写习惯,
3、数组的下标是一个很容易出错的地方,在遍历循环数组,尤其是排序的时候,注意开始和结束的条件和判断!
4、常用的头文件

  • stdio.h
  • stdlib.h
  • math.h
  • string.h
  • ctype.h
    5、在进行除法计算的时候一定要注意1/2和1.0/2的区别,前者是整除,后者是小数除法!尤其是在解决数学问题的时候很容易出错。

字符串

1)字符串的输入
易错点: 在输入字符串之前一定要注意回车换行符,如果不读走就会被scanf("%s",s);或gets(s)读入到字符串中从而影响最后的结果!

  • gets()
    参数:字符指针变量名、字符数组名。
    使用gets()方法时,系统会自动将最后敲入的回车换行符从缓冲区读走,然后丢弃。所以接在gets()方法后面的字符串输入可以不用担心回车换行符会被读入字符串的问题。gets()方法把回车换行符作为字符串输入的结束标志。
  • scanf()
    scanf()函数也有返回值,一般不会用到,读入数据成功就会返回1。
    使用scanf()方法输入字符串的时候一定要考虑回车换行符!而且无法将空格读入,所以在操作字符串的输入时最好使用gets()方法!

2)字符串的输出

  • printf()
    输出时注意换行符’\n’

  • puts()
    参数:字符指针变量名、字符数组名,或者直接是一个字符串常量。
    输出时只有遇到 ‘\0’ 也就是字符串结束标志符才会停止。系统会自动最字符串末尾添加一个换行符’\n’。
    用了puts()函数以后妈妈再也不用担心我输出的字符串不会换行啦!
    所以在输出字符串的时候最好使用puts()函数!

3)常用函数
C语言中没有字符串类型变量,字符串均是字符数组构成,使用与字符串相关的函数需要提前导入头文件string.h

  • strlen()

size_t strlen( const char* str)

计算的是字符串的实际长度,遇到第一个’\0’结束。
参数指向的字符串必须以 ’ \0 ‘结束。

  • strcpy()

char* strcpy(char* dest,char* src)

功能:将参数src字符串拷贝至参数dest所指的地址。
返回值:返回参数dest的字符串起始地址 。
源字符串必须以’\0’结束。
如果参数dest所指的内存空间不够大,可能会造成缓冲溢出的错误情况,在编写程序时需特别留意,或者用strncpy()来取代。

  • strncpy()

char* strncpy(char* dest,const char* src,size_t num)

功能:拷贝src字符串的前num个字符至dest
返回值:dest字符串起始地址
如果src字符串长度小于num,则拷贝完字符串后,在目标后追加0,直到num个。
strncpy不会向dest追加’\0’
src和dest所指的内存区域不能重叠,且dest必须有足够的空间放置n个字符

  • strcat()

char* strcat(char* dest,const char* src)

功能: 将参数src字符串复制到参数dest所指的字符串尾部
返回值:返回dest字符串起始地址

源字符串必须’\0’结束
目标空间必须可修改
dest最后的结束字符’\0’会被覆盖掉,并在连接后的字符串的尾部再增加一个’\0’
dest与src所指的内存空间不能重叠,且dest要有足够的空间来容纳要复制的字符串

  • strncat()

char* strncat (char* dest,const char* src,size_t num)

功能:从字符串src的开头拷贝n个字符到dest字符串尾部
返回值:返回dest字符串的起始地址

dest要有足够的空间来容纳要拷贝的字符串
如果n大于字符串src的长度,那么仅将src全部追加到dest的尾部
strncat会将dest字符串最后的’\0’覆盖掉,字符追加完成后,再追加’\0’

  • strcmp()

int strcmp (const char* str1,const char* str2)

功能:判断两个字符串大小。判断顺序(1)ASII码 (2)长度
返回值:若参数s1和s2字符串相同则返回0,s1若大于s2则返回大于0的值,s1若小于s2则返回小于0的值

区分大小写比较的,如果希望不区分大小写进行字符串比较,可以使用stricmp函数。

-strncmp

int strncmp(const char* str1,const char* str2,size_t num)

功能:比较str1和str2前num个字符组成的字符串大小
返回值:若参数str1和str2字符串相同则返回0,str1若大于str2则返回大于0的值,str1若小于str2则返回小于0的值

  • 字符分类函数(添加头文件ctype.h)

int isalnum(int c):检查字符是否为数字或字母;(09,az,A~Z)
int isalpha(int c):检查字符是否为字母;(a~z, A~Z)
int iscntrl(int c):检查字符是否为控制字符;(八进制000~037以及177的字符)
int isdigit(int c):检查字符是否为十进制数字;(0~9)
int isgraph(int c):检查字符是否为图形表示,依赖于使用语言的环境;09,az,A~Z,以及标点符号)
int islower(int c):检查字符是否为小写的字母;(a~z)
int isprint(int c):检查字符是否为可打印的;(数字、字母、标点符号、空白字符)
int ispunct(int c):检查字符是否为标点符号;(! ” # $ % & ’ ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~等)
int isspace(int c):检查字符是否为空白字符;(TAB、换行、垂直TAB、换页、回车、空格)
int isupper(int c):检查字符是否为大写字母;(A~Z)
int isxdigit(int c):检查字符是否为十六进制数字;(0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f)

动态分配数组

注意:动态分配数组的函数默认返回值是void所以要使用类型强制转换,与定义的数据类型保持一致。
1)malloc

  • 用法:
#include<stdlib.h>//使用malloc()一定要写头文件!
/*给字符指针动态分配n个char型字符所占字节的存储空间
即字符指针p所分配的存储空间最多可以存储n个char型字符。*/
char *p = (char*) malloc(n*sizeof(char));

int *q = (int*) malloc(n*sizeof(int));

2)calloc
用法:

#include<stdlib.h>
double *p = (double *)calloc(n,sizeof(double));

结构体

  • 定义
struct tag { 
    member-list
    member-list 
    member-list  
    ...
} variable-list ;

tag:结构体标签。
member-list:标准的变量定义,比如 int i; 或者 float f,或者其他有效的变量定义。
variable-list:结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量。

下面是声明 Book 结构的方式:

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;

在一般情况下,tag、member-list、variable-list 这 3 部分至少要出现 2 个。

/此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//同时又声明了结构体变量s1
//这个结构体并没有标明其标签
struct 
{
    int a;
    char b;
    double c;
} s1;
 
//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//结构体的标签被命名为SIMPLE,没有声明变量
struct SIMPLE
{
    int a;
    char b;
    double c;
};
//用SIMPLE标签的结构体,另外声明了变量t1、t2、t3
struct SIMPLE t1, t2[20], *t3;
 
//也可以用typedef创建新类型
typedef struct
{
    int a;
    char b;
    double c; 
} Simple2;
//现在可以用Simple2作为类型声明新的结构体变量
Simple2 u1, u2[20], *u3;
  • 对结构体变量初始化
#include <stdio.h>
 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book = {"C 语言", "RUNOOB", "编程语言", 123456};
 
int main()
{
    printf("title : %s\nauthor: %s\nsubject: %s\nbook_id: %d\n", book.title, book.author, book.subject, book.book_id);
}
  • 访问结构体成员
    使用成员访问运算符(.)访问结构体成员。
#include <stdio.h>
#include <string.h>
 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
 
int main( )
{
   struct Books Book1;        /* 声明 Book1,类型为 Books */
   struct Books Book2;        /* 声明 Book2,类型为 Books */
 
   /* Book1 详述 */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali"); 
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;
 
   /* Book2 详述 */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;
 
   /* 输出 Book1 信息 */
   printf( "Book 1 title : %s\n", Book1.title);
   printf( "Book 1 author : %s\n", Book1.author);
   printf( "Book 1 subject : %s\n", Book1.subject);
   printf( "Book 1 book_id : %d\n", Book1.book_id);
 
   /* 输出 Book2 信息 */
   printf( "Book 2 title : %s\n", Book2.title);
   printf( "Book 2 author : %s\n", Book2.author);
   printf( "Book 2 subject : %s\n", Book2.subject);
   printf( "Book 2 book_id : %d\n", Book2.book_id);
 
   return 0;
}
  • 结构体指针
#include <stdio.h>
#include <string.h>
 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
 
/* 函数声明 */
void printBook( struct Books *book );
int main( )
{
   struct Books Book1;        /* 声明 Book1,类型为 Books */
   struct Books Book2;        /* 声明 Book2,类型为 Books */
 
   /* Book1 详述 */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali"); 
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;
 
   /* Book2 详述 */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;
 
   /* 通过传 Book1 的地址来输出 Book1 信息 */
   printBook( &Book1 );
 
   /* 通过传 Book2 的地址来输出 Book2 信息 */
   printBook( &Book2 );
 
   return 0;
}
void printBook( struct Books *book )
{
   printf( "Book title : %s\n", book->title);
   printf( "Book author : %s\n", book->author);
   printf( "Book subject : %s\n", book->subject);
   printf( "Book book_id : %d\n", book->book_id);
}

例题1
约瑟夫问题:N个人围成一圈,从第一个人开始报数,数到M的人出圈;再由下一个人开始报数,数到M的人出圈;……直到只剩1人,输出依次出圈的人的编号。N,M由键盘输入。用数组实现。

#include<stdio.h>

int main(){
	int n;  //游戏人数 
	int m;	//报数 
	int i;	//游标 
	int c=0;	//计数变量 
	int p=0;	//记录出局人数 
	printf("请依次输入参与游戏的人数和数字:");
	scanf("%d %d",&n,&m);
	int a[n]; //用于存储每个游戏者的编号 
	for(i=0;i<n;i++){
		a[i] = i+1;//将每个人的编号存入数组中 
	}

	for(i=0;i<n;i++){
		if(a[i] != 0){//没有出局的人报数 
			c++;
			if(c == m){ //数到m的人出局
			 
				printf("%2d出圈\n",a[i]);
				c = 0; //计数器恢复到0 
				a[i] = 0; //出局以后用0做标记 
				p++; //出局的人数加一 
			}
		}
		if(i==n-1){ //所有游戏者都报数一遍后再从第一个游戏者开始报数。 
			i=-1;//再次循环的时候先进行i++才进入循环,所以这里i=-1而不是0
		}
		if(p==n-1){ //出局人数达到要求退出循环 
			break;
		}
	}
	for(i=0;i<n;i++){
		if(a[i]!=0)
		printf("%d为最后一人",a[i]);
	}
	
}


例题2
加密的病历单

小英是药学专业大三的学生,暑假期间获得了去医院药房实习的机会。在药房实习期间,小英扎实的专业基础获得了医生的一致好评,得知小英在计算概论中取得过好成绩,主任又额外交给他一项任务,解密抗战时期被加密过的一些伤员的名单。经过研究,小英发现了如下加密规律。

原文中所有的字符都在字母表中被循环左移了3个位置(dec-abz)

逆序存储(abcd–dcba)

大小写反转(abXY-ABxy)

若给定一个加密的字符串(只含有大小写字母),请给出明文。

# include<stdio.h>
# include<string.h>

char Alp[] = {'D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C'};

char alp[] = {'d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a','b','c'};

char password[100];//存储密文 
char p[100];//存储逆序后的密文 
int length;//获取字符串长度 

void opposite(){//大小写字母翻转。
	int i;//游标 
	for(i=0;password[i]!='\0';i++){ 
		if(password[i]>64 && password[i]<91){
			password[i] +=32;
		}else{
			password[i] -=32;
		}
	} 
}

void reverse(){//倒叙存储 
	int i;//游标 
	for(i=0;i<length;i++){
		p[length-i-1]=password[i];
	} 
}

void move(){//将字符串每个字符进行循环移动 
	int i,j;
	for(i=0;i<length;i++){
		if(p[i]>64 && p[i]<91){
			j = p[i]-'A';
			p[i] = Alp[j];
		}else{
			j = p[i]-'a';
			p[i]=alp[j];
		}
	}

}
int main() {
	int i;//游标
	char t;//倒序交换 
	int j;
	char *p1;
	gets(password);
	length = strlen(password); 
	opposite();
	reverse();
	move(); 
	puts(p);
}

例题3

统计输入的字符串中的单词数个数。(输入的字符串由字母和空格组成,不包含任何标点符号。)
思路:字符串仅由字母和空格组成,因此只要是字母前面出现空格就可以认为是一个单词,从而字符串中的单个或多个空格对统计单词数量都没有实质性的影响。对于字符串开头的单词可以单独判断来解决偶然性。

#include<stdio.h>
#include<string.h>
#include<ctype.h>

int main(){
	char words[100];
	int i;//游标
	int count=0;//单词统计变量 
	printf("请输入英文文本:");
	gets(words);
	if(isalpha(words[0])){
		count++;
	}
	
	for(i=0;i<strlen(words);i++){
		if(isalpha(words[i]) && words[i-1] == ' '){
			count++;
		}
	}
	printf("单词数量为:%d",count);
} 
  • 4
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值