【课业】C语言一点点笔记

11月13日

c语言自带的qsort

#include<stdio.h>
#include<stdlib.h>
int comp(const void *a,const void *b)//用来做比较的函数。
{
return *(int*)a-*(int*)b;
}
int main()
{
int a[10] = {2,4,1,5,5,3,7,4,1,5};//乱序的数组。
int i;
qsort(a,10,sizeof(int),comp);//调用qsort排序
return 0;
}

从小到大排 b-a就是从大到小了


memset函数

# include <stdio.h>
# include <string.h>
int main(void)
{
    int i;  //循环变量
    char str[10];
    char *p = str;
    memset(str, 0, sizeof(str));  //只能写sizeof(str), 不能写sizeof(p)
    for (i=0; i<10; ++i)
    {
        printf("%d\x20", str[i]);
    }
    printf("\n");
    return 0;
}

11月16日

输出最后多个换行一般会影响结果吗?否。


多组字符串输入一般还是用二维数组比较好。
但也不是绝对的,比如内存分配器那道题


数组实现栈

char contents[SIZE];
int top=0;
void push(char i){
    contents[top++]=i;
}
char pop(void){
    if(top==0){
        printf("Empty\n");
    }
    else{
        return contents[--top];
    }
}

11月18日
寻找比大的2的幂

int two(int x){
    int ans=-1;
    for(int i=1;;i*=2){
        ans++;
        if(i>=x){break;}
    }
    return ans;
}

计算2的幂
1<<n就行了


11月19日
malloc函数的使用

    char *b;
    a=malloc(N);
    b=malloc(N);

————————————————————————————————————————
IEEE754 十六进制转十进制 单精度浮点

#include <math.h>
float f(int number)
{
    int sign = (number & 0x80000000) ? -1 : 1;//这里的&是按位与运算符。这里是判断符号位
    int exponent = ((number >> 23) & 0xff) - 127;//先右移操作,再按位与计算,出来结果是30到23位对应的e
    float m = 1 + ((float)(number & 0x7fffff) / 0x7fffff);//将22~0转化为10进制,得到对应的x
    return sign * m * pow(2, exponent);
}
int main()
{

    int a;
    scanf("%x",&a);
    float result = f(a);
    printf("%f", result);
    return 0;
}

如果只是为了输出正确的值,请见内存解释器
————————————————————————————————————————————
11月20日

int search(int x){
    int l=0,r=n-1;//范围是k[l]到k[r]
    while(r>=0&&l<n&&l<=r){
        int i = (l+r+1)/2;
        if(k[i]==x){
            return 1;
        }
        else if(k[i]<x){
            l=i+1;
        }
        else{
            r=i-1;
        }
    }
    return 0;

}

此为二分法搜索,在此之前必须从小到大排序
——————————————————————————————

void swap(int *a,int *b){
    int x=*a;
    *a=*b;
    *b=x;
}

void sort(int l,int a[]){
    for(int i=0;i<l-1;i++){
        for(int j=0;j<l-i-1;j++){
            if(a[j]>a[j+1]){
                swap(&a[j],&a[j+1]);
            }
        }
    }
}

此为冒泡排序


几个string.h里面的函数

char *strcpy(char *s1,const char *s2){
    char *p=s1;
    while (*s1++ = *s2++);
    return p;
}
char *strcat(char *s1,const char *s2){
    char *p = s1;
    while(*p){
        p++;
    }
    //这个地方不应该写为while(*p++)因为这会导致p多走一位
    //正如数学中开闭区间容易出错,编程中的端点位置也是很容易出问题的
    while(*p++ = *s2++)
        ;
    return s1;
}

在倒水那道题里一直用的比较
#define min(a, b) ((a) < (b) ? (a) : (b))
既不需要反复写又不需要定义函数
宏是很简洁的写法


字符反转和素数检验两个函数太常用了。

    int ans = 0;
    while (n) {   翻转数字
        ans = ans * 10 + n % 10;
        n/=10;
    }
    return ans;
}

这个的想法是什么呢?
1234换为4321,实际是个什么过程?
4321=(410+3)10+2)*10+1
课本上提到,这种方法可以用在一切多项式函数身上。

