C指针 的一些练习
注:此篇是我使用指针敲的一些题目的集成,有一些代码是重复的(挠头)。这样做的目的是进行前后的一些比较和收获一些心得(?)。
关于上一次我上台的题目:
题目:输入十个整数,进行排序。
做法1:(传递指针p)
#include <cstdio>
#include <iostream>
#include <string.h>
using namespace std;
void swap(int *p)
{
int i,j;
int t;
for(i = 1 ; i <= 10; i++)
{
for(j = i + 1; j <= 10; j++)
{
if(*(p + j) < *(p + i))
{
t = *(p + i);
*(p + i) = *(p + j);
*(p + j) = t;
}
}
}
for(i = 1; i <= 10; i++)
{
printf("%d ",*(p + i));
}
printf("\n");
}
int main()
{
int a[10];
memset(a,0,sizeof(a));
int i,j;
int *p;
p = a;
for(i = 1; i <= 10; i++)
{
scanf("%d",&a[i]);
}
swap(p);
return 0;
}
做法2:(传递数组名)
#include <cstdio>
#include <iostream>
#include <string.h>
using namespace std;
void swap(int a[])
{
int i,j;
int t;
for(i = 1 ; i <= 10; i++)
{
for(j = i + 1; j <= 10; j++)
{
if(a[j] < a[i])
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
for(i = 1; i <= 10; i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
int main()
{
int a[10];
memset(a,0,sizeof(a));
int i,j;
for(i = 1; i <= 10; i++)
{
scanf("%d",&a[i]);
}
swap(a);
return 0;
}
链表
有段时间没敲链表了(挠头),重新实现下,发现还是很多地方出错了:(
经过漫长时间的debug,发现一个原因是,在主函数里面定义的整形变量,在函数pdelete里面缺少了对其的定义,编译居然过了(挠头)
写了两遍。贴个最后一次实现的代码吧。
链表的创建,输出,插入和删除
#include <cstdio>
#include <iostream>
#include <stdlib.h>
using namespace std;
struct Node
{
int data;
Node *next;
};
void IniNode(Node *head)
{
head = (Node *)malloc(sizeof(Node));
if(head == NULL)
{
printf("Overflow\n");
exit(1);
}
head -> next = NULL;
head -> data = -1;
}
Node *Creat()
{
Node *head;
IniNode(head);
Node *p1,*p2;
p1 = p2 = head;
while(p1 -> next != NULL || p1 == head)
{
int a = 0;
scanf("%d",&a);
if(a < 0)
{
p1 -> next = NULL;
break;
}
p1 = (Node *)malloc(sizeof(Node));
if(p1 == NULL)
{
printf("Overflow\n");
exit(1);
}
p1 -> data = a;
p2 -> next = p1;
p2 = p1;
}
return head;
}
void output(Node *head)
{
Node *p = head -> next;
while(p != NULL)
{
printf("%d ",p -> data);
p = p -> next;
}
printf("\n");
}
void pinsert(Node *head)
{
Node *p1,*p2;
p1 = p2 = head;
int i_data = 0,num = 0;
scanf("%d%d",&num,&i_data);
int i,j;
for(i = 1; i <= num; i++)
{
p2 = p1;
p1 = p1 -> next;
}
Node *p;
p = (Node *)malloc(sizeof(Node));
if(p == NULL)
{
printf("Overflow\n");
exit(1);
}
p -> next = p1;
p -> data = i_data;
p2 -> next = p;
output(head);
}
void pdelete(Node *head)
{
Node *p1,*p2;
p1 = p2 = head;
int d_num = 0;
scanf("%d",&d_num);
int i,j;
for(i = 1; i <= d_num; i++)
{
p2 = p1;
p1 = p1 -> next;
}
p1 = p1 -> next;
free(p2 -> next); // 勿忘我
p2 -> next = p1;
output(head);
}
int main()
{
Node *head;
head = Creat();
output(head);
pinsert(head);
pdelete(head);
return 0;
}
链表错误小结
- 构建部分:
void IniNode(Node *head)
{
head = (Node *)malloc(sizeof(Node));
if(head == NULL)
{
printf("Overflow\n");
exit(1);
}
head -> next = NULL;
head -> data = -1;
}
Node *Creat()
{
Node *head;
IniNode(head);
Node *p1,*p2;
p1 = p2 = head;
while(p1 -> next != NULL || p1 == head)
{
int a = 0;
scanf("%d",&a);
if(a < 0)
{
p1 -> next = NULL;
break;
}
p1 = (Node *)malloc(sizeof(Node));
if(p1 == NULL)
{
printf("Overflow\n");
exit(1);
}
p1 -> data = a;
p2 -> next = p1;
p2 = p1;
}
return head;
}
**1. **在Creat里面,初始化Node的时候不能置NULL:
Node *head = NULL; // Error.
IniNode(head);
**2. **其次,在构建链表的时候,需要注意p2 始终跟在 p1的后面,起到link的作用。
p1 = (Node *)malloc(sizeof(Node));
···
p1 -> data = a;
p2 -> next = p1; // 这句话不要忘记
p2 = p1;
**3. **while循环条件,我的写法是刚刚开始时将p1 和p2 ,指向头节点。所以循环条件得:
while(p1 -> next != NULL || p1 == head)
否则,开始时
p1 -> next == NULL
就没有办法进入循环进行输入。
- **输出部分: **
void output(Node *head)
{
Node *p = head -> next;
while(p != NULL)
{
printf("%d ",p -> data);
p = p -> next;
}
printf("\n");
}
注意:按照我的写法,开始赋值的时候,需要置p为
head -> next
,否则无法进入循环。
- 插入部分:
void pinsert(Node *head)
{
Node *p1,*p2;
p1 = p2 = head;
int i_data = 0,num = 0;
scanf("%d%d",&num,&i_data);
int i,j;
for(i = 1; i <= num; i++)
{
p2 = p1;
p1 = p1 -> next;
}
Node *p;
p = (Node *)malloc(sizeof(Node));
if(p == NULL)
{
printf("Overflow\n");
exit(1);
}
p -> next = p1;
p -> data = i_data;
p2 -> next = p;
output(head);
}
**1. **for循环条件需要根据p1 和 p2的初始指向确定。
p1 = p2 = head;
···
for(i = 1; i <= num; i++) // <=
{
p2 = p1;
p1 = p1 -> next;
}
否则会导致崩溃,指向错误。
**2. **创立的新结点 同样需要
malloc
语句
Node *p;
p = (Node *)malloc(sizeof(Node));
if(p == NULL)
{
printf("Overflow\n");
exit(1);
}
- 删除部分:
(这里指的是删除结点)
void pdelete(Node *head)
{
Node *p1,*p2;
p1 = p2 = head;
int d_num = 0;
scanf("%d",&d_num);
int i,j;
for(i = 1; i <= d_num; i++)
{
p2 = p1;
p1 = p1 -> next;
}
p1 = p1 -> next;
free(p2 -> next); // 勿忘我
p2 -> next = p1;
output(head);
}
注:和insert一样,需要根据p1 和p2 的初始指向确定循环范围。
- 最后需要释放内存
void pfree(Node *head)
{
Node *p1,*p2;
p1 = p2 = head;
while(p1 -> next != NULL)
{
p2 = p1;
p1 = p1 -> next;
free(p2);
}
if(p1 == head)
free(p1);
}
To improve is to change, to be perfect is to change often.