I have written this simple program to print a string in reverse order but it is showing segmentation fault.
#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);
}
Can anybody explain me why I am getting this segmentation fault? Opearating system : Ubuntu , compilor : gcc
char *string
creates a variable which can hold a pointer to a string, but it is not set here. So it points to a random location which, when accessed, segfaults.
To be useful, either allocate some memory and assign that to the pointer:
char *string = malloc(1000); // big enough for string
or, do it all at once:
char string[1000];
Ideally, instead of using a hardcoded constant (like my example 1000
) use a symbolic constant, or better yet, find out how long the string needs to be and then use that.
There are several problems with your code, which I highlighted:
-you don't allocate memory for the string
-you try to access an array element which is out of bounds
-you forgot to decrement n, so you'll have an infinite loop
Remember that arrays in C are 0-based.
#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);
}
%s
with scanf
does not allocate anything. The caller is supposed to allocate. Even if you were allocating something, since you don't know how big the string in the input stream is going to be, this is akin to doing gets
, which is bad for security and stability reasons.
One of the simplest things you can do is have a pre-set constant amount of characters and use fgets:
char string[256];
if (!fgets(string, sizeof(string), stdin))
{
// TODO: handle error
}
This puts an artificial limit to the maximum size of the string. Another approach would be to use dynamic memory. Here's just a quick example that grows the buffer as-needed.
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);
As for reversing a string, this is just an example of a typical "string manipulation, C-style" way of doing things:
// 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;
}
}
}
With this, after reading you can do:
reverse(string);
puts(string);
Like @wallyk already said:
char* string
is actually a pointer to a character. You must allocate memory for the string using either,
malloc or calloc
so you can do something like:
char* string;
string = (char*) malloc( 50 * sizeof(char) );
which will allocate 50 characters for string. If your string is more than 50 characters, simply allocate appropriately.
Another way to do this is instead of creating a pointer, you can (not dynamically) allocate memory as follows:
char string[50]
That will also allocate 50 characters to string.
You have declared the string as char *
and you didn't assign the address, so it points to the variable address.
精彩评论