我编写了这个简单的程序,以相反的顺序打印字符串,但它显示了分段错误。
#include<stdio.h>
#include<string.h>
int main (int argc, char **argv)
{
char *string;
int n;
printf("Enter a string\n");
scanf("%s",string);
printf("\n");
n = strlen(string);
printf("%d",n);
while(n != 0)
{
printf("%c",string[n]);
n--;
}
return(0);
}
有人能解释我为什么会出现这种分段错误吗?操作系统:Ubuntu,compilor:gcc
答案 0 :(得分:6)
char *string
创建一个变量,可以保存指向字符串的指针,但不在此处设置。所以它指向一个随机位置,当被访问时,会发生段错误。
为了有用,要么分配一些内存并将其分配给指针:
char *string = malloc(1000); // big enough for string
或者,一次完成所有操作:
char string[1000];
理想情况下,不是使用硬编码常量(如我的示例1000
)而是使用符号常量,或者更好,找出字符串需要多长时间然后使用它。
答案 1 :(得分:2)
您的代码存在一些问题,我强调了这一点:
- 你不为字符串分配内存
- 您尝试访问超出范围的数组元素
- 你忘了减少n,所以你将有一个无限循环
请记住,C中的数组是从0开始的。
#include<stdio.h>
#include<string.h>
int main (int argc, char **argv)
{
char *string = malloc(100); //forgot to allocate memory
int n;
printf("Enter a string\n");
scanf("%s",string);
printf("\n");
n = strlen(string);
printf("%d",n);
while(n != 0)
{
n--; //forgot to decrement here, so infinite loop
//crash was also from here, string[n] is not a valid index
printf("%c",string[n]);
}
return(0);
}
答案 2 :(得分:2)
%s
的 scanf
不会分配任何内容。调用者应该分配。即使你是分配一些东西,因为你不知道输入流中的字符串有多大,这类似于做gets
,这对安全性和稳定性原因。
您可以做的最简单的事情之一就是预先设定一定数量的字符并使用fgets:
char string[256];
if (!fgets(string, sizeof(string), stdin))
{
// TODO: handle error
}
这会对字符串的最大大小设置一个人为限制。另一种方法是使用动态内存。这里只是一个根据需要增加缓冲区的快速示例。
char *buf = NULL;
size_t current_len = 0, current_alloc = 0;
int c = 0;
int should_continue = 1;
while (should_continue)
{
// Read a character...
c = fgetc(stdin);
// If c is EOF or a newline, let's zero-terminate the buffer and terminate
// the loop...
if (c == EOF || c == '\n')
{
c = 0;
should_continue = 0;
}
if (current_len + 1 > current_alloc)
{
// Need to grow the buffer.
void *newbuf;
size_t newsize;
newsize = current_alloc ? current_alloc * 2 : 256;
newbuf = realloc(buf, newsize);
if (!newbuf) { /* TODO: handle error */ }
current_alloc = newsize;
buf = newbuf;
}
// We've ensured capacity, now add the character.
buf[current_len++] = c;
}
// TODO: use buf as string...
// Now free since we're done
free(buf);
至于反转字符串,这只是典型的“字符串操作,C风格”处理方式的一个例子:
// Reverse the string in-place...
void reverse(char *s)
{
if (*s)
{
char *t = s + strlen(s) - 1;
while (s < t)
{
char u = *s;
*s++ = *t;
*t-- = u;
}
}
}
有了这个,读完后你可以这样做:
reverse(string);
puts(string);
答案 3 :(得分:0)
就像@wallyk已经说过的那样:
char* string
实际上是指向角色的指针。您必须使用
为字符串分配内存malloc or calloc
所以你可以这样做:
char* string;
string = (char*) malloc( 50 * sizeof(char) );
将为字符串分配50个字符。如果您的字符串超过50个字符,只需适当分配。
另一种方法是不是创建指针,而是可以(不动态)分配内存,如下所示:
char string[50]
那也将为字符串分配50个字符。
答案 4 :(得分:-1)
您已将字符串声明为char *
并且未指定地址,因此它指向变量地址。