第8讲 字符常量的使用

运用字符常量使程序看起来更简洁和易修改,不容易出错

/*
*Copyright (c)2016,csdn学院
*All rights reserved.
*文件名称:main.c
*作    者:吴东锋
*完成日期:2016年5月28日
*版 本 号:v1.0
*功能描述:
(1)输入圆柱休的半径和高
(2)计算输出底面积、侧面积和表面积
 (3)程序中使用符号常量
*/
#include <stdio.h>
#include <stdlib.h>
#define PI 3.1415926
int main()
{
    float r,h,c,s,s1,s2;
    printf("请输入圆住体的半径和高度:");
    scanf("%f %f",&r,&h);
    c=r*2*PI;//底面周长
    s1=PI*r*r;//底面积
    s2=c*h;//侧面积
    s=s1*2+s2;//表面积
    printf("表面积:【%f】侧面积:【%f】底面积:【%f】\n",s,s2,s1);
    system("pause");
    return 0;
}

运行结果:


学习总结:

本节我学会了使用字符常量 在scanf里面%f代表float型,%lf代表double型  printf里面%f代表double型

<think> 我们参考了多个关于字符串循环右移的解决方案,并结合C++特性给出以下实现。核心思路是:通过取模处理大偏移量,分割字符串并重新拼接。 注意:循环右移n位相当于将字符串末尾的n个字符移到开头。我们可以通过以下步骤实现: 1. 计算实际需要移动的位数:`n % len`(避免重复移动) 2. 将字符串分为两部分:后n位和前面的字符 3. 将后n位与前面的字符交换顺序拼接 但是,题目要求是针对char组成的字符串(即C风格字符串),因此需要注意字符串结尾的空字符'\0'。 我们提供两种方法: 方法一:使用临时数组(安全,适用于所有情况) 方法二:三次反转法(空间复杂度低,但需要谨慎处理) 下面分别实现: ### 方法一:使用临时数组(参考引用[2]和[4]) 步骤: 1. 计算字符串长度len,并处理n(n=n%len) 2. 分配一个临时字符数组temp,大小为len+1(多一个位置存放'\0') 3. 复制原字符串中最后n个字符到temp的前n个位置 4. 复制原字符串中前len-n个字符到temp的后面部分 5. 将temp的内容复制回原字符串,并确保末尾有'\0' 注意:如果字符串为空或者n为0,则直接返回。 代码实现: ```cpp #include <cstring> // for strlen, strncpy, strcpy void rotateStringRight(char* str, int n) { int len = strlen(str); if (len == 0 || n % len == 0) { return; } n = n % len; // 确保n在[0, len-1]范围内 // 创建临时数组 char* temp = new char[len + 1]; // 动态分配,注意释放 // 复制最后n个字符到temp的前n个位置 strncpy(temp, str + len - n, n); // 复制前面len-n个字符到temp+n的位置 strncpy(temp + n, str, len - n); // 添加字符串结束符 temp[len] = '\0'; // 将temp复制回原字符串 strcpy(str, temp); // 释放临时数组 delete[] temp; } ``` ### 方法二:三次反转法(空间复杂度O(1)) 思路: 1. 反转整个字符串 2. 反转前n个字符 3. 反转剩下的字符 例如:字符串"abcdefg",循环右移2位: 原始: a b c d e f g 整个反转: g f e d c b a 反转前2个: f g e d c b a 反转剩余: f g a b c d e -> 得到目标"fgabcde"(注意:这里实际上应该是右移2位,即最后两位移到前面,所以是"fgabcde",但示例中应该是"fgabcde",注意原字符串是"abcdefg",右移2位后最后两位是"fg",移到前面,剩下的是"abcde") 但是注意:右移n位,相当于将最后n位移到前面。经过三次反转: 整个反转:将最后n个字符移到了前面,但顺序反了;前面的字符移到了后面,顺序也反了。 然后分别反转两部分,各自恢复顺序。 步骤: 1. 反转整个字符串(得到逆序) 2. 反转前n个字符(将前n个字符恢复为原来的顺序) 3. 反转剩下的字符(将后面的字符恢复为原来的顺序) 代码实现: ```cpp #include <cstring> // for strlen // 反转字符串的辅助函数 void reverse(char* str, int start, int end) { while (start < end) { char temp = str[start]; str[start] = str[end]; str[end] = temp; start++; end--; } } void rotateStringRight(char* str, int n) { int len = strlen(str); if (len == 0 || n % len == 0) { return; } n = n % len; // 反转整个字符串 reverse(str, 0, len - 1); // 反转前n个字符 reverse(str, 0, n - 1); // 反转剩下的字符 reverse(str, n, len - 1); } ``` ### 测试代码 我们可以编写main函数进行测试: ```cpp #include <iostream> using namespace std; int main() { char str1[] = "abcdefg"; rotateStringRight(str1, 2); cout << str1 << endl; // 应该输出 "fgabcde" char str2[] = "helloworld"; rotateStringRight(str2, 3); cout << str2 << endl; // 应该输出 "rldhellowo" return 0; } ``` ### 注意事项 1. 方法一中使用了动态内存分配,注意释放,避免内存泄漏。 2. 方法二的空间复杂度为O(1),但修改了原字符串。 3. 两种方法都要求传入的字符串是可修改的(即不能是字符常量)。 ### 相关问题 1. 如何实现字符串的循环左移? 2. 如果要求不使用额外空间,哪种方法更好? 3. 三次反转法的原理是什么? 4. 如何处理字符串为空或者长度为0的情况? 5. 如果n大于字符串长度,为什么需要取模? 以上两种方法均可有效实现字符串循环右移,根据需求选择合适的方法。 </think> # C++实现字符串循环右移 在C++中实现字符串循环右移n个位置有多种方法,下面我将介绍两种高效且实用的实现方式,并分析其原理和应用场景。 ## 方法一:字符串分割拼接法 这种方法利用字符串分割操作,将字符串分为两部分后重新拼接: ```cpp #include <iostream> #include <cstring> #include <cstdlib> // 用于memcpy void rotateStringRight(char* str, int n) { int len = strlen(str); if (len == 0 || n % len == 0) return; n %= len; // 处理n大于字符串长度的情况 char* temp = new char[len + 1]; // 动态分配临时空间 // 复制最后n个字符到临时数组开头 memcpy(temp, str + len - n, n); // 复制前面的字符到临时数组剩余部分 memcpy(temp + n, str, len - n); // 添加字符串结束符 temp[len] = '\0'; // 将结果复制回原字符串 strcpy(str, temp); delete[] temp; // 释放临时空间 } int main() { char str[] = "abcdefg"; int n = 2; std::cout << "原始字符串: " << str << std::endl; rotateStringRight(str, n); std::cout << "循环右移" << n << "位后的字符串: " << str << std::endl; return 0; } ``` ### 算法分析 - **时间复杂度**:$O(n)$,其中n是字符串长度 - **空间复杂度**:$O(n)$,需要额外空间存储临时字符串 - **优点**:逻辑清晰,易于理解 - **缺点**:需要额外空间 ## 方法二:三次反转法(空间优化) 这种方法通过三次反转操作实现循环右移,不需要额外空间: ```cpp #include <iostream> #include <cstring> // 反转字符串的辅助函数 void reverse(char* str, int start, int end) { while (start < end) { char temp = str[start]; str[start] = str[end]; str[end] = temp; start++; end--; } } void rotateStringRight(char* str, int n) { int len = strlen(str); if (len == 0 || n % len == 0) return; n %= len; // 处理n大于字符串长度的情况 // 三次反转实现循环右移 reverse(str, 0, len - 1); // 反转整个字符串 reverse(str, 0, n - 1); // 反转前n个字符 reverse(str, n, len - 1); // 反转剩余字符 } int main() { char str[] = "helloworld"; int n = 3; std::cout << "原始字符串: " << str << std::endl; rotateStringRight(str, n); std::cout << "循环右移" << n << "位后的字符串: " << str << std::endl; return 0; } ``` ### 算法分析 - **时间复杂度**:$O(n)$,三次反转操作的总和 - **空间复杂度**:$O(1)$,原地操作,无需额外空间 - **优点**:空间效率高 - **缺点**:理解难度稍高 ## 关键概念说明 1. **循环右移原理** 循环右移n位相当于将字符串的最后n个字符移动到开头位置。例如"abcdefg"右移2位变为"fgabcde"。 2. **取模运算的重要性** 通过`n %= len;`处理n大于字符串长度的情况,避免不必要的重复移动操作。 3. **边界条件处理** - 空字符串直接返回 - n为0或字符串长度的倍数时直接返回 - 处理n为负数的情况(可转换为左移) 4. **内存安全** 方法一中动态分配的内存必须使用`delete[]`释放,防止内存泄漏。 ## 应用场景 1. 密码学中的位操作 2. 数据加密算法的轮函数 3. 循环缓冲区的实现 4. 文本处理中的移位密码 ## 相关问题 1. 如何实现字符串的循环左移功能? 2. 三次反转法的数学原理是什么?为什么它能实现循环位移? 3. 当处理超长字符串(GB级别)时,哪种方法更优? 4. 如何修改代码以处理UTF-8编码的多字节字符? 5. 循环移位操作在加密算法中有哪些具体应用? 这些实现方法都遵循了高效的算法设计原则,第一种方法直接明了,第二种方法空间效率高,可以根据具体场景选择合适的解决方案[^1][^2][^3][^4]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A'feng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值