指针之初学习

1.字符数组在指定位置插入字符;

#include<stdio.h>
#include<string.h>
int main()
{
    char a[100] = {0};			//最好初始化一下
    char s;
    int len_a, num, i;
    printf("please input a string:\n");
    scanf("%s %c%d", a, &s, &num);
//    printf("aaaaaaaaaaaaaa\n");
    len_a = strlen(a);

    for(i = len_a; i >= num; i--)
    {
        a[i + 1] = a[i];
    }
    
   //   printf("bbbbbbbbbb\n");
    a[num] = s;
   //	a[len_a + 1] = '\0'		//不初始化数组中要加'\0'
   //   printf("ccccccccccccc\n");
    printf("%s\n", a);

    return 0;
}

getchar();获取一个字符

段错误(Segmentation),不能访问内存。

可能出现段错误的三种情况;

1、int a[10];访问a[10]可能出现段错误

2、指针分配空间 申请i个字节访问i+1个,会出现段错误

3、没有分配,直接访问地址

调试段错误最常用的方法:

在每个函数段后面输出一串字符如:printf("aaaaaaaaaaaaaa\n");

\n一定要加 不加\n程序结束后一并输出

\n的作用:1.换行

2.刷新缓冲区(把缓冲区中的数据清空,并刷新到屏幕上)

∴printf 能加 \n 就加\n

sleep(1) 停1s

fflush(stdout) 函数的作用也是刷新缓冲区

2.在字符数组中指定开始位置插入字符串

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

int main()
{
	char str[64] = {0}, ptr[32] = {0};
	int num, len_str, len_ptr, i;

	printf("Please input :\n");
	scanf("%s%d%s", str, &num, ptr);
	
	len_str = strlen(str);
	len_ptr = strlen(ptr);

	for (i = 0; i < len_str - num; i++)
	{
		str[len_str - 1 - i + len_ptr] = str[len_str - 1 - i];
	}

	strncpy(str + num, ptr, len_ptr);
		
	printf("%s\n", str);

	return 0;
}

3.有n个人围成一圈,顺序排号,从第一个开始报数(从1到3报数),凡报到3的人退出圈子,问最后最后留下的是原来第几号的那位

#include <stdio.h>

int main()
{
	int num, person;    		//person表示当前的人数
	int k = 0;      		//k用于报数
	int flag[1000] = {0};   	//用于标记是否还在  1 不在  0 在
	int i = 0;                 	 //数组的下标

	printf("Please input a number:\n");
	scanf("%d", &num);

	person = num;

	while (person != 1)
	{
		i++;                      //人的编号
		if (flag[i] == 0)
		{
			k++;
		}
		if (k == 3)
		{
			k = 0;
			flag[i] = 1;    //踢出去
			person--;
		}

		if (i == num)
		{
			i = 0;
		}
	}

	for (i = 1; i <= num; i++)
	{
		if (flag[i] == 0)
		{
			printf("the last one : %d\n", i);
			break;
		}
	}

	return 0;
}

预处理

对#开头的文件处理

种类:

宏定义 #define 预处理做替换

定义常量

定义函数

#include<stdio.h>

#define OUT printf("helloworld\n");		//无参数的宏
#define p(s) printf("abcdefg\n");		//有参数的宏
  		      宏定义的参数没有类型
#define SQR(x) x*x			//宏函数只做简单替换
int main()				此时 		
{					SQR(a+b) = 1 + 2 * 1 + 2 =5							
    int a = 1, b = 2;			     所以写宏函数时多加括号
    OUT;
    p(s);
    printf("%d \n", SQR(a + b));
    return 0;
}

面试题:自定义函数和宏函数的区别

(两个方面来分析,时间和空间)

答:宏函数不占空间,不需要给形参分配空间 优点:节省空间

缺点:1.浪费编译时间

2.没有语法检查,不安全

普通函数优点:有语法检查

缺点:浪费空间

文件包含 #include

#include"" 在当前目录和TC指定的目录中找 自定义的用这个 ''

