C语言 数据结构/函数 模板

重新开始学C了,C++都还没学明白呢。
用惯了C++/Python 回到C很有点不习惯,很多数据结构、函数都莫得了,有以下替代方法

1 字符串(字符数组vs字符指针)

1.1 定义与初始化

在c++中,字符串可以用string,加字符可以直接用“+=”。

但c中只能用字符数组(char a1[]=“123”;)或者字符指针(char* a2=“123”;)(二者可以用strcmp()比较)

//c
char a1[]="123";
char* a2="123";
//strcmp(a1,a2)=0
//a1 is equal to a2

ps:
对于字符指针,需要在一开始就给字符指针申请足够大的空间。字符指针只能初始化一次,之后内容不能变动了。???

//c
char* temp="666";
 
int maxLen=3;
char* temp2=(char *) calloc(maxLen+1,sizeof(char));
strncpy(temp2,temp,maxLen);

(留坑:leetcode 14里,我sumbit了一个答案,字符指针指向的内容竟然可以被改变,测试还通过了,然鹅本地编译过不了,会报错,应该是不能被改变的才对,可能leetcode编译器有点不一样?)

(坑:可信培训里在“不能引用未初始化”的部分里,有一个正确实例:

int *y=(int*)malloc(n*sizeof(int));
if (y==NULL)
	return NULL;
int ret=memset_s(y,n*sizeof(int),0,n*sizeof(int));
//之后再y[i]+=...

这不就是改变了字符指针所值的内容吗???说好的常量呢???守株待大佬解答我的问题)

1.2 赋值

把message看成a
(把message看成a)
所以,对于a1[]是可以后续进行赋值的( eg. a[0]=‘a’; )
对于*a2则不可以(因为指向的是字符串常量!)否则会出现:Cannot access memory。

1.3 函数返回

a1[]是一个局部变量,保存在栈中,函数若返回则消失,而*a2指向的是一个字符串常量,保存在数据区,函数返回不会消失

char * fork_user_name2()
{
    char *name = "veryitman";
    return name;
}
/*
//wrong example
char * fork_user_name()
{
    char name[] = "veryitman";
    return name;
}
//
Xcode: Address of stack memory associated with local variable 'name' returned
Linux Gcc: warning: function returns address of local variable [-Wreturn-local-addr]
*/

1.4 字符数组和字符指针的互转

1.4.1 char [] 转 char *

int main()
{
    char c_str_array[] = "veryitman.com";
    char *p_str;
    p_str = c_str_array;
    printf("p_str: %s\n", p_str);
    return 0;
}

1.4.2 char * 转 char []

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
    char c_str_array[] = "veryitman.com";
    char *p_str = "veryitman.com";
    strncpy(c_str_array, p_str, strlen(p_str));
    printf("c_str_array: %s\n", c_str_array);
    return 0
}
/*
//wrong example
int main()
{
    char c_str_array[] = "veryitman.com";
    char *p_str = "veryitman.com";
    c_str_array = p_str;
    printf("c_str_array: %s\n", c_str_array);
    return 0;
}
*/

这位大佬总结的太妙了: http://www.veryitman.com/2019/05/10/C%E5%87%BD%E6%95%B0%E4%B8%AD%E8%BF%94%E5%9B%9E%E5%AD%97%E7%AC%A6%E6%95%B0%E7%BB%84/.

1.5 substring

c++中有substr()简直不要太好用,离开c++的第n天,想他。
于是我用c写了个。效率啥的肯定不咋样,但看起来肯定 应该是最好懂的5555。(菜鸡的自我安慰)

//改进
char* substr(char *haystack, int index, int len){
    char* res=(char*) calloc(len+1,sizeof(char));//calloc真好用
    int i;
    for (i=0;i<len;i++){
        res[i]=haystack[index+i];
    }
    res[i]='\0';//需要有截断!否则后面temp会不一样
    // char* temp;
    // temp=res;
    // return temp;
    return res;
        
}
/*
char* substr1(char *haystack, int index, int len){
    char res[len+1];
    int i;
    for (i=0;i<len;i++){
        res[i]=haystack[index+i];
    }
    res[i]='\0';//需要有截断!否则后面temp会不一样
    char* temp;
    temp=res;
    return temp;
        
}
*/

1.6 常用函数

1.6.1 字符串比较: strcmp()

C中,指针存的是地址,用==是永远都不等的,可以用库函数strcmp(a,b)(相同则返回0)

区别:C++中 string a,b; 是可以直接用==作比较的

