gpt4 book ai didi

c - 指针数组上的指针算术

转载 作者:行者123 更新时间:2023-11-30 15:41:02 25 4
gpt4 key购买 nike

正在开发一个程序,将字符串拆分为较小的字符串,并删除尾随空格,试图充分了解我头脑中的指针。然而,当我尝试对指针数组进行指针算术时,我不断收到段错误(经过测试并确定这是发生错误的特定行);这是我的代码:

int enfold(char* to_enfold, long unsigned line_length, char** enfolded) {
int k;

long unsigned char_num = strlen(to_enfold);
if (char_num < line_length) {
for (k = 0; k <= sizeof(to_enfold); k++)
enfolded[0][k] = to_enfold[k];

printf("TOO SHORT\n");

enfolded[0][k] = '\n';

return 1;
}

else {
int i = LINE_LENGTH-1;

while ( to_enfold[i] == ' ' ||
to_enfold[i] == '\t' ||
to_enfold[i] == '\n' ||
i == 0) {
printf("%d\n", i);
i--;
}

for (k = 0; k <= i; k++)
enfolded[0][k] = to_enfold[k];

enfolded[0][k] = '\n';

return 1 + enfold((to_enfold+LINE_LENGTH), line_length, (enfolded+1));
}
}

问题在于递归,这会导致使用 (enfolded+1) 算术时出现段错误,但如果我们使用 enfolded 进行覆盖则不会出现段错误。对指向指针的指针使用指针算术是否存在问题。

最佳答案

一个问题是在代码中使用 sizeof():

if (char_num < line_length) {
for (k = 0; k <= sizeof(to_enfold); k++)
enfolded[0][k] = to_enfold[k];

这应该是 strlen(),除非你在循环条件下不调用 strlen(),并且在任何情况下循环都应该这样写:

    strcpy(enfolded[0], to_enfold);

但是,这不是您看到问题的代码部分。由于您没有向我们展示如何为 enfolded 分配内存,因此很难知道您做了什么,但很有可能您没有正确分配内存。您不仅应该预先分配指针数组,还应该预先分配每个指针指向的数组(因为您没有在此代码中分配空间)。或者,您需要在此处分配必要的空间。您也没有告诉该函数数组中有多少个指针。因此,精心设计的输入很容易导致您写出越界。您需要知道指针数组中有多少空间。

所以,我认为你应该:

  1. 在此函数中分配字符串。
  2. 完成后请确保将它们全部释放。
  3. 确保您知道数组中可以存储多少个字符串。

如果您使用的系统带有 valgrind然后用它来指导您完成内存分配和释放。

<小时/>

请阅读如何创建 SSCCE ( Short, Self-Contained, Correct Example )。人们可能没有跳出来提供帮助的原因之一是,您的代码显然不是 SSCCE;您的代码显然不是 SSCCE。没有 main() 函数。这是可行的 SSCCE 的近似值。我所做的主要更改是确保字符串以 null 结尾;我相当确定这是您问题的很大一部分。

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static
int enfold(char *to_enfold, size_t line_length, char **enfolded)
{
size_t k;

size_t char_num = strlen(to_enfold);
if (char_num < line_length)
{
for (k = 0; k <= char_num; k++)
enfolded[0][k] = to_enfold[k];
printf("TOO SHORT\n");
enfolded[0][k] = '\n';
enfolded[0][k+1] = '\0';
return 1;
}
else
{
size_t i = line_length - 1;

while (to_enfold[i] == ' ' ||
to_enfold[i] == '\t' ||
to_enfold[i] == '\n' ||
i == 0)
{
printf("%zu\n", i);
i--;
}

for (k = 0; k <= i; k++)
enfolded[0][k] = to_enfold[k];

enfolded[0][k] = '\n';
enfolded[0][k+1] = '\0';

return 1 + enfold((to_enfold + line_length), line_length, (enfolded + 1));
}
}

int main(void)
{
enum { SIZE = 100 };
char *enfolded[SIZE];

for (int i = 0; i < SIZE; i++)
enfolded[i] = malloc(sizeof(char) * SIZE);

char line[4096];
while (fgets(line, sizeof(line), stdin) != 0)
{
int n = enfold(line, 8, enfolded);
assert(n < SIZE);

for (int i = 0; i < n; i++)
printf("%d: <<%s>>\n", i, enfolded[i]);
printf("Parts: %d\n", n);
}

for (int i = 0; i < SIZE; i++)
free(enfolded[i]);

return 0;
}

示例运行:

$ ./mem <<< "Hello, how are you today?"
TOO SHORT
0: <<Hello, h
>>
1: <<ow are y
>>
2: <<ou today
>>
3: <<?
>>
Parts: 4
$

使用 valgrind 检查可以使代码获得干净的健康状况。但是,您可能需要考虑如果字符串中间有 30 个空格会发生什么(我强烈怀疑您会遇到问题,但我还没有证明这一点)。

在 Mac OS X 10.9.1 Mavericks 上使用 GCC 4.8.2 进行编译:

gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror mem.c -o mem

我几乎不会使用比这更宽松的编译选项进行编译(除非它需要是 C99,或者,放弃这个想法,C89 代码)。请注意,该代码确实使用了一些 C99 功能,特别是 for 循环中的变量声明。

关于c - 指针数组上的指针算术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20714274/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com