#include<> 在TC指定的文件目录中 库里面用这个 <>

TC:编译环境

条件编译 #if--#else--#endif等

补充:

static 修饰全局变量 改变变量的作用域 只能在本文件被使用

修饰函数 改变函数的作用域 只能在本文件中被调用

修饰局部变量 改变变量的声明周期,直到程序结束才被释放

函数调用最后释放栈空间,被static修饰的局部变量,存放在数据段

即(静态数据区)

#include<stdio.h>
int add()
{
    static int a = 0;		//输出12345
//    int a = 0;		//输出5个1
    a++;
    printf("%d\n", a);
}

int main()
{
    int i;
    for(i = 0; i < 5; i++)
    {
        add();
    }
    return 0;
}

指针

指针式变量的一种,里面是一个地址,通过这个地址找到要找的数据

实质:单元的地址就是指针的内容

运算符:

& 是取地址的运算符 * 表示指针运算符

#include<stdio.h>
int main()
{
    int *a;
    char *b;    				//都是指针
                				//所有类型的指针 长度都是4字节
    printf("int:%d\n", sizeof(int *));
    printf("char:%d\n", sizeof(char *));
    printf("long:%d\n", sizeof(long *));
    printf("short:%d\n", sizeof(short *));
    printf("double:%d\n", sizeof(double *));
    printf("float:%d\n", sizeof(float *));

    return 0;
}

*的含义

定义时(数据类型 *) 表示后面的变量是一个指针,没有取值的意思

使用时 表示取值 取地址里的值

int *p; *p=&a; ✖✖✖

把a的地址值赋给整型数a 不合理!

指针做参数

#include<stdio.h>

void fun(int *x, int *y)	//如果不传地址,形参改变 实参不变
{				//当i涉及到修改实参内存值的时候,需要传地址
    int tmp = *x;
    *x = *y;
    *y = tmp;
}				

int  main()
{
    int a = 1, b = 2;
    fun(&a, &b);
    printf("a = %d, b = %d\n", a, b);

    return 0;
}

指针和变量

#include<stdio.h>

int main()
{
    int x = 3, y = 0, *px = &x;
    printf("%p\n",px);
    y = *px + 5;
    printf("%d\n", y);			//y = 8
    y = ++*px;
    printf("%d\n", y);			//y = 4
    y = *px++;
    printf("%d\n", y);			//y = 4
    printf("%p\n",px);			//px 比 px 大4个字节

    return 0;
}

(*px)++ 与 *px++区别?

(*p1)++是x的内容加1;

*p1++是先求*p1的值(x),然后再p1++,指向下一个元素,不再指向x;

利用指针实现strcpy函数

#include <stdio.h>

char *mystrcpy(char *str, const char *ptr) 
//char * 返回值(暂时不需要了解)
{
	char *tmp = str;
	/*while (*ptr != '\0')
	{
		*str = *ptr;
		str++;
		ptr++;
	}*/
	while ((*str++ = *ptr++) != '\0');
//先赋值再判断再移动指针
	return tmp;
}

int main()
{
	char str[20] = "helloworld";
	char ptr[20] = "world";

	mystrcpy(str, ptr);

	printf("%s\n", str);
	return 0;
}

NULL 空指针

头文件中宏定义

#define NULL 0

int *p = NULL; 定义空指针

int *p; 野指针 指向一段不能访问的内存

p为指针变量 p=NULL表示空指针,不指向任何变量。

P !=NULL表示p不是空指针;

不同类型与零值比较

int

if(n == 0)或者 if (n != 0)

float

const float EPSINON = 0.00001;

if ((n >= -EPSINON ) && (n <= EPSINON )) 由于精确度

bool类型 c++中才有

if (flag)或者if (!flag)

指针类型

if (n == NULL)或者if (n != NULL)

指针的使用步骤

1.定义指针变量;

2.给指针变量赋地址; ★容易忽略 内存需合法

3.正常使用指针进行运算;

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