字符数组(char a1[]=“123”;)或者字符指针(char a2=“123”;)*,二者可以用strcmp()比较。

函数详情见:https://www.programiz.com/c-programming/library-function/string.h/strcmp.

1.6.2 int to string

int snprintf(char *str, size_t size, const char *format, …)

函数详情:https://www.runoob.com/cprogramming/c-function-snprintf.html

2 建立哈希/字典

2.1 利用函数

输入值为key,输出值为value
例如: leetcode 13.

//C
int getInt(char c){
    switch(c){
        case 'I':return 1;
        case 'V':return 5;
        case 'X':return 10;
        case 'L':return 50;
        case 'C':return 100;
        case 'D':return 500;
        case 'M':return 1000;
        }
        return 0;
}

2.2 利用数组

举例:leetcode 3. Longest Substring Without Repeating Characters
key: ASCII码
value: 你要保存的东西,注意与初始化的数避开。
比如你要存‘a’在"abc"中的index,初始化的值为-1,‘a’的ASCII码是97,myHash[‘a’]=0; 相当于在数组myHash的第98个位置存了0,

//c
int myHash[128];
memset(myHash,-1,128*sizeof(int));
myHash['a']=0;

参考:https://blog.csdn.net/lv1224/article/details/54137262
关于数组初始化,注意第一个方法只能初始化为0,而且有点编译器(C99 compiler (with support for dynamically sized arrays))会出现报错"Variable-sized object may not be initialized" ,尽量用memset,但是array size需要注意。
在这里插入图片描述

3 栈

顺序栈的实现采用的是数组。

在顺序栈中设定一个随时指向栈顶元素的变量(一般命名为 top ),当 top 的值为 -1 时,说明数组中没有数据,即栈中没有数据元素,为“空栈”;只要数据元素进栈,top 就加 1 ;数据元素出栈, top 就减 1 。

以下举例仅供参考,可以根据实际需求定返回值(设定全局变量以避免多返回值)。

//c
#include <stdio.h>
//元素elem进栈
int push(char* a,int top,char elem){
    a[++top]=elem;
    return top;
}
//数据元素出栈
int pop(char * a,int top){
    if (top==-1) {
        printf("空栈");
        return -1;
    }
    printf("弹栈元素:%c\n",a[top]);
    top--;
    return top;
}
int main() {
    char a[100];
    int top=-1;
    top=push(a, top, 'a');
    top=push(a, top, 'b');
    top=push(a, top, 'c');
    top=push(a, top, 'd');
    top=pop(a, top);
    top=pop(a, top);
    top=pop(a, top);
    top=pop(a, top);
    top=pop(a, top);
    return 0;
}

输出

弹栈元素:d
弹栈元素:c
弹栈元素:b
弹栈元素:a
空栈

参考:http://data.biancheng.net/view/9.html

4 链表

彻底要和C++弄混了 T.T

C中分配空间函数是malloc(size),释放空间是free(),C++中对应的是在这里插入图片描述
new和delete。

int *p=(int *)malloc(sizeof(int));
free p;
//c
struct ListNode{
    int val;
    struct ListNode *next;
};

void printList(struct ListNode* head){
    while (head){
        printf("%d ",head->val);
        head=head->next;
    }
}

int main() {
    struct ListNode *p=(struct ListNode *)malloc(sizeof(struct ListNode));
    struct ListNode *head=(struct ListNode *)malloc(sizeof(struct ListNode));
    
    //init
    head->val=-1;//return head->next
    p=head;
    p->next=(struct ListNode*)malloc(sizeof(struct ListNode));

    //loop
    p=p->next;
    p->val=666;
    p->next=(struct ListNode*)malloc(sizeof(struct ListNode));

    //end
    p->next=NULL;

    printList(head->next);
    return 0;

}

5 数组排序

C语言里只有一个库函数qsort(); 需要自己写个compare配套使用。

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

// qsort 要结合  compare使用
int compare(const void *value1, const void *value2) {
	// 升序 
	return (*(int*)value1 - *(int*)value2);
	//降序
	//return (- *(int*)value1 + *(int*)value2);
}

int main(int argc, char *argv[]) {
	int arr[]= {-1,5,6,2,7,9};

	qsort(arr, 6, sizeof(int), compare);
	// 输出结果
	int i=0;
	for(; i<sizeof(arr)/sizeof(int); i++) {
		printf("%d ", arr[i]);
	}

	return 0;
}

其他排序方式的实现:https://www.cnblogs.com/hexstudio/p/14277954.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值