PAT段错误 PAT1002

  1. 为何会出现段错误?
    一般是访问了不该访问的内容,导致出现这种错误,比如数组越界等。

  2. 修改示例:
    在这里插入图片描述
    题目中要求Ni取值范围在[0,1000]中,起初定义数组时开辟的空间太小,误把K的取值范围当做了Ni的取值范围:
    在这里插入图片描述
    结果出现了数组越界情况,发生了段错误
    在这里插入图片描述
    进行修改之后:
    在这里插入图片描述
    在这里插入图片描述
    问题解决!(*^^** )
    对于1002这道问题,我的答案

    #include<iostream>
    using namespace std;
    
    int main() {
    	int n = 2;
    	int a[1001] = { 0 };`在这里插入代码片`
    	double b[1001] = { 0.0 };
    	int aa;
    	double bb;
    	while (n--) {
    		int m;
    		cin >> m;
    		while (m--) {
    			cin >> aa;
    			a[aa] = 1;
    			cin >> bb;
    			b[aa] += bb;
    		}
    	}
    	int all = 0;
    	for (int i = 0; i < 1001; i++) {
    		if (a[i] == 1 && b[i] != 0.0) all++;
    	}
    	if (all == 0) {
    		printf("%d", all);
    		return 0;
    	}
    	printf("%d ", all);
    	for (int i = 1000; i >= 0; i--) {
    		if (a[i] == 1 && b[i] != 0.0) {
    			all--;
    			if (all == 0) {
    				printf("%d %.1f", i, b[i]);
    			}
    			else printf("%d %.1f ", i, b[i]);
    		}
    	}
    	system("pause");
    	return 0;
    }

下面就到了紧张刺激的对答案环节了!
在这里插入图片描述
可见参考答案把我的两个数组给合并了,我之前考虑的是引入另一个数组来表示多项式中的一个项是否被用到了,但要考虑到正负数相加为0的情况,所以还是要判断d[i]是否为0,故新引入的数组可以去掉。
修改完空格的位置之后,单独对非零项数是否为0的判断也可简化掉。

### PAT 段错误的原因及解决方案 段错误(Segmentation Fault),通常是因为程序试图访问未分配给它的内存区域而引发的一种运行时错误。以下是可能导致段错误的一些常见原因及其对应的解决方案: #### 1. 非法指针操作 非法的指针解引用或释放可能会导致段错误。例如,尝试访问已经释放的内存或者从未初始化的指针指向的内容。 ```c++ int *p = nullptr; // 或者 int *p; *p = 10; // 这里会触发段错误 ``` 为了避免此类问题,应始终确保指针在使用前被正确初始化并指向有效的内存地址[^1]。 #### 2. 越界数组访问 当数组索引超出其定义范围时,也可能发生段错误。C/C++ 不会对数组边界进行自动检查,因此程序员需格外小心。 ```c++ int arr[5]; arr[5] = 10; // 此处越界,可能引起段错误 ``` 为了防止这种情况的发生,在编写代码时应该仔细验证所有的数组下标是否合法[^2]。 #### 3. 动态内存管理失误 如果动态分配的内存没有得到妥善处理,比如重复释放同一块内存或是忘记释放不再使用的资源,都容易造成段错误。 ```c++ int* ptr = new int(1); delete ptr; // 下面的操作会导致段错 *ptr = 20; ``` 合理规划好对象生命周期内的每一个阶段是非常重要的,包括创建、修改以及销毁过程中的每一步都要谨慎对待[^3]。 #### 4. 函数调用栈溢出 递归层次太深或者其他形式的大规模函数嵌套调用也有可能耗尽系统的堆栈空间从而产生段错误现象。 ```c++ void recursive_function(int n){ if(n>0){ recursive_function(n-1); } } recursive_function(INT_MAX); // 极端情况下会造成栈溢出进而引发段错误 ``` 对于存在潜在无限循环风险的功能模块设计上要特别留意控制最大迭代次数或其他限制条件来规避上述隐患[^4]。 --- ### 示例代码修正版 下面给出一段可能存在段错误风险的例子,并展示如何修复它: 原有问题版本: ```cpp #include <iostream> using namespace std; class Test { public: char* str; void setStr(const char* s){ str=s;//仅保存了字符串常量地址,但该地址不可更改内容. } }; int main(){ Test t; t.setStr("hello"); *(t.str)= 'H'; //企图改变只读存储区的数据,将导致segment fault cout<<t.str<<endl; return 0; } ``` 改进后的安全版本: ```cpp #include <iostream> #include <cstring> using namespace std; class SafeTest { private: char* data_; public: ~SafeTest(){ delete[]data_; } explicit SafeTest(size_t size=8):data_(new char[size]){ memset(data_, '\0', sizeof(char)*size ); } void safeSetStr(const string& src){ const auto len =src.length()+1 ; if(len > strlen(data_)+1 ){ resizeData(len ); } strcpy(data_, src.c_str()); } friend ostream & operator << (ostream &os ,const SafeTest &st){ os<< st.data_; return os; } protected://内部调整大小逻辑封装起来供外部调用即可. bool resizeData(unsigned newSize){ try{ char *temp=new(nothrow)char[newSize]; if(!temp)return false; unsigned copyLen=min(strlen(this->data_), newSize-1u); memcpy(temp,this->data_,copyLen*sizeof(*this->data_)); temp[copyLen]='\0'; delete [] this->data_; this->data_=temp; return true; }catch(...){return false;} } }; int main(){ SafeTest tst; tst.safeSetStr("world!"); cout<<tst<<endl; return EXIT_SUCCESS; } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值