int main()
{
#if 0							//条件编译1
	int *p;       //定义一个指针

	printf("%p\n", p);

	*p = 1;       //不合法 不能直接使用

	int a = 1;
	int *q; 
	q = &a;     //给指针赋值

	int *pa;
	pa = q;    //给pa赋值q
#endif
	char *fp;
	fp = (char *)malloc(sizeof(char) * 20);
  				//向操作系统申请空间 连续的空间  堆空间
	if (NULL == fp)
	{
		printf("malloc falure!\n");
	}

	strcpy(fp, "helloworld");

	printf("%s\n", fp);

	free(fp);       //malloc申请的空间不用后释放空间

	return 0;
}

用指针实现字符串反向输出

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

void string_reverse(const char *ptr, char *str)
{
	int len = strlen(ptr), i;

	ptr += (len - 1);

	for (i = 0; i < len; i++)
	{
		*str = *ptr;
		str++;
		ptr--;
	}
}

int main()
{
	char *ptr = "helloworld!";  	
 //ptr指向helloworld字符串 helloworld是常量,不能修改
	char *str = (char *)malloc(sizeof(char) * 64);

	string_reverse(ptr, str);

	printf("%s\n", str);   //打印字符串格式 %s, 参数是字符串的首地址

	return 0;
}

指针和数组

访问数组的方法:下标法和指针法

#include <stdio.h>

int main()
{	
	int i;
	int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};   //数组名a  常指针
	int *p = a;   				//指针p指向数组的第一个元素

	for (i = 0; i < 10; i++)
	{
		//printf("%d ", a[i]);   		//下标法
		//printf("%d ", *(a + i));  		//指针法  
		printf("%d ", *(p + i));  		//指针法
	}
	printf("\n");

	char *q = "helloworld";  //通过数组下标访问指针 就存储空间不一样

	for (i = 0; i < 10; i++)
	{
		printf("%c", q[i]);
	}
	printf("\n");
	return 0;
}

思考:

#include<stdio.h>
int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    int *p1 = (int *)(&a + 1);
    int *p2 = (int *)((int)a + 1);
    int *p3 = (int *)(a + 1);

    printf("%d\n", *p1);		     输出结果:	// 乱码
    printf("%d\n", *p2);				// 辣鸡值
    printf("%d\n", *p3);				// 2

    return 0;
}

判断字符串2是不是字符串1的子串

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

int main()
{	
	int len_str, len_ptr, i;
	char *str = (char *)malloc(sizeof(char) * 32);
	char *ptr = (char *)malloc(sizeof(char) * 32);
	
	printf("Please input :\n");
	scanf("%s%s", str, ptr);

	len_str = strlen(str);
	len_ptr = strlen(ptr);

	if (len_str < len_ptr)
	{
		printf("input error!\n");
		return -1;
	}

	for (i = 0; i < len_str - len_ptr + 1; i++)
	{
		if (strncmp(str + i, ptr, len_ptr) == 0)
		{
			printf("%s 是 %s 的子串\n", ptr, str);
			break;
		}

		if (i == len_str - len_ptr)
		{
			printf("%s 不是 %s 的子串\n", ptr, str);
		}
	}
	
	return 0;
}

指针和字符串

#include<stdio.h>
int main()
{
    char *str[] = {"I love China", "hello", "Nice"}; 	//指针数组
//[]优先级高,str[],所以是数组
//I love China 是指针	指向字符串 I love China 
    printf("%s\n", str[0]);	
    printf("%s\n", str[1]);
    printf("%s\n", str[2]);
//打印字符串 %s		参数:字符串的首地址
    printf("%s\n", str);

    return 0;
}

字符串的赋值方法

#include <stdio.h>

int main()
{
	char *ptr = "helloworld";   //ptr指向hellworld字符串

	char *str;
	str = "helloworld";        //同上

	char a[20] = "helloworld";   //数组a保存helloworld字符串

	char b[20];
	//b = "hellowrold";      //错误  b数组名是常指针
	strcpy(b, "helloworld");  //正确

	return 0;
}

猜你喜欢

转载自blog.csdn.net/zzb_mx/article/details/81211250