int check(int n) {
    for (int i = 2; i * i  n; i)
        if (n % i  0)  如果有因式,直接返回 “非素数”
            return 0;
    return 1;
}

while(scanf("%s",&s)!=EOF){
...
}

是个很好的读入方式
clion请在调试时键入ctrl+D以输入EOF


#include <stdlib.h>
struct node{
    int n;
    struct node* next;
};
struct node* addtolist(int n,struct node*list){
    struct node*newnode= malloc(sizeof(struct node));
    newnode->n=n;
    newnode->next=list;
    return newnode;
}
struct node* deletefromlist(int n,struct node*list){
    struct node* cur,*prev;
    for(cur=list,prev=NULL;cur!=NULL&&cur->n!=n;prev=cur,cur=cur->next){

    }
    if(cur==NULL)return list;
    if(prev==NULL)list=list->next;
    else
        prev->next=cur->next;
    free(cur);
    return list;
}
int main(){
    struct node* p;
    struct node* first = NULL;
    first = addtolist(114514,first);
    first = addtolist(1919810,first);
    for(p=first;p!=NULL;p=p->next){
        printf("%d\n",p->n);
    }
    first = deletefromlist(1919810,first);
    for(p=first;p!=NULL;p=p->next){
        printf("%d\n",p->n);
    }
    return 0;
}


//链表最基本的操作,这里的addtolist使用的是头插法

今天学的有点多。。。
有序链表,函数指针,函数数组,太妙辣

受限指针。指针的指针。都是特殊情况下的妙计。


int (*p) [10] = malloc(sizeof(int)*200);
这种一般都是对二维数组的某一列进行操作。p是一个指针,指向一个10元数组,也就是每一行有10个元素,共有20列
p++就会到下一行的同一列。


位运算系统讲解

i&(1<<j):读取i的第j位
i &= ~(1<<j):把i的第j位设为0
i |= (1<<j):把i的第j位设为1
同理可以进行多位操作,比如i&(0x0070),0x0070的第4到第6位都是1,所以这是在读取i的第4到6位
异或可以用来加密。abb=a,b就是那个密钥,ab就是密文。


期末冲刺

1.复习过往的oj,并且回忆、思考当时遇到的问题
2.回忆经典算法
3.回顾经典函数(准备笔试)


如果不是ysy问我,这种代码我是看都不看的。。。
不过的确学会了点东西。
应该是输出011101111,EF
首先把s1字符串每个字符对应的数字转化成二进制,3 5 7->011 101 111,合起来存到了s2里,然后s2的011101111代表的十进制数转化成十六进制数存进s3。如果是我写的话,我会把11101111整体直接转化成十六进制
但它这段代码是把十六进制每四位划分开,化成了1110;1111,1110的十六进制是E,1111的十六进制是F,把这两个拼起来就是EF,恰好是11101111的十六进制。这本质其实是16=2^4

#include<stdio.h>
#include<string.h>
#include<math.h>
void conv(char s1[],char s2[],char s3[]){
    char*p,*p1,c;int j,t;
    p=s2;
    for(;*s1!='\0';s1++){
        t=*s1-'0';
        p+=2;
        for(j=0;j<3;j++){
            *p=t%2+'0';
            p--;t/=2;}
        p+=4;
        }
    *p='\0';
    p=s2+ strlen(s2)-1;
    p1=s3;
    for(t=0,j=0;p>=s2;p--){
        t+=(*p-'0')*(int)pow(2,j++);
        if(t!=0&&(j%4==0||p==s2)){
            if(t<10)*p1=t+'0';
            else *p1=t-10+'A';
            j=0;t=0;p1++;
        }
    }
*p1='\0';
    for(p1--;s3<p1;s3++,p1--){
        c=*s3;*s3=*p1;*p1=c;
    }

}
int main(){
char s1[]="357",s2[10],s3[5];
    conv(s1,s2,s3);
    printf("%s,%s\n",s2,s3);
}
posted @ 2023-01-30 11:48  藤君  阅读(104)  评论(0)    收藏  举报