【C语言学习笔记】基础语法及各类bug总结

注:此blog为个人学习C语言总结之用,不定时补充更新,欢迎收藏与留言~

1.出现程序停止运行的原因:

情况1:
错解:

scanf("%d%d",a,b);

运用输入函数scanf时,a,b前未加取地址符&。

正解:

scanf("%d%d",&a,&b);

情况2:

二维或三维数组开的太大导致空间不够,程序无法运行!!!
比如:data[500][500]这个数量级我的vscode就带不动了,目测三维数组只能开100左右。
但是在各大刷题网站比如洛谷,PTA,leetcode上提交程序时可以开大一点,虽然你自己电脑带不动,但是各大平台的测评系统是可以的。(限制内存另说哈)

2.字符串与整型变量前后输入时:

主函数里有这样一段:

    int sum;
    int a,b;
    char c;
    scanf("%d%d",&a,&b);
    scanf("%c",&c);
    printf("%c",c);

    sum=a+b;
    printf("%d",sum);

若这样输入,那么你会发现,在输完a,b的值后习惯性按下回车开始输入c的值,却发现屏幕上已经显示了sum,说明此时程序已经越过输入c的那一行了。

3 4//输入

//输出

7

细心的朋友会发现,此时c的值实际上是'\n'
正解:

    int sum;
    int a,b;
    char c;
    scanf("%d%d\n",&a,&b);//在输入a,b之后加一个回车
    scanf("%c",&c);
    printf("%c",c);

    sum=a+b;
    printf("%d",sum);

3.数组输入时:

错解:

   int map[20][20];
    for(k=0;k<edge_num;k++)
    { 
        //scanf("%d%d",&i,&j);
        scanf("%d%d%d",&i,&j,&map[i][j]);
    }

正解:

    int map[20][20];
    for(k=0;k<edge_num;k++)
    { 
        scanf("%d%d",&i,&j);
        scanf("%d",&map[i][j]);
    }

也许三个数同一行同时输入时,输入的数字还留在缓冲区,所以计算机没办法确定最后一个数组的下标。

4.#define用法

错解:

#define INF 1000000; 

正解:(不能有分号!!!)

#define INF 1000000

5.malloc用法

详见:【c语言】malloc函数详解

int* p;
p = (int *) malloc (sizeof(int));
int **a;
a  = (int **) malloc(sizeof(int *) * r);//注意申请的指针格式

6.指针的空间分配

普通变量只要定义了之后就自动分配了储存空间

int a;

但是指针变量定义之后一定要记得分配内存空间!!!

Graph *g
g= (Graph *)malloc(sizeof(struct Graph));

7.结构体可以直接交换

比如这样一个结构体

typedef struct{
	int vex1;                     //边的起始顶点
	int vex2;                      //边的终止顶点
	int weight;                    //边的权值
}Edge;
Edge arr[SIZE];

想要交换arr[low]&arr[high]时:
不需要这么麻烦:

void swap(Edge arr[],int low,int high)
{
   
    int t1;
    t1 = arr[low].vex1;
    arr[low].vex1 = arr[high].vex1;
    arr[high].vex1 = t1;
     
    int t2;
    t2 = arr[low].vex2;
    arr[low].vex2 = arr[high].vex2;
    arr[high].vex2 = t2;

    int weight;
    weight = arr[low].weight;
    arr[low].weight = arr[high].weight;
    arr[high].weight = weight;
    

}

只需要:

void swap(Edge arr[],int low,int high)
{
    Edge temp;
    temp = arr[low];
    arr[low] = arr[high];
    arr[high] = temp;
   
}

8.vscode中函数里用形参作为函数中数组长度可能出现的问题

比如这样写时:

int Harry(int A[][SIZE],int n)
{
    int i,j;
    int max[n];
    int MIN;
    int tag;
   
}

最好在定义数组之前写上:

#define MAXSIZE 1000000

这样就可以不需要用到形参中的n作为数组长度了(这并不能从根本上解决空间浪费的问题,但至少这一步函数可以正常调试了[vscode运行这一步不会出问题],如果有好的方法,还望告知,谢谢!)

int Harry(int A[][SIZE],int n)
{
    int i,j;
    int max[MAXSIZE];
    int MIN;
    int tag;
   
}

9.strcpy-param-overlap

这个问题为个人的小众问题
STACK_1190_反转每对括号间的子串


char* reverse(char* str,int left,int len)
{
    int right ;
 //  ........对传入参数字符串str做了改动
 //  由于整个函数的参数都是传指针,所以此函数应该改为void类型即可满足要求,如果要用另一个变量再储存返回值呢?

    str[left] = '.';
    str[right] = '.';

    return str;//返回的是一个地址

    char* res = malloc(sizeof(char)*2001);// 那么我们必须再申请一块空间!
    strcpy(res,str);

    return res;//返回一定要为另一个地址,否则函数类型必须设为空函数!

}

如果上述函数返回一个相同的地址,那么会有大问题!

char* temp = reverse(s,i,len);
               //此时temp的地址是和s相同的
               strcpy(s,temp);//不能把两个相同的地址再次赋值(temp和s地址完全相同)

此操作非法!!!
不能对两个相同的地址做strcpy操作!
AddressSanitizer: strcpy-param-overlap: !

10.堆溢出
堆内存溢出heap-buffer-overflow on address

11.函数参数写法

 int len;
     int res = evalRPN( convert(infix,13,&len),len);

这种写法是有问题的,因为编译这一行的时候len的大小是未知的,不会先通过第一个参数里函数的调用确定len的值,而是同时对两个参数进行编译,所以如果这样写,在调用evalRPN函数时len为乱码值。
我们应该改成下面这样的写法:

 int len;
   
     char** postfix = convert(infix,13,&len);
     int res = evalRPN(postfix,len);

你可能感兴趣的:(C)