【C语言】刷题知识点总结

char * 与 char **

char * :是一个保存字符串首地址的指针变量
char**:为二级指针,是一个指向指针的指针,但是具体的意义还需要再探讨

void EnCnt(int len, int *cnt1, char **tmp)//char **tmp是什么意思,int *cnt1又是什么意思
{
    for(int j = 0; j < len; j++)
    {
        for(int i = 0; i < NUM_11; i++)
        {
            if(strcmp(tmp[j], EnglishNum[i]) == 0)
            {
                (*cnt1)++;    //数英语数字个数
            }
        }
    }
}

strcmp()字符串比较函数

用在字符串的qsort中,
用于比较两个字符串并根据比较结果返回整数。基本形式为strcmp(str1,str2),若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数

strtok() 分解字符串为一组字符串

char *strtok(char s[], const char *delim);

实例:

#include <string.h>
#include <stdio.h>
 
int main () {
   char str[80] = "This is - www.runoob.com - website";
   const char s[2] = "-";
   char *token;
   
   /* 获取第一个子字符串 */
   token = strtok(str, s);
   
   /* 继续获取其他的子字符串 */
   while( token != NULL ) {
      printf( "%s\n", token );
    
      token = strtok(NULL, s);
   }
   
   return(0);
}

让我们编译上述程序,将获得以下结果:
在这里插入图片描述

s为要分解的字符串,delim为分隔符字符(如果传入字符串,则传入的字符串中每个字符均为分割符)。首次调用时,s指向要分解的字符串,之后再次调用要把s设成NULL。

例如:strtok(“abc,def,ghi”,“,”),最后可以分割成为abc def ghi.尤其在点分十进制的IP中提取应用较多。

strtok_s 有问题

strtok_s(char *strToken, const char *strDelimit, char **context)

char *contx = NULL;
char *tmp;
// 2019-01-01 00:00:00.004
tmp = strtok_s(str, “-”, &contx);
strtok_s(char *strToken, const char *strDelimit, char **context)

参数之中是char **context 为什么tmp = strtok_s(str, “-”, &contx);中变成了 &contx

strtol() 字符串转数字

将str字符串转变成long int类型的数据

long int strtol(const char *nptr,char **endptr,int base);

参数:nptr:想要转换的字符串

endptr:str遇到哪个字符截止扫描 没有设置为NULL

base:nptr代表的进制数,例如2, 10,8,16等

使用后强转为int可完成二进制到十进制的转换

static int BinaryToDecimal(char *binaryString)
{
    int res;
    res = (int)strtol(binaryString, NULL, 2);
    return res;
}

int main(void)
{
    char binaryString[STR_LEN];
    if (scanf_s("%s", binaryString, STR_LEN) != 1) { return -1; }
    int output = BinaryToDecimal(binaryString);
    printf("%d", output);

    return 0;
}

5.qsort中cmp的各种写法

注意 cmp函数一定要写成下列形式,否则会报错

int cmp(const void *a, const void *b)

如果返回负数,说明a排在b前面

如果返回正数,说明a排在b后面

如果返回0,说明a和b无先后关系

所以如果要从小到大排则返回 ((int)a) - ((int)b)

如果从大到小则返回 ((int)b) - ((int)a)

5.1 数组排序

5.1.1 一维数组

例子1,给出一个数组,从小到大升序排列

arr[5] = {1, 3, 2, 5, 4};
int cmp(const void *a, const void *b)
{
    int A = *(int*) a;
    int B = *(int*) b;

    if (A > B) {// 升序
        return 1;
    }
    else {
        return -1;
    }
}
qsort(arr, (size_t)arrLen, sizeof(int), cmp);

5.1.2 二维数组

对{{1,3}, {1,2}.{1,6},{2,10},{5,7}} 进行排序

int cmp (const void *a, const void *b) //二维数组
{
    int *left = *(int **)a;
    int *right = *(int **)b;
    if (left[0] != right[0]) {
        return left[0] - right[0];
    }
    return left[1] - right[1];

}

int main(void)
{
    int num[4][2] = {{1,3},{2,6},{8,10},{15,18}};
    int intervalsSize = 4;
    int **intervals = (int **)malloc(sizeof(int*) * intervalsSize);//按照最大的区间分配
    for (int i = 0; i < 4; i++) {
        int * tmp = (int *)malloc(sizeof(int) * 2);
        tmp[0] = num[i][0];
        tmp[1] = num[i][1];
        intervals[i] = tmp;
    }
    
    qsort(intervals, 4, sizeof(int*), cmp);
    
    for (int i = 0; i < 4; i++) {
        printf("%d,%d ", intervals[i][0], intervals[i][1]);
    }
    return 0;
}

