C语言编程--3.Z 字形变换

C语言编程–3.Z 字形变换

题目:

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,Z 字形排列之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。

请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);

示例 1:
输入:s = “PAYPALISHIRING”, numRows = 3
输出:“PAHNAPLSIIGYIR”

示例 2:
输入:s = “PAYPALISHIRING”, numRows = 4
输出:“PINALSIGYAHRPI”

示例 3:
输入:s = “A”, numRows = 1
输出:“A”

提示:

1 <= s.length <= 1000
s 由英文字母(小写和大写)、‘,’ 和 ‘.’ 组成
1 <= numRows <= 1000

我编写的程序是:

char* convert(char* s, int numRows) {
    int n=strlen(s);
    if (numRows==1) return s;
    int temp=2*numRows-2;
    int a=n/temp;
    int num=n%temp?a+1:a;
    char spro[n+1];
    int count=0;
    int tempro=temp;
    for(int i=0;i

运行后,显示有误,UU们可以帮忙看看哪里出错了吗?很欢迎私我!!

  1. 数组越界风险
    在 else 分支中,代码使用了 spro[count++] = s[tempro - j];。这里 tempro - j 可能会超出字符串 s 的有效索引范围(即大于等于 n),从而引发数组越界错误。因为没有对 tempro - j 的值进行边界检查,一旦其超出字符串 s 的长度,就会访问到未定义的内存区域。

  2. 返回局部数组的地址
    代码中定义了一个局部数组 spro,并且在函数结束时返回了该数组的地址,即 return spro;。在 C 语言里,局部变量的内存是在栈上分配的,当函数执行结束后,栈上的局部变量所占用的内存会被释放。因此,返回局部数组的地址会导致返回一个指向已释放内存的指针,这会引发未定义行为,后续使用该指针访问内存时可能会得到错误的数据。

  3. 逻辑错误
    在 for 循环里,j = j + temp; 语句在循环体内部修改了循环变量 j 的值,这会影响到 for 循环本身的迭代逻辑。由于 for 循环已经在循环头部分对 j 进行了递增操作(for(int j = i; j < n; j++)),在循环体内部再次修改 j 的值会使循环的迭代变得混乱,可能会跳过某些字符或者重复处理某些字符。

  4. 变量 tempro 初始值和使用问题
    变量 tempro 初始化为 temp,但在后续的 else 分支中,tempro 被用于计算 s 的索引,并且每次循环都会更新 tempro 的值(tempro = tempro + temp;)。这种使用方式缺乏清晰的逻辑依据,并且没有考虑到边界情况,容易导致索引越界和逻辑混乱。
    接下来有正确的代码:

    char* convert(char* s, int numRows) {
     int n = strlen(s);
     if (numRows == 1) return s;
    
     char* result = (char*)malloc((n + 1) * sizeof(char));
     if (result == NULL) {
         return NULL;
     }
    
     int index = 0;
     int cycleLen = 2 * numRows - 2;
    
     for (int i = 0; i < numRows; i++) {
         for (int j = 0; j + i < n; j += cycleLen) {
             result[index++] = s[j + i];
             if (i != 0 && i != numRows - 1 && j + cycleLen - i < n) {
                 result[index++] = s[j + cycleLen - i];
             }
         }
     }
     result[index] = '\0';
     return result;
     }
    
  5. 动态内存分配:使用 malloc 函数为结果字符串分配内存,确保在函数返回后内存仍然有效。

  6. 边界检查:在添加字符到结果字符串时,对索引进行边界检查,避免数组越界。

  7. 逻辑修正:使用 cycleLen 来控制循环的步长,避免在循环体内部修改循环变量 j 的值,使循环逻辑更加清晰。

你可能感兴趣的:(算法,数据结构)