C语言入门2-数据类型、运算符和表达式

变量命名

命名规范

  • 只能由字母(含"_")和数字组成;
  • 首字母不能是数字;
  • 不能与关键字重名,例如floatdoubleif等。

注意事项

  • 不使用"_"开头,因为很多库函数这样命名,容易冲突;
  • 区分大小写;
  • 变量名使用小写字母,符号常量使用大写字母;
  • 局部变量使用短变量名,全局变量使用长变量名。

数据类型

基本数据类型

  • char 单字节
  • short 一般为双字节
  • int 一般为四个字节
  • long 一般为八个字节
  • float 单精度
  • double 双精度

常量

整型常量

  • 1234 int类型
  • 1234L或1234l long类型

浮点型常量

  • 123.4或1e-2(0.01)double类型
  • 123.4f或123.4F float类型
  • 123.4L long double类型

八进制和十六进制常量

  • 037 八进制
  • 0x1f或0X1F 十六进制

字符常量

  • ‘0’

常用符号常量表:
在这里插入图片描述
举例:编写一个统计字符串的字符数的函数。

int strlen(char str[]) {
    int i;
    
    i = 0;
    while (str[i] != '\0')
        ++i;
    return i;
}

枚举常量

int main() {
    enum boolean {NO = 0, YES = 1};

    enum boolean flag = NO;

    printf("%d\n", flag);
}

变量声明

第一种方式:

int  lower, upper, step;
char c, line[1000];

第二种方式:

int  lower;
int upper;
int step;
char c;
char line[1000];

第三种方式,声明式赋值:

char  esc = '\\';
int   i = 0;
int   limit = MAXLINE+1;
float eps = 1.0e-5;

使用const关键字声明不变量:

const double e = 2.71828182845905;
const char msg[] = "warning: "; 
// 还用用在函数的参数上
int strlen(const char[]);

算术运算符

二元运算符

  • + 加
  • - 减
  • * 乘
  • / 除
  • % 取模
    举例:判断年份是否为闰年。
int main() {
    int year = 2011;

    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
        printf("%d is a leap year\n", year);
    else
        printf("%d is not a leap year\n", year);
}

关系和逻辑运算符

关系运算符

> >= < <= == !=

注意:因为算术运算符优先级高于关系运算符,所以i < lim - 1会被视作i < (lim - 1)
逻辑运算符

  • && 且
  • || 或
  • ! 取反

类型转换

隐式类型转换(自动类型转换)

  • 当不同数据类型的操作数参与运算时,编译器会自动将它们转换为同一类型,以便于执行运算。
  • 转换规则通常是基于操作数的数据范围和精度,较小的数据类型会被转换为较大的数据类型。
  • 例如,char 类型和 int 类型相加时,char 类型通常会被转换为 int 类型。

显式类型转换(强制类型转换):

  • 使用强制类型转换运算符 (type) 来明确指定将一个类型的值转换为另一种类型。
  • 程序员需要在代码中明确写出转换的类型,以确保转换的意图是清晰的。
  • 例如,(int)3.14 将 double 类型的 3.14 转换为 int 类型,结果是 3。

举例
将字符串转换为整数。

#include <stdio.h> // 引入标准输入输出库,用于printf函数

// 函数声明:将接收一个字符串s,并返回其数值形式
int atoi(char s[]);

int main(void) {
    char s[] = "1234"; // 定义一个字符串数组s,并初始化为"1234"
    printf("%d\n", atoi(s)); // 调用atoi函数,并将结果打印出来
}

// 函数定义:实现字符串转换为整数
int atoi(char s[]) {
    int i, n; // 定义循环计数器i和数值n

    n = 0; // 初始化数值n为0
    // 循环遍历字符串s,直到遇到非数字字符或字符串结束
    for (i = 0; s[i] >= '0' && s[i] <= '9'; i++) {
        // 将字符转换为数值并累加到n上
        n = 10 * n + (s[i] - '0');
    }
    return n; // 返回计算得到的数值
}

在循环中,通过 s[i] - ‘0’ 将字符转换为相应的整数值。例如,字符 ‘5’ 转换为整数 5。
练习

  1. 编写一个函数 htoi(s),将一串十六进制数字(包括可选的 0x 或 0X)转换为其等效的整数值。
#include <stdio.h> // 引入标准输入输出库,用于printf函数

// 函数声明:将接收一个表示十六进制数的字符串s,并返回其数值形式
int htoi(char s[]);

int main(void) {
    char s[] = "0x1af"; // 定义一个字符串数组s,并初始化为"0x1af"
    printf("%d\n", htoi(s)); // 调用htoi函数,并将结果打印出来
}

// 函数定义:实现十六进制字符串转换为十进制整数
int htoi(char s[]) {
    int i, n; // 定义循环计数器i和数值n

    n = 0; // 初始化数值n为0
    // 从字符串的第三个字符开始循环遍历(跳过前缀"0x")
    for (i = 2; 
         (s[i] >= '0' && s[i] <= '9') || 
         (s[i] >= 'a' && s[i] <= 'z') || 
         (s[i] >= 'A' && s[i] <= 'Z'); 
         i++) {
        // 根据字符在ASCII表中的位置计算数值
        switch(s[i]) {
            case 'a': case 'A': // 对小写和大写的'a'或'A'进行处理
                n = 16 * n + 10; // 十六进制的'a'或'A'对应十进制的10
                break;
            case 'b': case 'B': // 对小写和大写的'b'或'B'进行处理
                n = 16 * n + 11; // 以此类推
                break;
            // ... 其他字符的处理
            case 'f': case 'F':
                n = 16 * n + 15; // 十六进制的'f'或'F'对应十进制的15
                break;
            default: // 对数字0-9的处理
                n = 16 * n + (s[i] - '0'); // 直接转换
                break;
        }
    }
    return n; // 返回计算得到的数值
}