5.2 结构体排序

例子2,给出一个结构体,里面有长度和优先级,以优先级为主按升序排列,优先级相同时按长度升序排列

typedef struct o {
    int length;
    int pri;
}Tel;
int cmp(const  void *a, const void *b)//cmp的参数一定要写成const void *a 否则会报错
	{
    Tel A =*(Tel *)a;//这么处理的意义是啥  强转
    Tel B =*(Tel *)b;//这么处理的意义是啥
    if(A.pri > B.pri){
        return 1;
    }
    else if (A.pri < B.pri) {
        return -1;
    }
    else {
        return A.length >= B.length ? 1 : -1;
    }
}
num[5] = {50, 20, 30, 10, 50};
pri[5] = {2, 2, 1, 3, 1};
 Tel *buf = (Tel *)malloc(sizeof(Tel) * num);//为什么要用Tel *buf,还要注意C语言每次使用XX前可以malloc申请内存  也可以是结构体数组
 /*或者这样写*/
 Tel buf[num];
 for (int i = 0; i < num; i++) {
        buf[i].length = bill[i];
        buf[i].pri = pri[i];
    }
qsort(buf, (size_t)num, sizeof(buf[0]), cmp);//记录一下qsort是如何使用的

strncpy_s()字符串复制

#define STR_BUF_LEN 101

char temp[STR_BUF_LEN];
inputStr[STR_BUF_LEN] = "a-132b";
int i = 2;
int count = 3;
strncpy_s(temp, STR_BUF_LEN, inputStr + i, count);
temp[count] = "\0" //其实不设置temp[count]及其之后也等于‘\0’
// temp = “132”

上述函数的意义是从inputStr的第2个字符开始截取3个字符,包括第二个字符

fabs( ) 求浮点数的绝对值

double fabs(double x)
int StrCheck(char *strs, char *out)//函数参数里 *strs是什么意思
{
/*handle*/
}
while (*strs == ' ') { // 语句里*str是什么意思
        strs++; // str++又是什么意思
    }
 *out++ = (char)tolower(*strs++); // *和++的优先级

*str 和 **str

isalpha()

if (!isalpha(*strs)) { //判断strs的首字母是否为英文字母
        return -1;
    }

判断字符ch是否为英文字母,若为英文字母,返回非0(小写字母为2,大写字母为1)。若不是字母,返回0

isdigit()

if (!isdigit(*strs)) { //判断strs的首字母是否为英文字母
        return -1;
    }

若参数c为阿拉伯数字0~9,则返回非0值,否则返回0

tolower()

功能是把字母字符转换成小写,非字母字符不做出处理

 *out++ = (char)tolower(*strs++); // 记录一下tolower

再看一下qsort和cmp的用法

int cmp(const void *a, const void *b) {
    int ret;
    ret = strncmp((char *)a, (char *)b, BUF_LEN); // 为啥是 BUF_LEN,另外 需要看一下(char *)转换对不对 strncmp是啥意思
    if (ret == 0) {
        *(char *)b = '\0'; // 转换看一看
    }
    return ret;
}
 qsort(s, n, sizeof(char) * BUF_LEN, cmp);

申请数组的3种方式

int a[10]; 成员数量为10(固定)

int tmp[10] = {0};

malloc

int * tmp = (int *)malloc(a1Len * a2Len * sizeof(int)); 成员数量为a1Len(变量)

calloc

int *result = (int *)calloc(1,  (a1Len * a2Len) * sizeof(int));

malloc 和 calloc 的区别

函数malloc()和calloc()都可以用来动态分配内存空间,但两者稍有区别。

malloc()函数有一个参数,即要分配的内存空间的大小:
void *malloc(size_t size);
calloc()函数有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小。
void *calloc(size_t numElements,size_t sizeOfElement);

如果调用成功,函数malloc()和函数calloc()都将返回所分配的内存空间的首地址。
函数malloc()和函数calloc()的主要区别是前者不能初始化所分配的内存空间,而后者能,但只能初始化为0
如果由malloc()函数分配的内存空间原来没有被使用过,则其中的每一位可能都是0;反之,如果这部分内存曾经被分配过,则其中可能遗留有各种各样的数据。也就是说,使用malloc()函数的程序开始时(内存空间还没有被重新分配)能正常进行,但经过一段时间(内存空间还已经被重新分配)可能会出现问题。
函数calloc()会将所分配的内存空间中的每一位都初始化为零,也就是说,如果你是为字符类型或整数类型的元素分配内存,那麽这些元素将保证会被初始化为0;如果你是为指针类型的元素分配内存,那麽这些元素通常会被初始化为空指针;如果你为实型数据分配内存,则这些元素会被初始化为浮点型的零。

