C语言笔记

目录

14

231120_字符串分割​编辑

231211_多层嵌套

231216_正序分割A(n位数)并逐位输出

 231217_for循环中大括号的必要性

231217_输出n行数字金字塔

231217_函数调用注意点

231217_static\全局变量

231217_形参、实参

231218_整型常量

231218_转换说明符/输出格式控制

231218_逗号表达式

231219_条件表达式

231219_++i和i++的区别

231224_数组

231230_字符及字符串


14


这是因为else if括号内把x赋值为0了,所以X值会变化。其实应该是else if (x==0)


 


输出结果是S


可以用scanf()获取字符,
char a;
scanf("%c", &a);
也可以用printf()输出字符 printf("%c",a);




231120_字符串分割

# include <stdio.h>
int main()
{
char ch;
int first = 1, k, n;
scanf("%d\n", &n);
for(k = 1; k <= n; k++){
    ch=getchar();
    if ( first == 1){
     putchar(ch); 
      first+=1;
    }else{ 
     printf("\n");
             putchar(ch);
        }
    }
    return 0;
}

switch case要注意break;的书写,以及case与后面常数间要保留空格



1.while语句的一般形式如下,其中的循环体语句只能是一条语句。

while (表达式)

循环体语句

答案:T

解析:for 循环和while 循环循环体都是一条语句,但是可以加{}变成复合语句,但也算一条。


231211_多层嵌套

  • 在嵌套循环(多层循环)中, 每一层循环都应该使用自己的循环变量,以免互相干扰。
  • 在嵌套循环(多层循环)中, 每一层循环中都不应该改变其他层使用的循环变量的值,以免互相干扰。

231216_正序分割A(n位数)并逐位输出

 若想要:正序分割A,并逐位输出。首先计算A是N位数,再用A除10的(N-1)次方取商

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

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char *argv[]) {
	
	int digit, number, pow, t_number;

    scanf("%d", &number);
    t_number = number;
    pow = 1;
    
    while (t_number > 9)//获取number位数 
    {
        pow = pow * 10;//pow位数+1 
        t_number = t_number / 10;//t_number位数-1 
    }
    
    while (pow >= 1)//开始分割 
    {
        digit = number / pow;
        number = number - digit * pow;
        pow = pow / 10;
        printf("%d ", digit);
    }
    printf("\n");
	
	return 0;
}

 231217_for循环中大括号的必要性

for循环语句如果循环体内只有一条执行语句则不用加大括号,如果执行语句为多条语句则必须用大括号括起来,以表示这一部分的执行语句都在循环体内,循环条件满足时要被执行的语句;如:(1

for(i=0;i<5;i++)  s+=m[i];//这个循环体内就一条执行语句s+=m[i];故不用大括号

2

for(i=0;i<5;i++)
    for(j=0;j<5;j++){
        a[i][j]=m;
        m++;
        if(j<=i) printf("%3d",a[i][j]);
    }

这个例题双重for循环,第一重循环for(i=0;i后没有大括号,因为他的循环体内只有一条执行语句就是内循环语句,它是一个复合语句:for(j=0;j<5;j++){a[i][j]=m;m++;if(j<=i) printf("%3d",a[i][j]);}

而内循环语句后有大括号,是因为内循环体内包括a[i][j]=m;和m++; 和if(j<=i) printf("%3d",a[i][j]); 三条执行语句,想把他们都包括到循环体内就必须用大括号括起来,作为一个复合语句出现。

for 语句还有空循环模式,就是没有执行语句,如:for(i=0;str[i]!='\0';i++); 此句后就有分号,表示为空循环,没有执行语句,它的功能就是为了得到i的值。


231217_输出n行数字金字塔

在C语言的函数定义中,如果不需要返回结果,就可以省略return语句。如下代码:

本题要求实现函数输出n行数字金字塔。

n是用户传入的参数,为[1, 9]的正整数。要求函数按照如样例所示的格式打印出n行数字金字塔。注意每个数字后面跟一个空格。

#include <stdio.h>
void pyramid( int n );
int main()
{    
    int n;
    scanf("%d", &n);
    pyramid(n);
    return 0;
}
/* 你的代码将被嵌在这里 */
void pyramid( int n ){
	int i,j;
	for(i=1;i<=n;i++){
		for(j=n;j>i;j--)
		printf(" ");
		for(j=1;j<=i;j++)
		printf("%d ",i);
		printf("\n");
	}		
}

231217_函数调用注意点

void fun(int n,double x)

{......}

若下列选项中的变量都已正确定义并赋值,则对函数fun的正确调用语句是()

A. fun(int y,double m)

B. k=fun(10,12.5)

C. fun(x,n)

D. void fun(n,x)

解析:因为fun是void,也即是无返回值,所以不能k=fun(B),函数调用是直接传入实参,不需要传类型(A),函数调用不能把返回类型也写上(D)

231217_static\全局变量

函数f定义如下,执行语句“sum=f(5)+f(3);”后,sum的值应为( )。

int f(int m){
  static int i=0;
  int s=0;
  for(;i<=m;i++)
  s+=i;
return s;
}

答案:15

解析:首先明确for循环三个表达式,(表达式1;表达式2;表达式3),循环结束前表达式3执行了操作。然后明确静态局部变量的意思,f(5)=15,结束时i=6;再进入函数i=6,不执行,返回值 就是0;15+0=15.


静态局部变量

静态局部变量使用static修饰符定义

1)在全局数据区分配内存空间,即使函数返回,它的值也会保持不变;(倘若再次调用定义它的函数时,它又可继续使用,而且保存了前次被调用后留下的值。)

2)在声明时未赋初值,编译器自动对其初始化为0