增量和减量运算符

前缀递增/递减

  • 先将变量的值加一/减一,然后返回新值。

后缀递增/递减

  • 先返回变量的值,然后变量值加一/减一。

举例

  1. 从字符串中移除所有的指定字符。
#include <stdio.h> // 引入标准输入输出库,用于printf函数

// 函数声明:从字符串s中删除所有出现的字符c
void squeeze(char s[], int c);

int main() {
    char s[] = "Hello world!"; // 定义一个字符串数组s,并初始化为"Hello world!"
    squeeze(s, 'l'); // 调用squeeze函数,删除s中的所有'l'字符

    printf("%s\n", s); // 打印修改后的字符串s
}

// 函数定义:从字符串s中删除所有出现的字符c
void squeeze(char s[], int c) {
    int i, j; // 定义循环计数器i和用于跟踪新字符串结束位置的j

    // 使用for循环和i作为计数器,j用于重写修改后的字符串
    for (i = j = 0; s[i] != '\0'; i++) {
        // 如果当前字符不是要删除的字符c
        if (s[i] != c) {
            // 将当前字符复制到s[j]的位置,然后递增j
            s[j++] = s[i];
        }
    }
    // 在新字符串的末尾添加空字符,标记字符串结束
    s[j] = '\0';
}
  1. 把一个字符串拷贝另一个字符串末尾。
#include <stdio.h> // 引入标准输入输出库,用于printf函数

// 函数声明:将字符串t连接到字符串s的末尾
void StrCat(char s[], char t[]);

int main() {
    char s[100] = "Hello world!"; // 定义一个足够大的字符数组s,并初始化为"Hello world!"
    char t[] = " nihao shijie";   // 定义一个字符串数组t,并初始化为" nihao shijie"
    StrCat(s, t);                // 调用StrCat函数,将t连接到s的末尾

    printf("%s\n", s); // 打印连接后的字符串s
}

// 函数定义:将字符串t连接到字符串s的末尾
void StrCat(char s[], char t[]) {
    int i, j; // 定义循环计数器i和j

    i = j = 0; // 初始化计数器i和j为0
    // 使用while循环找到s字符串的结束位置
    while (s[i] != '\0')
        i++;
    // 从s的末尾开始,将t字符串的每个字符复制到s中
    while ((s[i++] = t[j++]) != '\0')
        ; // 空循环体,直到t字符串结束
}

练习

  1. 编写 squeeze(s1,s2) 的另一个版本,删除 s1 中与字符串 2 中的字符匹配的每个字符。
#include <stdio.h> // 引入标准输入输出库,用于printf函数

// 函数声明:从字符串s中删除所有在字符串t中出现的字符
void squeeze(char s[], char t[]);

int main() {
    char s[] = "Hello world!"; // 定义一个字符串数组s,并初始化为"Hello world!"
    char t[] = " lo";          // 定义一个字符串数组t,并初始化为" lo"
    squeeze(s, t);             // 调用squeeze函数,删除s中所有在t中出现的字符

    printf("%s\n", s); // 打印修改后的字符串s
}

// 函数定义:从字符串s中删除所有在字符串t中出现的字符
void squeeze(char s[], char t[]) {
    int i, j, z; // 定义循环计数器i, j和用于跟踪新字符串结束位置的z

    // 外层循环:遍历字符串t中的每个字符
    for (i = 0; t[i] != '\0'; i++) {
        z = 0; // 重置z为0,准备构建新的字符串
        // 内层循环:遍历字符串s中的每个字符
        for (j = 0; s[j] != '\0'; j++) {
            // 如果s[j]不等于t[i],则将其复制到s的前面位置
            if (s[j] != t[i]) {
                s[z++] = s[j]; // 复制字符,并递增z
            }
        }
        // 内层循环结束后,在新字符串的末尾添加空字符
        s[z] = '\0';
    }
}
  1. 编写函数 any(s1,s2),返回字符串 s1 中第一个出现字符串 s2 中任意字符的位置,如果 s1 不包含 s2 中的字符,则返回 -1。
#include <stdio.h> // 引入标准输入输出库,用于printf函数

// 函数声明:检查字符串t中的任意字符是否出现在字符串s中
int any(char s[], char t[]);

int main() {
    char s[] = "Hello world!"; // 定义一个字符串s,并初始化为"Hello world!"
    char t[] = "l";            // 定义一个字符串t,并初始化为"l"
    // 调用any函数,检查t中的字符是否出现在s中,并打印返回的索引或-1
    printf("%d\n", any(s, t));
}

// 函数定义:检查字符串t中的任意字符是否出现在字符串s中
int any(char s[], char t[]) {
    int i, j; // 定义循环计数器i和j

    // 外层循环:遍历字符串t中的每个字符
    for (i = 0; t[i] != '\0'; i++) {
        // 内层循环:遍历字符串s中的每个字符
        for (j = 0; s[j] != '\0'; j++) {
            // 如果在s中找到与t[i]匹配的字符,则返回当前索引j
            if (s[j] == t[i])
                return j; // 返回匹配字符在s中的索引
        }
    }
    // 如果遍历完t中的所有字符都没有找到匹配项,则返回-1
    return -1;
}

三元表达式

z = (a > b) ? a : b;    /* z = max(a, b) */
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值