使用程序将字符串拆分为较小的字符串并删除尾随空格,以便充分了解我脑中的指针。但是,当我尝试对指针数组进行指针运算时,我不断得到一个分段错误(测试并计算出这是发生错误的特定行);这是我的代码:
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覆盖则不会。在指针指针上使用指针算法是否有问题。
答案 0 :(得分:1)
一个问题是在代码中使用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
分配内存,因此很难知道您做了什么,但很有可能您没有正确分配内存。您应该不仅预先分配了指针数组,而且还预先分配了每个指针所指向的数组(因为您没有在此代码中分配空间)。或者,您需要在此处分配必要的空间。您还没有告诉此函数数组中有多少指针。因此,精心制作的输入很容易让你写出界限。你需要知道指针数组中有多少空间。
所以,我认为你应该:
如果您使用的是valgrind
系统,请使用它来指导您完成内存分配和发布。
请阅读有关如何创建SSCCE(Short, Self-Contained, Correct Example)的信息。人们可能没有参与帮助的一个原因是你的代码显然不是SSCCE;没有main()
功能。这是一个有效的SSCCE的近似值。我做的主要改变是确保字符串为空终止;我很确定这是你问题的很大一部分。
#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
循环中的变量声明。