3)其作用域为局部作用域,当定义它的函数结束时,其作用域随之结束

4)出现在函数内部的基本类型的静态变量初始化语句只有在第一次调用才执行(如上题中的i=6)

全局变量

全局变量定义在函数体外部,在全局数据区分配存储空间,且编译器会自动对其初始化。

1)普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。

2)静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。所以,在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用。

#include<stdio.h>
int x;
int f(int n)
{
   int x = 1;
   return x;
}
int main(void)
{
   printf("%d %d", f(3),x);
   
   return 0;
}
//上面程序运行结果是1 0

全局变量只能定义在程序的最前面,即第一个函数的前面。(x)

用法:在主函数之前定义全局变量(不包含在任何变量里)

        int po;//全局变量

在主函数main中调用,要加关键字extern

        extern int po; //全局变量


231217_形参、实参

形参

1.形参只能是变量,在被定义的函数中,必须指定形参的类型。

2.没有确定的值

3.形参变量在未出现函数调用时,并不占用内存,只在调用时才占用。调用结束后,将释放内存。

实参

1.实参可以是常量、变量、表达式、函数等

2.无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值。

3.开辟内存存储数据

函数的实参和形参都可以是变量、常量和表达式。(x)

实参:常量、变量、表达式、函数等任意类型

形参:变量!同时在定义函数(函数名、函数体)时,指定形参的类型


231218_整型常量

在C语言中,整型常量分为十进制整型常量、八进制整型常量和十六进制整型常量三种表示形式。

1、十进制整型常量

此种格式的整型常量只能出现 0~9 的数字,且可带正、负号。比如:0 1 364 28 -34

2、八进制整型常量

此种格式的整型常量以数字0开头的八进制字串。其中数字为 0~7。例如:

0111十进制 73、011十进制 9、0123十进制 83、

3、十六进制整型常量

此种格式的整型常量以0x或0X(x是大写)开头的十六进制字串。其中每个数字可以是 0~9、a~f或 A~F 中的数字或英文字母。例如:

0x11十进制 17、0Xa5十进制 165、0x5a十进制 90


231218_转换说明符/输出格式控制

%d整型输出(有符号十进制整数),%ld长整型输出,

%o以无符号八进制整数输出,

%x以无符号十六进制整数输出,

%p指针的值、地址符,

%u以无符号十进制整数输出。

%c用来输出一个字符,

%s用来输出一个字符串,

%f用来输出十进制的浮点数,以小数形式输出,

%e以指数形式输出实数,

%g根据大小自动选f格式或e格式,且不输出无意义的零

    说明:

(1). 可以在"%"和字母之间插进数字表示最大场宽。

     例如: %3d   表示输出3位整型数, 不够3位右对齐。

        %9.2f 表示输出场宽为9的浮点数, 其中小数位为2, 整数位为6, 小数点占1位, 不够9位右对齐。

               %8s   表示输出8个字符的字符串, 不够8个字符右对齐。

    如果字符串的长度、或整型数位数超过说明的场宽, 将按其实际长度输出。但对浮点数, 若整数部分位数超过了说明的整数位宽度, 将按实际整数位输出; 若小数部分位数超过了说明的小数位宽度, 则按说明的宽度以四舍五入输出

  • 另外, 若想在输出值前加一些0, 就应在场宽项前加个0。

    例如:   %04d 表示在输出一个小于4位的数值时, 将在前面补0使其总宽度为4位。

  • 如果用浮点数表示字符或整型量的输出格式, 小数点后的数字代表最大宽度,小数点前的数字代表最小宽度。

    例如: %6.9s 表示显示一个长度不小于6且不大于9的字符串。若大于9, 则第9个字符以后的内容      将被删除。