例子

以1812.矩阵列的最大值中的最小值为例

int cmp(const void *a, const void *b) 
{
    return *(int *)a < *(int *)b;
}

int GetTheMinWithColMaxs(int **matrix, int n, int m)
{
    // 在此添加你的代码
    int lie_Max = INT_MIN;
    // 申请一个大小为m的数组A
    int *tmp = (int*)malloc(m * sizeof(int));
    // 遍历矩阵,把每列的最大值保存到数组A中
    for (int j = 0; j < m; j++) {
        for (int i = 0; i < n; i++) {
            if(matrix[i][j] > lie_Max) {
                lie_Max = matrix[i][j];
            }
        }
        tmp[j] = lie_Max;
        lie_Max = INT_MIN;
    }
    // 把数组A排序
    qsort(tmp, m, sizeof(int) * m, cmp);
    // 输出最小值
    return tmp[0];
    
}

这里申请数组有问题,数组的初始化不清楚,导致排序后的结果错误,体现为某些数组成员被随机初始化了

直接

int tmp[10] = {0};

即可申请长度为10,内容为0的数组。

数组初始化的几种方式

memset_s

memset_s(void *dest, size_t destMax, int c, size_t count)

参数

参数意义
dest指向要填充的对象的指针
destMax目标数组的大小
c填充字节
count要填充的字节数

int a[10] = {0}

int a[10] = {0};

浮点数转化为整数

1.直接强转

float f = 1.5;
int a;
a = (int)f;
NSLog("a = %d",a);

输出结果是1。(int)是强制类型转化,丢弃浮点数的小数部分。

2.通过强制类型转换四舍五入

float f = 1.5;
int a;
a = (int)(f+0.5);
NSLog("a = %d",a);

输出结果是2。

手撸reverse() 字符串反转

void reverse (char *s, int start, int end) {
    while (start < end) {
        char temp = s[start];
        s[start++] = s[end];
        s[end--] = temp;
    }
}

用法: 反转字符串中的单词顺序
先反转整个字符串,再反转每个单词

char * strings = "hello world"
int len = strlen(strings);
// 1.反转整个字符串
reverse(strings, 0, len - 1);
// 2.反转每个单词
for (int i = 0; i < len; i++) {
        int j = i;
        while (j < len && strings[j] != ' ') {
            j++;
        }
        reverse(strings, i, j - 1);
        i = j;
    }

fmax, fmin

1.含义
fmax, fmin 函数用于C语言快速比较两数大小,头文件为math.h
作用是:

返回两个浮点参数中较大的一个
2.举例

#include <stdio.h>
#include <math.h>
 
int main(void)
{
    printf("fmax(2,1)    = %f\n", fmax(2,1));
    printf("fmax(-Inf,0) = %f\n", fmax(-INFINITY,0));
    printf("fmax(NaN,-1) = %f\n", fmax(NAN,-1));
}

输出:

fmax(2,1)    = 2.000000
fmax(-Inf,0) = 0.000000
fmax(NaN,-1) = -1.000000

安全函数

memcpy_s()

errno_t memcpy_s(
   void *dest,
   size_t destMax,
   const void *src,
   size_t count 
);

memcpy_s的四个参数命名其实是有迷惑性的,个人的理解是,dest-目标地址,destMax-目标地址的字节数(可使用sizeof获取),src-源地址,count-需要拷贝的源字符个数(可使用sizeof获取)。

注意一点:destMax必须大于等于count,否则拷贝将出现中断。

memset_s()

errno_t memset_s(
   void *dest,
   size_t destMax,
   const void *src,
   size_t count 
);

dest-目标地址,destMax-目标地址的字节数(可使用sizeof获取),src-源地址,count-需要拷贝的源字符个数(可使用sizeof获取)

strcat_s()连接两个字符串的函数

只能往字符串后边加字符串

errno_t strcat_s(char *Destination, size_t SizeInBytes ,const char *Source);
Destnation 被添加字符串
SizeInBytes 字节(:内容大小不能超过这个数)
Sourse添加的字符串

strcat_s(str1 , 1024 ,str2);
运行后str1→str1str2;

scanf_s

int sscanf_s( const char *buffer, const char *format [, argument ] ... );

sprintf_s

C语言没有itoa()函数 需要用sprintf_s函数 去格式化输出
需要去看

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值