C++程序运行报错“prg.exe已停止工作”,求原因排查
首先,你的程序崩溃主要是内存越界访问和逻辑条件错误导致的,我来逐一拆解问题并给出修复方案:
1. 最直接的崩溃原因:反向遍历循环的条件错误
你这段代码里的反向遍历循环:
for(; (str[k] != ' ') || (k != 0); k--, m++) { stress[m] = str[k]; }
这里用了||(逻辑或)完全错误。当k减到0时,如果字符串的第一个字符不是空格,k !=0为假,但str[k] != ' '为真,整个条件依然成立,循环会继续让k变成负数——此时访问str[k]就是去读数组范围外的内存,直接触发内存访问错误,导致程序崩溃。
正确的条件应该是当k >=0且当前字符不是空格时继续遍历,改用while循环更清晰:
while (k >= 0 && str[k] != ' ') { stress[m++] = str[k--]; }
2. 数组越界:strain数组的初始化和终止符赋值错误
你这段代码:
for(g = 0; stress[g] != '\0'; g++) ; char strain[g]; for(int n = 0, q = k - 1; q >= 0; n++, q--) { strain[n] = stress[q]; } strain[g] = '\0';
首先,g最终是stress的有效字符长度(不包含'\0'),所以char strain[g];的大小是g,但你最后给strain[g] = '\0';是写到数组的第g个位置——数组下标从0开始,strain的合法下标是0到g-1,这一步直接越界写内存,会破坏其他变量或者栈结构,导致崩溃。
其实你完全不需要额外的strain数组,直接反向输出stress数组就能得到正确的单词,能省掉很多不必要的错误。
3. 不安全的gets()函数
gets()是已经被C标准弃用的函数,它完全不检查输入的长度,当用户输入的字符串超过str[100]的容量时,会直接缓冲区溢出,导致程序崩溃或者不可预测的行为。应该用C++的cin.getline(str, 100)来替代。
4. 遗漏最后一个单词的判断
你当前判断单词结尾是'y'的条件是(str[i] == 'y') && (str[j] == ' '),但如果输入的最后一个单词以'y'结尾,str[j]是字符串终止符'\0'而不是空格,这样就会漏掉这个单词。所以条件应该改成:
if (str[i] == 'y' && (str[j] == ' ' || str[j] == '\0'))
修复后的完整代码
我把这些问题都修复了,同时去掉了调试用的cout<<12、cout<<1等语句,优化了逻辑:
#include <iostream> #include <cstring> using namespace std; int main() { char str[100]; cout << "Enter a string : "; cin.getline(str, 100); // 替换不安全的gets() cout << "The words containing y in their last place are : \n"; for(int i = 0; str[i] != '\0'; i++) { int j = i + 1; // 修正判断条件,包含最后一个单词的情况 if(str[i] == 'y' && (str[j] == ' ' || str[j] == '\0')) { char stress[50]; int m = 0; int k = i; // 修正反向遍历的循环条件,避免越界 while (k >= 0 && str[k] != ' ') { stress[m++] = str[k--]; } stress[m] = '\0'; // 给stress添加终止符 // 直接反向输出stress,不需要额外的strain数组 cout << "• "; for(int p = m - 1; p >= 0; p--) { cout << stress[p]; } cout << "\n"; } } return 0; }
这个版本应该能正常运行,不会再出现崩溃的情况,同时能正确识别所有以'y'结尾的单词,包括最后一个。
内容的提问来源于stack exchange,提问作者Starklearner