(2). 可以在"%"和字母之间加小写字母l, 表示输出的是长型数

    例如:   %ld   表示输出long整数、%lf   表示输出double浮点数

(3). 可以控制输出左对齐或右对齐, 即在"%"和字母之间加入一个"-" 号可说明输出为左对齐, 否则为         右对齐。

    例如:   %-7d 表示输出7位整数左对齐、 %-10s 表示输出10个字符左对齐

(4)%p和%x的区别:

  • 输出类型相同:都是无符号十六进制。
  • 输出结果不同:

        a. %p以十六进制的形式是打印地址,编译器多少位,就打印多少位。比如:32位的打印32                位,64位打印64位(不够的左边补0);

        b. %x的输出位数不固定,比如:0x01,0x0101,0x01010101等。

#include <stdio.h>
    int main(){
    int i;

    printf("%X",&i);//运行后输出65FE1C
    printf("%p",&i);//运行后输出000000000065FE1C

	return 0;
}

   


关于保留小数点后有效位数四舍五入原则

#include <stdio.h>
int main()
{
float f1=3.1415926;
float f2=1234.1415926;
float f3=124.1;
printf("%3.4f\n", f1);
printf("%3.4f\n", f2);
printf("%3.4f\n", f3);
printf("----------------\n");
printf("(%m.nf) 打印至少m个字符宽度(包括小数点和小数部分的位数),打印n位小数");//
printf("----------------\n");
printf("%8.3f\n",3.1415926);//打印" 3.142" 一共8位,前面3个空格
printf("%2.6f\n",3.1415926);//打印"3.141593"
printf("%6.6f\n",3.1415926);//打印"3.141593" 至少打印2个字符和6个字符 在这没区别
printf("%6.4f\n",3.1415926);//打印"3.1416"
printf("%7.4f\n",3.1415926);//打印" 3.1416"前面打印一个空格
printf("%8.4f\n",3.1415926);//打印" 3.1416" 前面打印两个空格
printf("%2.9f\n",3.1415926);//打印"3.141592600"
printf("%2.9f\n",333.1415926);//打印"333.141592600" 小数位补0
return 0;
}

输出结果:


231218_逗号表达式

判断:表达式 (z=0, (x=2)||(z=1),z) 的值是1(x)

解析:

运行的结果应该是0。(z=0, (x=2)||(z=1),z)这是一个逗号表达式,它是从左到右依次计算各个表达式,而最终表达式的值为最后一个表达式的值,具体分析如下:首先计算第一个表达式z=0,它给把z赋值为0;然后计算第二个表达式(x=2)||(z=1),因为||为短路或运算符,即当检查到某个条件的值为真-即一个不等于0的值后,即停止往后判断条件,所以这里执行完x=2后,第一个条件已为真, 所以后面的z=1不继续执行;接着计算第三个表达式,即一个z,无赋值等操作;最后,返回整个逗号表达式的值,即最后一个表达式z的值0,它在第一步计算中赋值为0,所以最后整个表达式的值为0。


231219_条件表达式

设int a=5,b=6,表达式(++a==b--)?++a:--b的值是?

解析:

结果为7。

条件表达式为:表达式1?表达式2:表达式3。先求解表达式1,若其值为真(非0)则将表达式2的值作为整个表达式的取值,否则(表达式1的值为0)将表达式3的值作为整个表达式的取值。

先判断++a==b--是否为真,++a表达的值为6,b--表达的值为6,两者相等,为真。则将表达式++a的值作为整个表达式的取值,因为在此之前a的值已经自增变成6,再进行++a表达式的值为7。

条件运算符优先级高于赋值、 逗号运算符 ,低于其他运算符


231219_++i和i++的区别

​+、-作为单目运算符时,表示正负,+a 等于a,-a等于负a


231224_数组

在定义数组时,系统会在内存中分配一段连续的地址来存储这个数组。其中数组名是一个指针常量,它指向数组中第一个元素的地址。因此,数组名的值是一个地址,不能被修改。

如果你想修改数组名的值,你可以考虑使用指针来实现。指针是一个变量,它存储了一个地址。通过修改指针的值,你可以改变指针所指向的地址。

