问答题
问答题1:下面两个结构体大小分别是多少?
struct One{
double d;
char c;
int i;
}
struct Two{
char c;
double d;
int i;
}
在 VS 2017 中,编译器默认对齐数为 8,在类 One
第一个 double
占8个字节,char
占4个字节, int
占四个字节,所以总共占16字节.
在类 Two
中第一个 char
占8个字节,double
占 8个字节,int
占 4个字节,最大对齐数是8,所以最终大小要是最大对齐数的整数倍,24个字节.
当把默认对齐数设置为 #pragma pack(4) 的时候,类占的字节数也可能发生变化. 对于类 One
来说, double
依然占8个字节,char
占4个字节,int
占4个字节,最终占 16字节.
类 Two
中,char
占4个字节,这时候 double
占8字节,编译器默认对齐数为4,所以对齐数选择4的整数倍,double
占8个字节,int
占4个字节,总共是 16 字节.
结构体对齐规则
第一个成员在与结构体变量偏移量为0的地址处
其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处,对齐数 = 编译器默认的一个对齐数与该成员大小的较小值,VS中默认的值为8,Linux中的默认值为 4
结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍
如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍
问答题2:下列程序输出什么?
char p1[15]= "abcd",*p2= "ABCD", str[50]= "xyz";
strcpy(str+2,strcat(p1+2,p2+1));
printf("%s",str);
提示:strcat
的作用是将两个字符串连接到一起,p1+2
= "cd"
,p2+1
="BCD"
所以 strcpy
第二个参数字符串是"cdBCD"
,函数strcpy
的功能是进行拷贝覆盖.将字符查拷贝到源字符串.拷贝的位置是z
字符的位置,所以最终 str
字符串是"xycdBCD"
答案:xycdBCD
问答题3:若运行时从键盘上输入9876543210
则上面程序在 gcc 编译器下的输出结果是?
int main(){
int a;
float b,c;
scanf("%2d%3f%4f",&a,&b,&c);
printf("\na=%d,b=%d,c=%f\n",a,b,c);
}
提示:
答案:a=98,b=0,c=0.000000
编程题
编程题1:统计回文字符串
回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。花花非常喜欢这种拥有对称美的回文串,生日的时候她得到两个礼物分别是字符串A和字符串B。现在她非常好奇有没有办法将字符串B插入字符串A使产生的字符串是一个回文串。你接受花花的请求,帮助她寻找有多少种插入办法可以使新串是一个回文串。如果字符串B插入的位置不同就考虑为不一样的办法
例:A = "aba"
,B = "b"
,这里有4种把B插入A的办法:
(1) 在A的第一个字母之前:"baba"
不是回文
(2) 在第一个字母‘a’之后: "abba"
是回文
(3) 在字母‘b’之后: "abba"
是回文
(4) 在第二个字母’a’之后 "abab"
不是回文 ;所以满足条件的答案为2
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int backword(string str1){
size_t end = str1.size() - 1;
size_t begin = 0;
while (begin < end) {
if (str1[begin] != str1[end]){
return 0;
}
++begin;
--end;
}
return 1;
}
int main(){
string A, B;
getline(cin, A);
getline(cin, B);
size_t num = 0;
for (size_t i = 0; i < A.size()+1; ++i){
string temp = A;
//这个接口就是在i的前面插入B,最后返回插入后的字符串
temp.insert(i, B);
if (backword(temp)){
++num;
}
}
cout << num << endl;
return 0;
}
循环次数应该是 字符串长度+1 否则,最后一次并没有插入到结尾.
python 3解法
import sys
if __name__ == "__main__":
sa = str(sys.stdin.readline().strip())
sb = str(sys.stdin.readline().strip())
count = 0
for i in range(len(sa)+1):
newS = sa[:i] + sb + sa[i:]
if newS == newS[::-1]:
count += 1
print(count)
编程题2:连续最大和
一个数组有 N 个元素,求连续子数组的最大和。 例如:[-1,2,1],和最大的连续子数组为[2,1],其和为 3
输入描述:输入为两行。 第一行一个整数n(1 <= n <= 100000),表示一共有n个元素 第二行为n个数,即每个元素,每个整数都在32位int范围内。以空格分隔。
输出描述:所有连续子数组中和最大的值。
例:输入:3 -1 2 1 输出:3
方法一:只保存最大的子序列和
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int n;
while(cin>>n){
vector<int>v(n,0);
for(int i=0;i<n;++i){
cin>>v[i];
}
int sum = 0;
int res = v[0];
for(int i=0;i<n;++i){
if(sum>=0){
sum+=v[i];
}else{
sum = v[i];
}
res = max(res,sum);
}
cout<<res<<endl;
}
return 0;
}
方法二:动态规划,保存每一个状态的子序列和,输出子序列的最大和
转义方程:dp[i] = max(dp[i-1],0)+v[i];
dp[i]
: 代表至当目前的下标位置为止,最大的子序列和 . 从前一个值和0比较,取出最大值加源数组的下标元素.
res = max(res,dp[i]);
找出最大的子序列,保存下来.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int n;
while(cin>>n){
vector<int>v(n,0);
for(int i=0;i<n;++i){
cin>>v[i];
}
vector<int>dp(n,0);
dp[0] = v[0];
int res= v[0];
for(int i=1;i<n;++i){
dp[i] = max(dp[i-1],0)+v[i];
res = max(res,dp[i]);
}
cout<<res<<endl;
}
return 0;
}