C 程序步骤中的一些问题
写C 和 C++ 或者 python 还是有很多不同,列举一下常见的基础流程的问题
malloc构建二维数组
以构建一个int dp[n+1][m+1]为例。首先malloc 和 free 要一一对应,第二是 malloc 的大小参数要做数据检查,0字节的长度申请,或者负数长度去申请,负数会被当成一个很大的无符号整数,从而申请内存大小过大导致错误。
#define MAX_M 100
#define MAX_N 500
int **dp = (int**)malloc((MAX_N + 1) * sizeof(int*));
for (int i = 0; i < n + 1; i++) {
dp[i] = (int*)malloc((MAX_M + 1)*sizeof(int));
}
堆上数组的开辟问题
在很早的C语言版本中 使用变量在堆上初始化数组int [m][n]的写法是不被支持的,需要用malloc进行动态构建开辟。
但是C99或者C11版本中,使用变量在堆上初始化数组在后面的编译器是支持的。
int i = 5;
i++;
char test[i];
int i;
scanf("%d", &i);
char test[i];
int m = 3; int n = 2;
int xoe[m][n];
xoe[2][1] = 3;
printf("%d", xoe[2][1]);
// 需要注意的是使用这种方式进行定义的时候不能直接花括号赋初值
// 下面的写法就不行
int i = 5;
char test[i] = {0, 1, 2, 3, 4};
对数组都赋相同初始值
目前对于全部赋0,-1,或者 MAX 值, C实现比较方便,其他的初始化数值不太方便。
最常见的是都赋0 int arr[10] = {0}; 这个容易实现。
那么要是想要都赋 -1 呢? int arr[10] = {-1}; 第一个元素将初始化为提供的值,而其他元素将填充零: 只会把 arr[0]变成 -1,arr[1] 的值是0。
除了循环赋值,就只能用memset进行配置。
int test[10] = {0};
memset(test, -1, sizeof(test));
或者用 0x3f填满,达到构造类似于INT_MAX的功能。例如使用 0x3f进行赋值,stack里面的每个int数值被 初始化为0x3f3f3f3f,即为1061109567。
常用函数
strcpy_s()
strcpy_s(char* dest, size_t numElems, const char* src)
strncpy_s(char *strDest,size_t numberOfElements,const char *strSource,size_t count)
sprintf_s()
int sprintf_s(char *strDest, size_t destMax, const char *format, ...)
memset()
该库函数属于C库函数 。复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。
void *memset(void *str, int c, size_t n)
虽然本意是用于字符串,但是也支持对int初始数组进行赋初值, 一般赋值全为0, 或者用 0x3f填满,达到构造类似于INT_MAX的功能。例如使用 0x3f进行赋值,stack里面的每个int数值被 初始化为0x3f3f3f3f,即为1061109567。
int stack[10];
memset(stack, 0, sizeof(stack)); // memset(stack, 0x3f, sizeof(stack))
for (int i = 0; i < 10; i++) {
printf("%d ", stack[i]);
}
如果是直接进行初始值的定义使用花括号。
int arr[2][3] = { {1,2,3}, {4,5,6}}
memcpy_s ()
memcpy_s(dest, destMax, src, srcLen);
接收数组长度变量的destMax 必须设置为 sizeof(dest) 或者 BUFF_SIZE*sizeof(elementType)。只有当元素数组为字节类型(如char,signed char,unsigned char) 时,sizeof(elementType) 为1,此时可以忽略。
qsort()
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
base -- 指向要排序的数组的第一个元素的指针。
nitems -- 由 base 指向的数组中元素的个数。
size -- 数组中每个元素的大小,以字节为单位。
compar -- 用来比较两个元素的函数。
cmp()会有三种返回值(以qsort为例):
1、返回一个正数:a排在b之后;
2、返回0:a、b相等;
3、返回一个负数:a排在b之前;
#include
#include
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main()
{
int n;
printf("排序之前的列表:\n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
qsort(values, 5, sizeof(int), cmpfunc);
printf("\n排序之后的列表:\n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return(0);
}
解释下比较函数的写法:
在一些函数定义中,const void *a 这类形参,const void *a这是定义了一个指针,a可以指向任意类型的值,但它指向的值必须是常量,在这种情况下,我们不能修改被指向的对象,但可以使指针指向其他对象。void *则为“无类型指针”,void *可以指向任何类型的数据。
后面 *(int*) a 分为两步 (int*) a是把上面的无类型指针转换为 int 型指针, 再前面加上 * 变成 *(int*) a 是进行了一个dereference解引用。
其实传参也可以直接传个 int 类型的指针,不过对于更复杂的情况还是建议 const void*后,在cmp函数内部进行强转。
int cmpfunc(int* a, int* b) {
return *a - *b;
}
对于double类型的比较需要特别注意, 要用比较符号,不能用减号。
double in[100];
int cmp( const void *a , const void *b)
{
return *(double *)a > *(double *)b ? 1 : -1;
}
qsort(in,100,sizeof(in[0]),cmp);
借助 strcmp(str1, str2) 对字符串进行排序
返回值:
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str1 大于 str2。
如果返回值 = 0,则表示 str1 等于 str2。
struct In
{
int data;
char str[100];
}s[100];
//按照结构体中字符串str的字典顺序排序
int cmp ( const void *a , const void *b)
{
return strcmp( (*(In *)a).str , (*(In *)b).str);
}
qsort(s,100,sizeof(s[0]),cmp);
除此之外,qsort 也比较适用于对结构体进行排序。
struct In
{
int x;
int y;
}s[100];
//按照x从小到大排序,当x相等时按照y从大到小排序
int cmp( const void *a , const void *b )
{
struct In *c = (In *)a;
struct In *d = (In *)b;
if(c->x != d->x) return c->x - d->x;
else return d->y - c->y;
}
qsort(s,100,sizeof(s[0]),cmp);
针对二维数组,也可以进行排序,值得注意的是cmp的写法,需要在里面强转(int**)后再解引用,不能直接在入参时候(int**),下面例子里的二维数组形式如下:
people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
int cmp(const void* _a, const void* _b) {
int *a = *(int**)_a, *b = *(int**)_b;
return a[0] == b[0] ? b[1] - a[1] : a[0] - b[0];
}
int** reconstructQueue(int** people, int peopleSize, int* peopleColSize, int* returnSize, int** returnColumnSizes) {
qsort(people, peopleSize, sizeof(int*), cmp);
int** ans = malloc(sizeof(int*) * peopleSize);
*returnSize = peopleSize;
*returnColumnSizes = malloc(sizeof(int) * peopleSize);
memset(*returnColumnSizes, 0, sizeof(int) * peopleSize);
for (int i = 0; i < peopleSize; ++i) {
int spaces = people[i][1] + 1;
for (int j = 0; j < peopleSize; ++j) {
if ((*returnColumnSizes)[j] == 0) {
spaces--;
if (!spaces) {
(*returnColumnSizes)[j] = 2;
ans[j] = malloc(sizeof(int) * 2);
ans[j][0] = people[i][0], ans[j][1] = people[i][1];
break;
}
}
}
}
return ans;
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/queue-reconstruction-by-height/solution/gen-ju-shen-gao-zhong-jian-dui-lie-by-leetcode-sol/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
bsearch()
进行二分搜索的函数,使用前对base里面的数组需要进行排序。
void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *))
参数
key -- 指向要查找的元素的指针,类型转换为 void*。
base -- 指向进行查找的数组的第一个对象的指针,类型转换为 void*。
nitems -- base 所指向的数组中元素的个数。
size -- 数组中每个元素的大小,以字节为单位。
compar -- 用来比较两个元素的函数。
如果查找成功,该函数返回一个指向数组中匹配元素的指针,否则返回空指针。
以字符串数组为例:
int cmp(cons void *a, const void *b) {
char *a0 = *(char **)a;
char *b0 = *(char **)b;
return strcmp(a0, b0);
}
char *retStr[3] = {"ab", &#