以下是一个示例,演示了如何使用指针来修改数组名的值:

#include <stdio.h>

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int *ptr = arr; // 将指针ptr指向数组arr的第一个元素的地址

    printf("原始数组名的值:%p\n", arr);
    printf("原始指针的值:%p\n", ptr);

    ptr = &arr[2]; // 修改指针的值,使其指向数组arr的第三个元素的地址

    printf("修改后的数组名的值:%p\n", arr);
    printf("修改后的指针的值:%p\n", ptr);

    return 0;
}

输出结果:

原始数组名的值:0x7ffeedd4a9e0
原始指针的值:0x7ffeedd4a9e0
修改后的数组名的值:0x7ffeedd4a9e0
修改后的指针的值:0x7ffeedd4a9e8

在这个示例中,我们定义了一个整型数组arr,并将指针ptr指向数组的第一个元素的地址。然后,我们修改了指针的值,使其指向数组的第三个元素的地址。通过打印数组名和指针的值,我们可以看到数组名的值没有改变,但指针的值已经被修改。

判断题

  • int cnt[10] = {1}; 定义了数组cnt,并对cnt[0]赋初值1,其余元素的初值为0。(√)
  • int fib[45]; 定义了数组fib,且45个数组元素的值都不确定。(√)

231230_字符及字符串

c语言'a'和"a"有什么区别

1、本质区别。双引号里面的是字符串, 而单引号里面的代表字符。

2、输出区别。str = “a”输出的就是a这个字母;str = ‘a’输出的测试65

3、底层区别。用单引号引起的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值。

  • 字符'\0'的ASCII码值为0。
  • 字符串常量就是用一对双引号括起来的字符序列,它有一个结束标志 '\0'

231231_计算字符串的有效长度

#include <stdio.h>
int main(){
    int k, len;
    char str[81];
    k = 0;
    while((str[k]=getchar())!='\n'){
        k++;
    }    
    str[k]='0';
    len = k;
    printf("%d\n", len);
    return 0;
}
#include  <stdio.h>
unsigned int  MyStrlen(const char str[]);
 
int main()
{
    char   a[80];
    unsigned int len;
    gets(a);
    len=MyStrlen(a);
    printf("%u\n", len);
    return 0;
}
 
/*在此实现MyStrlen函数*/
unsigned int  MyStrlen(const char str[])
{
	int count=0;
	for (int i = 0; str[i] != '\0'; i++)
    {
    	count++;
	}
	return count;
}

240101_字符排队

        将给定字符串中的字符,按照ASCII码顺序从小到大排序后输出。

#include <stdio.h>
#include <string.h>
int main(){
	char a[80],t;
	gets(a);
//	printf("%s",a);
	for(int i=0;i<strlen(a);i++){
		for(int j=i;j<strlen(a)-1;j++){
			if(a[j+1]<a[i]){
				t=a[i];
				a[i]=a[j+1];
				a[j+1]=t;				
			}					
		}		
	}
	printf("%s",a); 
	return 0;
}

下述对C语言字符数组的描述中错误的是(C):
A,字符数组可以存放字符串   //int a[10]="abcdefghi";
B,字符数组中的字符串可以整体输入、输出   //使用 gets()接收 puts()输出
C,可以在赋值语句中通过赋值运算符“=”对字符数组整体赋值   //char str[] = "skf";这是初始化,定义了以后,就不能使用所谓的赋值语句str="else"了。只能用memcpy函数或strcpy函数进行赋值
D,不可以用关系运算符对字符数组中的字符串进行比较   // 字符串的比较在C中只能用strcmp之类的函数

解析:这是一考题,猜想出题的目的,C选项大概是想考字符数组不能像指针那样用。比如:
char arr[10];
arr="hello";
这样就不行,而:
char *arr;
arr="hello";
这样是可以的。


240107_指针

对于类型相同的两个指针变量之间不能进行运算的是“+”运算。

类型相同的两个指针变量之间可以进行<(小于)、=(赋值)、-(减法)运算。

1、“<(小于)”运算在两个同类型的指针间可以比较大小,比较原则应该是按照实际内存的高低位比较的

2、“=(赋值)”是对于类型相同的两个指针变量之间常规运算。

3、“-(减法)”运算两个相同指针变量相减可以获得在之间相隔的同类型元素个数(在某个类型的数组中的应用)。

4、“+”运算是不可以的,因为两个指针相加什么都得不到,所以规定不允许相加。


