Chapter07

7.5.1

#include<stdio.h>
#include<math.h>
/// <summary>
/// 计算二阶多项式 a x^2 + bx + c的值
/// </summary>
/// <param name="x"></param>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
/// <returns></returns>
float fun(float x, float a, float b, float c) 
{
	return a * pow(x, 2) + b * x + c;
}

7.5.2


```c
#include<stdio.h>
#include<math.h>
/// <summary>
/// 打印m行n列的图形
/// 第一行由n个字符A组成
/// 第二行由n个字符B组成
/// ...
/// </summary>
/// <param name="m"></param>
/// <param name="n"></param>
void prn(int m, int n) {

	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < n; j++)
		{
			fputc('A' + i, stdout);
		}

		printf("\n");
	}
}

7.6

/// <summary>
/// 计算两个数的最大公约数
/// </summary>
/// <param name="num1"></param>
/// <param name="num2"></param>
/// <returns></returns>
long Gcd(long num1, long num2)
{

	if (num1 < num2)
	{
		long temp = num1;
		num1 = num2;
		num2 = temp;
	}

	while (num2 != 0)
	{
		long temp = num2;
		num2 = num1 % num2;
		num1 = temp;
	}

	return num1;
}

/// <summary>
/// 计算两个数的最小公倍数
/// </summary>
/// <param name="num1"></param>
/// <param name="num2"></param>
/// <returns></returns>
long Lcm(int num1, int num2)
{

	return num1 / Gcd(num1, num2) * num2;
}

7.7

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

// 函数声明  
unsigned long long fibonacci(int n);
unsigned long long findClosestFibonacci(unsigned long long x);

int main() {
    unsigned long long x;
    printf("请输入一个正整数x: ");
    scanf_s("%llu", &x);

    unsigned long long result = findClosestFibonacci(x);
    printf("与%llu最接近的斐波那契数列中的值是: %llu\n", x, result);

    return 0;
}

// 计算第n个斐波那契数  
unsigned long long fibonacci(int n) {
    if (n <= 1) {
        return n;
    }
    unsigned long long a = 0, b = 1, c;
    for (int i = 2; i <= n; i++) {
        c = a + b;
        a = b;
        b = c;
    }
    return b;
}

// 找到与x最接近的斐波那契数  
unsigned long long findClosestFibonacci(unsigned long long x) {
    unsigned long long closest = 0;
    unsigned long long diff = ULLONG_MAX;
    int n = 0;

    while (1) {
        unsigned long long fib = fibonacci(n);
        unsigned long long currentDiff = (fib > x) ? (fib - x) : (x - fib);

        if (currentDiff < diff) {
            diff = currentDiff;
            closest = fib;
        }

        // 如果已经找到了等于x的斐波那契数,或者下一个斐波那契数已经超过x,并且差值不再可能变小,则停止  
        if (fib == x || fib > x && (fib - x) > diff) {
            break;
        }

        n++;
    }

    return closest;
}

7.8

#include <stdio.h>  
#include <stdlib.h>  
#include <ctype.h>  
#include <string.h>  
  
#define MAX_SIZE 100  
  
// 定义操作符的优先级  
int precedence(char op) {  
    if (op == '+' || op == '-')  
        return 1;  
    if (op == '*' || op == '/')  
        return 2;  
    return 0;  
}  
  
// 执行两个操作数的运算  
int applyOp(int a, int b, char op) {  
    switch (op) {  
        case '+': return a + b;  
        case '-': return a - b;  
        case '*': return a * b;  
        case '/': return a / b;  
    }  
    return 0;  
}  
  
// 评估表达式  
int evaluate(char* tokens[], int size) {  
    int values[MAX_SIZE]; // 存储操作数的栈  
    char ops[MAX_SIZE];   // 存储操作符的栈  
    int valTop = -1;      // 操作数栈顶指针  
    int opsTop = -1;      // 操作符栈顶指针  
  
    for (int i = 0; i < size; i++) {  
        // 跳过空格  
        while (isspace(tokens[i][0])) {  
            tokens[i]++;  
        }  
  
        // 当前token是操作数  
        if (isdigit(tokens[i][0])) {  
            values[++valTop] = atoi(tokens[i]);  
        }  
        // 当前token是操作符  
        else {  
            // 如果栈不为空且栈顶操作符优先级大于或等于当前操作符优先级,则执行栈顶操作符  
            while (opsTop != -1 && precedence(ops[opsTop]) >= precedence(tokens[i][0])) {  
                int val2 = values[valTop--];  
                int val1 = values[valTop--];  
                char op = ops[opsTop--];  
                values[++valTop] = applyOp(val1, val2, op);  
            }  
            // 将当前操作符压入栈  
            ops[++opsTop] = tokens[i][0];  
        }  
    }  
  
    // 执行栈中剩余的操作符  
    while (opsTop != -1) {  
        int val2 = values[valTop--];  
        int val1 = values[valTop--];  
        char op = ops[opsTop--];  
        values[++valTop] = applyOp(val1, val2, op);  
    }  
  
    // 返回结果  
    return values[valTop];  
}  
  
// 将表达式分割成token数组  
void tokenize(char* expr, char tokens[][MAX_SIZE], int* size) {  
    int count = 0;  
    char* token = strtok(expr, " ");  
    while (token != NULL) {  
        strcpy(tokens[count++], token);  
        token = strtok(NULL, " ");  
    }  
    *size = count;  
}  
  
int main() {  
    char expr[MAX_SIZE];  
    char tokens[MAX_SIZE][MAX_SIZE];  
    int size;  
  
    printf("请输入一个不含括号的四则运算表达式: ");  
    fgets(expr, MAX_SIZE, stdin);  
  
    // 移除换行符  
    expr[strcspn(expr, "\n")] = 0;  
  
    // 分割表达式  
    tokenize(expr, tokens, &size);  
  
    // 计算结果  
    int result = evaluate(tokens, size);  
  
    // 输出结果  
    printf("结果是: %d\n", result);  
  
    return 0;  
}

7.9 使用有限状态机(FSM)的方法

#include <stdio.h>  
#include <ctype.h>  
#include <stdbool.h>  
#include <string.h>  
  
// 枚举表示状态  
typedef enum {  
    START,  
    AFTER_OPERAND,  
    AFTER_OPERATOR,  
    END  
} State;  
  
// 检查字符是否是有效的操作符  
bool isValidOperator(char c) {  
    return c == '+' || c == '-' || c == '*' || c == '/';  
}  
  
// 检查字符是否是有效的数字字符(包括负号和小数点,但这里只考虑整数)  
bool isValidDigit(char c) {  
    return isdigit(c);  
}  
  
// 检查表达式是否正确  
void checkExpression(const char* expr) {  
    State currentState = START;  
    bool operandFound = false; // 标记是否找到了操作数  
    bool operatorFound = false; // 标记是否找到了操作符  
    const char* errorPos = NULL; // 记录错误位置  
  
    for (int i = 0; expr[i] != '\0'; i++) {  
        char c = expr[i];  
  
        // 跳过空格  
        if (isspace(c)) {  
            continue;  
        }  
  
        // 根据当前状态和字符决定下一步  
        switch (currentState) {  
            case START:  
                if (isValidDigit(c)) {  
                    currentState = AFTER_OPERAND;  
                    operandFound = true;  
                } else if (isValidOperator(c)) {  
                    currentState = AFTER_OPERATOR;  
                    operatorFound = true;  
                    errorPos = &expr[i]; // 记录错误位置,因为这里不应该直接有操作符  
                } else {  
                    printf("表达式错误:在位置 %d 处遇到无效字符 '%c',原因是操作数不匹配。\n", i, c);  
                    return;  
                }  
                break;  
  
            case AFTER_OPERAND:  
                if (isValidOperator(c)) {  
                    currentState = AFTER_OPERATOR;  
                    operatorFound = true;  
                    operandFound = false; // 重置,准备检查下一个操作数  
                } else if (isValidDigit(c)) {  
                    // 允许连续的数字,视为同一个操作数的一部分  
                } else {  
                    printf("表达式错误:在位置 %d 处遇到无效字符 '%c',原因是操作数不匹配。\n", i, c);  
                    return;  
                }  
                break;  
  
            case AFTER_OPERATOR:  
                if (isValidDigit(c)) {  
                    currentState = AFTER_OPERAND;  
                    operandFound = true;  
                } else {  
                    printf("表达式错误:在位置 %d 处遇到无效字符 '%c',原因是操作符不匹配。\n", i, c);  
                    return;  
                }  
                break;  
  
            case END:  
                // 不应该到达这个状态,除非表达式以非法方式结束  
                printf("表达式错误:表达式以非法方式结束。\n");  
                return;  
        }  
    }  
  
    // 检查表达式是否以正确的状态结束  
    if (currentState == AFTER_OPERATOR && !operandFound) {  
        // 表达式以操作符结束,但没有后续的操作数  
        if (errorPos) {  
            // 如果之前已经记录了错误位置,则使用该位置  
            printf("表达式错误:在位置 %ld 处操作符后缺少操作数,原因是操作数不匹配。\n", errorPos - expr);  
        } else {  
            // 否则,指出表达式以操作符结束  
            printf("表达式错误:表达式以操作符结束,原因是操作数不匹配。\n");  
        }  
    } else if ((currentState == START || currentState == AFTER_OPERATOR) && !operatorFound && operandFound) {  
        printf("表达式错误:表达式中缺少操作符,可能是操作符不匹配或表达式不完整。\n");  
    } else if (currentState == AFTER_OPERAND) {  
       
        printf("表达式合法,但可能不完整(以操作数结束)。\n");  
    } else {  
        
        printf("表达式合法。\n");  
    }  
}  
  
int main() {  
    char expr[100];  
    printf("请输入一个简单四则运算表达式:");  
    fgets(expr, sizeof(expr), stdin);  
  
    // 移除换行符  
    expr[strcspn(expr, "\n")] = 0;  
  
    // 检查表达式  
    checkExpression(expr);  
  
    return 0;  
}

7.10

#include <stdio.h>  
#include <stdlib.h>  
#include <stdbool.h>  
#include <time.h>  
  
// 检查是否是有效日期  
bool isValidDate(int year, int month, int day) {  
    struct tm date = {0};  
    date.tm_year = year - 1900; // tm_year是从1900年开始计数的  
    date.tm_mon = month - 1;    // tm_mon是从0开始计数的(0=一月, 11=十二月)  
    date.tm_mday = day;  
  
    // 使用mktime来验证日期的有效性  
    // 如果mktime返回的时间戳是-1,则表示日期无效  
    time_t time_check = mktime(&date);  
    struct tm *timeinfo = localtime(&time_check);  
  
    // 检查mktime是否改变了我们的日期结构(如果无效,它会设置为某个默认时间)  
    return (timeinfo->tm_year == date.tm_year &&  
            timeinfo->tm_mon == date.tm_mon &&  
            timeinfo->tm_mday == date.tm_mday);  
}  
  
// 计算两个日期之间的天数差  
int daysBetweenDates(struct tm *startDate, struct tm *endDate) {  
    time_t start = mktime(startDate);  
    time_t end = mktime(endDate);  
    double difference = difftime(end, start) / (60 * 60 * 24); // 将秒转换为天  
    return (int)difference;  
}  
  
// 计算距离下一次生日的天数  
int daysToNextBirthday(struct tm birthDate, struct tm currentDate) {  
    struct tm nextBirthday = currentDate;  
    nextBirthday.tm_year += (currentDate.tm_mon < birthDate.tm_mon ||  
                             (currentDate.tm_mon == birthDate.tm_mon && currentDate.tm_mday < birthDate.tm_mday)) ? 1 : 0;  
    nextBirthday.tm_mon = birthDate.tm_mon;  
    nextBirthday.tm_mday = birthDate.tm_mday;  
  
    // 如果当前日期就是生日当天,并且还没过当天的24点,则下一次生日应该是明年的同一天  
    if (currentDate.tm_mon == birthDate.tm_mon && currentDate.tm_mday == birthDate.tm_mday &&  
        currentDate.tm_hour < 24 && currentDate.tm_min < 60 && currentDate.tm_sec < 60) {  
        nextBirthday.tm_year += 1;  
    }  
  
    // 如果当前日期已经过了今年的生日,则计算到明年生日的天数  
    // 否则,计算到今年生日还剩下的天数  
    return daysBetweenDates(&currentDate, &nextBirthday);  
}  
  
int main() {  
    int birthYear, birthMonth, birthDay;  
    int currentYear, currentMonth, currentDay;  
  
    // 输入出生年月日  
    while (true) {  
        printf("请输入出生年份 (yyyy): ");  
        scanf("%d", &birthYear);  
        printf("请输入出生月份 (mm): ");  
        scanf("%d", &birthMonth);  
        printf("请输入出生日期 (dd): ");  
        scanf("%d", &birthDay);  
  
        struct tm birthDate = {0};  
        birthDate.tm_year = birthYear - 1900;  
        birthDate.tm_mon = birthMonth - 1;  
        birthDate.tm_mday = birthDay;  
  
        if (isValidDate(birthYear, birthMonth, birthDay)) {  
            break;  
        } else {  
            printf("无效的日期,请重新输入。\n");  
        }  
    }  
  
    // 获取当前时间(为了简化,这里使用系统时间作为当前时间)  
    time_t now = time(NULL);  
    struct tm *currentDate = localtime(&now);  
    currentYear = currentDate->tm_year + 1900;  
    currentMonth = currentDate->tm_mon + 1;  
    currentDay = currentDate->tm_mday;  
  
    // 计算年龄(周岁)  
    int age = currentDate->tm_year - birthDate.tm_year;  
    if (currentDate->tm_mon < birthDate.tm_mon ||  
        (currentDate->tm_mon == birthDate.tm_mon && currentDate->tm_mday < birthDate.tm_mday)) {  
        age--; // 如果还没过今年的生日,则年龄减一  
    }  
  
    // 计算距离下一次生日的天数  
    int daysToBirthday = daysToNextBirthday(birthDate, *currentDate);  
  
    // 输出结果  
    printf("年龄(周岁): %d\n", age);  
    printf("距离下一次生日的天数: %d\n", daysToBirthday);  
  
    return 0;  
}

7.14

#include <stdio.h>  
#include <stdbool.h>  
#include <math.h>  
  
// 检查一个数是否是素数  
bool isPrime(int num) {  
    if (num <= 1) {  
        return false;  
    }  
    for (int i = 2; i <= sqrt(num); i++) {  
        if (num % i == 0) {  
            return false;  
        }  
    }  
    return true;  
}  
  
// 求一个正整数的最大素数因子  
int largestPrimeFactor(int n) {  
    int maxPrime = -1; // 初始化最大素数为-1,因为素数都是正数  
  
    // 从n的平方根开始向下遍历  
    for (int i = (int)sqrt(n); i >= 2; i--) {  
        // 如果i是n的因子,并且i是素数  
        if (n % i == 0 && isPrime(i)) {  
            maxPrime = i; // 更新最大素数因子  
            // 如果n还有除了i以外的因子(一定是i的某个因子),继续除直到n变为1或素数  
            while (n % i == 0) {  
                n /= i;  
            }  
           
        }  
    }  
  
    // 如果n在循环结束时仍然大于1,说明n本身就是一个素数  
    if (n > 1) {  
        maxPrime = n;  
    }  
  
    return maxPrime;  
}  
  
int main() {  
    int num;  
  
    printf("请输入一个正整数: ");  
    scanf("%d", &num);  
  
    if (num <= 0) {  
        printf("请输入一个正整数。\n");  
        return 1; // 非零返回值表示错误  
    }  
  
    int largestPrime = largestPrimeFactor(num);  
    printf("最大素数因子: %d\n", largestPrime);  
  
    return 0;  
}

7.15

#include <stdio.h>  
#include <math.h>

bool isNarcissisticNumber(int num) {  
    int originalNum, remainder, result = 0, n = 0;  
  
    originalNum = num;  
  
    // 计算数字的位数  
    while (originalNum != 0) {  
        originalNum /= 10;  
        n++;  
    }  
  
    originalNum = num;  
  
    // 计算各位数字的 n 次幂之和  
    while (originalNum != 0) {  
        remainder = originalNum % 10;  
        result += pow(remainder, n);  
        originalNum /= 10;  
    }  
  
    // 判断结果是否等于原数  
    return (result == num);  
}

7.16

// 判断是否为完数  
bool isPerfectNumber(int num) {  
    int sum = 0;  
  
    // 检查从 1 到 num/2 的所有数是否为 num 的因子  
    for (int i = 1; i <= num / 2; i++) {  
        if (num % i == 0) {  
            sum += i;  
        }  
    }  
  
    // 判断因子和是否等于原数  
    return (sum == num);  
}

7.17

int POWER_INTEGER(int x, int n) {
	int pow = 1;

	while (n > 0)
	{
		if (n % 2 == 1)
		{
			pow *= x;

		}
		x *= x;
		n = n / 2;
	}

	return pow;
}

7.18

/// <summary>
/// 递归计算一个整数的幂
/// </summary>
/// <param name="base">基数</param>
/// <param name="exponent">幂次</param>
/// <returns></returns>
long powerInteger(int base, int exponent) {
	// 递归基准情况:任何数的0次幂都是1  
	if (exponent == 0) {
		return 1;
	}
	// 递归情况:x^n = x * (x^(n-1))  
	else {
		return base * powerInteger(base, exponent - 1);
	}
}

7.19

/// <summary>
/// 计算两个数的最大公因数
/// </summary>
/// <param name="num1"></param>
/// <param name="num2"></param>
/// <returns></returns>
long Gcd(long num1, long num2) {

	if (num1 < num2)
	{
		long temp = num1;
		num1 = num2;
		num2 = temp;
	}

	while (num2 != 0)
	{
		long tmp = num2;
		num2 = num1 % num2;
		num1 = tmp;
	}

	return num1;
}

7.20

#include <stdio.h>  
#include <stdlib.h> // 为了使用pow函数,但实际上我们可以避免使用它  

// 注意:为了避免使用浮点数和潜在的精度问题,我们不使用pow函数来计算10的幂  
// 而是使用循环或位移/乘法组合来模拟这个操作,但在这个简单例子中,我们直接硬编码了几次幂的计算  

int digit(int n, int j) {
    // 注意:这里的实现没有检查j是否超出了n的位数,如果j太大,结果将是0  
    switch (j) {
    case 1:
        return n % 10; // 直接返回最后一位  
    case 2:
        return (n / 10) % 10; // 返回倒数第二位  
    case 3:
        return (n / 100) % 10; // 返回倒数第三位  
    case 4:
        return (n / 1000) % 10; // 返回倒数第四位  
    case 5:
        return (n / 10000) % 10; // 返回倒数第五位  
    case 6:
        return (n / 100000) % 10; // 返回倒数第六位  
    case 7:
        return (n / 1000000) % 10; // 返回倒数第七位  
    case 8:
        return (n / 10000000) % 10; // 返回倒数第八位  
    case 9:
        return (n / 100000000) % 10; // 返回倒数第九位  
    default:
        // 如果j超出这个范围,我们可以返回一个特殊值来表示错误,比如-1  
        return 0;
    }
}
int main() {
    int n, j;
    printf("请输入n和j:  ");
    scanf_s("%d %d", &n, &j);

    printf("数字%d 的倒数第 %d 位为:%d\n", n, j, digit(n, j));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值