重新开始学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)
所以,对于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;
}
*/
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;
}