240107_输入年份和天数,输出对应的年、月、日

        要求定义和调用函数month_day (int year, int yearday, int * pmonth, int * pday),通过参数pmonth和pday返回计算得出的月和日。例如,输入2000和61,分别返回3和1,即2000年的第61天是3月1日。

# include <stdio.h>
void month_day ( int year, int yearday, int * pmonth, int * pday);

int main (void)
{
   int day, month, year, yearday; /*  定义代表日、月、年和天数的变量*/
   scanf ("%d%d", &year, &yearday );        
   month_day (year, yearday, &month, &day );/* 调用计算月、日函数  */ 
   printf ("%d %d %d\n", year, month, day );    
   return 0;    
}

/* 请在这里填写答案 */
void month_day ( int year, int yearday, int * pmonth, int * pday){
	int sum[13]={0};
	int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
	if((year%4==0&&year%100!=0)||(year%400==0))	a[2]=29;
	for(int i=1;i<=12;i++){
		sum[i]=sum[i-1]+a[i];
	}
	for(int i=1;i<=12;i++){
		if(sum[i-1]<yearday&&yearday<=sum[i]){
			*pmonth=i;
			*pday=yearday-sum[i-1];break;
		}
	}
}	

240107_关于int*p=&a与int *p;p=&a;

        两者的作用是一样的,都是指针的初始化。定义一个指针后必须进行初始化!)
第一种:定义时直接进行初始化

int a = 10;
int *p = &a;

&是取地址符号,取的是地址;用法为  &变量名。
int *是指针变量的类型,p是变量名。

因此 &a 取到的地址是赋值给 p 而不是 *p 的,所以p中存的内容是a的地址 。

第二种:定义后再进行初始化

int a = 10;
int *p;
p = &a;

        在C/C++语言中,指针一般被认为是指针变量,指针变量的内容存储的是其指向的对象的地址,指向的对象可以是变量(指针变量也是变量),数组,函数等占据存储空间的实体。通俗来讲指针就是存放内存单元的的地址。


         *是取值运算符,取的是值;用法为    *指针变量 。因为指针变量p被赋值了一个地址,所以对指针变量取值就是对一个地址取值,得到的结果就是放在那个地址上的值。所以*p是一个值

         *p=a;单独一条语句没有错误。但这样并不是给指针初始化!!!

int a = 10;
int *p;
*p = a;

        这样写会报错,原因是没有对指针进行初始化。int *p后,p指向的是一个随机的地址,这个地址上储存的值也是随机的,我们不能随意修改其值,否则会造成系统紊乱。

        在下述的情况时可以使用这条语句

#include <stdio.h>
  
void pswap(int *p1,int *p2)
{
        int temp;
        temp = *p1;
        *p1 = *p2;
        *p2 = temp;
}
int main()
{
        int a = 10;
        int b = 20;
        printf("Before pswap: a=%d b=%d\n",a, b);
        pswap(&a, &b);
        printf("After pswap: a=%d b=%d\n", a ,b);
        return 0;
}

以上摘录于链接:https://blog.youkuaiyun.com/qq_47548559/article/details/115016308


 240107_冒泡排序_函数

#include <stdio.h>
void bubble (int a[ ], int n);
int main(void)
{    
  int n, a[10];
    int i;
    scanf("%d", &n);
    for (i=0; i<n;i++)
        scanf("%d",&a[i]);
    bubble(a,n);
    for (i=0; i<n; i++)
        printf("%d ",a[i]);
  printf("\n");
    return 0;
}

/* 请在这里填写答案 */
void bubble (int a[ ], int n){
	int k; 
	for(int i=n-1;i>0;i--){
		for(int j=0;j<i;j++){
			if(a[j]>a[j+1]){
				k=a[j];
				a[j]=a[j+1];
				a[j+1]=k;
			}
		}
	}
}

240107_二分查找_函数

# include<stdio.h>
int Bsearch(int *p, int n, int x);     
int main(void)   
{
	// p是数组首地址,n是数组元素个数,x是要查找的值
    int a[10] = {1,2,3,4,5,6,7,8,9,10};    
    int x, m;
    scanf("%d",&x);                
    m = Bsearch(a, 10, x);
    if(m >= 0)   
        printf("Index is %d\n",m);
    else 
        printf( "Not Found\n");
    return 0;
}

/* 请在这里填写答案 */
int Bsearch(int *p, int n, int x){
	int left=0;
	int right=n-1;
	while(left<=right){
		int mid=(left+right)/2;
		if(p[mid]>x) right=mid-1;
		else if(p[mid]<x) left=mid+1;
		else if(p[mid]==x) return mid;
	}
	return -1;
}

240107_指针引用数组元素

        现在有一个问题:“数组名 a 表示数组的首地址,a[i] 表示的是数组第 i+1 个元素。那么如果指针变量 p 也指向这个首地址,可以用 p[i] 表示数组的第 i 个元素吗?”可以

        下面写一个程序看一下:

# include <stdio.h>
int main(void)
{
    int a[] = {1, 2, 3, 4, 5};
    int *p = a;
    printf("p[0] = %d\n", p[0]);
    printf("p[1] = %d\n", p[1]);
    printf("p[2] = %d\n", p[2]);
    printf("p[3] = %d\n", p[3]);
    printf("p[4] = %d\n", p[4]);
    return 0;
}

输出结果是:
p[0] = 1
p[1] = 2
p[2] = 3
p[3] = 4
p[4] = 5
所以 p[i] 和 *(p+i) 是等价的,即“指向数组的”指针变量也可以写成“带下标”的形式。

        那么反过来,因为数组名 a 表示的也是数组的首地址,那么元素 a[i] 的地址也可以用 a+i 表示吗?回答也是“可以的”。也就是说如果指针变量 p 指向数组 a 的首地址,那么 p+i 和 a+i 是等价的,它们可以互换。下面也写一个程序验证一下:

# include <stdio.h>
int main(void)
{
    int a[] = {2, 5, 8, 7, 4};
    int *p = a;
    printf("*(p+3) = %d, *(a+3) = %d\n", *(p+3), *(a+3));
    return 0;
}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

输出结果是:
*(p+3) = 7, *(a+3) = 7

        这时有人说,a 不是指针变量也可以写成“*”的形式吗?只要是地址,都可以用“*地址”表示该地址所指向的内存单元中的数据而且也只有地址前面才能加“*”。因为指针变量里面存放的是地址,所以它前面才能加“*”。
        实际上系统在编译时,数组元素 a[i] 就是按 *(a+i) 处理的。即首先通过数组名 a 找到数组的首地址,首地址再加上i就是元素 a[i] 的地址,然后通过该地址找到该单元中的内容。
        所以 a[i] 写成 *(a+i) 的形式,程序的执行效率会更高、速度会更快。因为在执行程序的时候数组是先计算地址,然后转化成指针。而直接写成指针 *(a+i) 的形式就省去了这些重复计算地址的步骤。


240109_字符串压缩

#include <stdio.h>
void zip( char *p );
int main()
{
    char s[]="Abbbffzh";
    zip(s);
    printf("%s\n", s);
    return 0;
}
/* 请在这里填写答案 */
void zip(char*p){
    char *a=p;//定义*a指针是为了方便赋值,*p指针拿来进行检查,两者共同指向数组s 
    int n;//记录重复字符的个数 
    while(*p!='\0')//当数组不到最后一位时
	{
        n=1;
        while(*p==*(p+n))//当前字符和下一字符相等时,重复字符个数+1 
			n++;
        if(n>=10)//将整形n转化为字符型
		{
            *a++=n/10+'0';
            *a++=n%10+'0';
        }else if(n>=2){
            *a++=n+'0';
        }
        *a++=*(p+n-1);/*将重复的字符放在数字后面,如果不加的话就只有重复的次数而没有字符*/   
        p=p+n;//跳跃到重复字符截止的地方,开始统计下一个字符
    }
    *a='\0';//结束标志
}

240113_scanf()与gets()

  • scanf( )在读取非空白符之前会忽略空白字符(Space、Enter、Tab),读取之后如果遇到空白字符会停止输入,并将其留在缓冲区里。
  • gets( )可以读取空格,但遇到Enter就输入结束,并把这个回车从缓冲区里移走。
  • getchar( )以Enter结束输入,并将其留在缓冲区里;

        为了避免出现上述问题,必须要清空缓冲区的残留数据,可以用以下的方法解决:

方法1:C语言提供了fflush(stdin)函数,用于清空缓冲区,只要在读数据之前先清空缓冲区就可以

方法2:自己取出缓冲区里的残留数据。 scanf("%[^\n]",str) ;,即遇到"\n"结束。'^'含有非的意思、“%[^\n]“即遇到\n结束。如果使用”%[^v]”,那我们输入 “I love you!” ,输出的就是 “I lo” 

方法3:getchar( )可以读走一个残留的空白字符,scanf(" ");可以读走之前最后一个非空白字符后的全部空白字符。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值