segmentation fault occur while reversing the string - c

Below is my piece of code, I don't understand why it always gives me the segmentation fault:
#include <stdio.h>
void reverse(void);
int main ()
{
printf("enter the text");
printf("\n");
reverse();
printf("\n");
return(0);
}
void reverse(void)
{
char c;
if((c=getchar()) != '\n')
{
reverse();
}
putchar(c);
}
In my opinion I have done everything correctly, what is the mistake?

The code works fine as long as you enter a newline. Perhaps you are terminating your input with EOF (usually bound to Ctrl+D) without feeding it a newline before, and in that case, the code will never see a newline and there will be a stack overflow due to infinite recursion.
So, you should check that getchar() doesn't return EOF. Also, getchar() returns int, not char - this is important for portability and to make sure that comparison with EOF works as expected.
Here's the code after addressing these issues:
#include <stdio.h>
void reverse(void);
int main (void) {
printf("enter the text\n");
reverse();
printf("\n");
return 0;
}
void reverse(void) {
int c;
if ((c=getchar()) != '\n' && c != EOF) {
reverse();
}
if (c != EOF) {
putchar(c);
}
}

Your program compiled and ran fine on my setup: latest stable gcc on Ubuntu 14.04.2 LTS 64-bit.
Here is another version using a different approach (namely the fgets function). See if it works for you:
#include <stdio.h>
#include <string.h>
void reverse_str( char * );
int main()
{
char input[1024];
printf("Enter text: ");
fgets(input, sizeof(input), stdin);
reverse_str(input);
printf("Reversed string: %s\n", input);
return 0;
}
void reverse_str(char *to_reverse)
{
char temp[1024];
int count = strlen(to_reverse) - 1; //Exclude newline introduced with fgets
int i=0;
for( i=count; i>=0; i-- ){
temp[i] = to_reverse[count - i - 1]; //Subtract 1 to not include the new line introduced by fgets
}
temp[count+1] = '\0';
strcpy(to_reverse, temp);
}

Your code seems to failing because of the nasty characters of getchar()..In most of the system it should work but I think your compiler is trying to access the memory saved beyond the array & hence generating segmentation fault...Can you please make sure if you give '\0' in place of '\n', it is working or not..I think the problem is that your machine is not able to detect the '\n' given from your keyboard & hence keep on going into recursion mode & stack is overflown before the recursion ends & when stack is overflown, it is trying to access unauthorised memory & hence segmentation fault occurs
Try this
#include <stdio.h>
#include <string.h>
char str[] = "Hello World";
size_t length;
int count = 0;
void reverse(char* a, char* b){
// static int count = 0;
char temp;
if (count < length/2){
count++;
reverse(str + count, str + (length - 1) - count);
}
temp = *a;
*a = *b;
*b = temp;
}
int main(){
length = strlen(str);
reverse(str, str + length - 1);
printf("%s", str);
return 0;
}

Related

does the pointer reallocate memory as it increments?

how can i stop *str from filling memory that i didnt give to it, without having to add an ending condition which in this case is : i <= n
do{
//instructions;
} while (... && i <= n);
in this exemple i reserved only 3 bytes of memory to *str but when i run my code and input more than 3 characters it still works... how does that happen shouldnt it give an error cuz there isnt enough memory for the rest of the characters ? what if the selected empty adresses were xxxxx1 xxxxx2 xxxxx3 and then xxxxx4 is full will it stop and output only the 3 characters without an error ?
P.s : I am aware of the function gets() but i dont want to use it because it reallocates memory. i thought that by entering character by character i will solve the problem and stop the user from filling the pointer because this time there is no memory reallocation and *str only has 3 blocks of memory so the rest will go to the buffer and *str will stop at *(str + 2)
hope u understood the problem and thank u for answering
#include <stdio.h>
#include <string.h>
#include <malloc.h>
int main()
{
int i = -1, n = 3;
char *str = (char *)malloc(n*sizeof(char));
printf("Enter a string: ");
do
{
i++;
str[i] = getchar();
} while (str[i] != '\n' && i < n);
str[i] = '\0';
printf("Entered string is: %s", str);
return 0;
}
C doesn't perform any type of bounds checking on arrays or allocated memory. That's part of what makes it fast.
That also means that reading or writing past the end of an array causes undefined behavior which basically means there's no guarantee what the program will do. The language trusts you to do the proper thing, so it's up to you to ensure that you don't do something you shouldn't.
Also, gets doesn't reallocate memory. In fact, it shouldn't be used at all specifically because it doesn't perform any bounds checking.
Your example doesn't work if the input string is longer than two characters since it then tries to write beyond the array. What will happen when you try to write outside of the array is undefined, which means that it may work by pure chance under some circumstances. Try this safe function instead which always reads the entire line and truncates the result if necessary:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void ReadLine(char result[], int resultLen)
{
int ch, i;
assert(resultLen > 0);
i = 0;
ch = getchar();
while ((ch != '\n') && (ch != EOF)) {
if (i < resultLen - 1) {
result[i] = ch;
i++;
}
ch = getchar();
}
result[i] = '\0';
}
int main(void)
{
int n = 3;
char *str = malloc(n);
printf("Enter a string: ");
ReadLine(str, n);
printf("Entered string is: %s\n", str);
free(str);
return 0;
}

C language alphanumeric check for bad chars

I have this C code fully working:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdint.h>
int isAlphaNum(char *str) {
for (int i = 0; str[i] != '\0'; i++)
if (!isalnum(str[i]))
return 0;
return 1;
}
int main() {
char *user_string = "abcdedf0123456789ABCD";
if (isAlphaNum(user_string)) {
printf(" is valid \n");
} else {
printf(" is not valid \n");
}
printf(" \n end \n");
return 0;
}
the following is copied from terminal:
but when I receive input via socket like this:
90a41ae8477a334ba609e06cujdikj#%&%$#$Dkdfsノ,ᅵハ"]￘モ {ᆳf
or
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒814
the program crashes
at this part:
for (int i = 0; str[i] != '\0'; i++)
if (!isalnum(str[i]))
I used the function by #chqrlie and works:
edited
int isAlphaNum(const char *str) {
//this message is printed , then craches
printf("pass isAlphaNum userinput = %s\n" , str);
while (*str) {
if (!isalnum((unsigned char)*str++))
return 0;
}
return 1;
}
if (isAlphaNum(userinput)) {
printf(" success ;) \n");
}
all ok now
thanks for the help
There is an issue in your code, but it is unlikely to cause the problem on GNU/linux systems, but might on other ones: isalnum(str[i]) has undefined behavior if str[i] has a negative value, which is possible if the string contains 8-bit bytes and the char type is signed by default. isalnum() should only be passed values of the type unsigned char or the special negative value EOF.
The function should be written this way:
#include <ctype.h>
int isAlphaNum(const char *str) {
while (*str) {
if (!isalnum((unsigned char)*str++))
return 0;
}
return 1;
}
Your remark about receiving input via socket prompts me to suspect that you are not null terminating the string received via a socket. This could cause isAlphaNum() to read beyond the end of the array and cause a segmentation fault if there is no null byte until the end of the memory mapped area (which used to be called a segment in ancient Multics systems).

Fill char array with input and I dont understand the output

So I'm learning the char arrays in C. I wrote a little program which works with functions and reads input from terminal and on EOF will printf the char array.
If I enter, for example: hello my name is and press enter, I receive this output: hello my z Ͳ
I don't understand where the z Ͳ comes from. Can someone explain it to me?
#include <stdio.h>
const int MAXLENGTH = 10;
int getLine(char[], int);
int main(void) {
char inputString[MAXLENGTH];
getLine(inputString, MAXLENGTH);
printf("%s", inputString);
return 0;
}
// Functions:
int getLine(char destArray[], int length) {
int returnLength;
int input;
for (int i = 0; i < length - 1; i++) {
if ((input = getchar()) != EOF) {
destArray[i] = input;
returnLength = i;
}
}
return returnLength;
}
There are multiple problems in your code:
you do not store a null terminator at the end of the destination array in getLine().
you should stop read from stdin when you get a newline ('\n') or an EOF value.
Here is a modified version:
#include <stdio.h>
const int MAXLENGTH = 10;
int getLine(char[], int);
int main(void) {
char inputString[MAXLENGTH];
getLine(inputString, MAXLENGTH);
printf("%s\n", inputString);
return 0;
}
// Functions:
int getLine(char destArray[], int length) {
int i, c;
for (i = 0; i < length - 1; i++) {
c = getchar();
if (c == EOF || c == '\n')
break;
destArray[i] = c;
}
destArray[i] = '\0';
return i;
}
Running this program will show that hello my name is does not fit in the destination array as the program's output will be hello my
In your program, you were not storing anything beyond the end of the buffer, because you correctly test i < length - 1, but printf did read beyond the 9-th byte set by getLine() and printed whatever contents was in memory at those addresses until it finds a null byte, which is undefined behavior. The weird output is a benign side effect of undefined behavior, the program could have crashed too. The bytes in the memory probably correspond to values stored in the stack for the main() function local frame and return address. Different compilers, different platforms or even different invocations of the same program could produce different output (the latter may seem unlikely, but would happen on OS/X because of stack randomisation).

C programming, meaningless figures on console [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I wrote code to reverse a sentence that the user inputs, but when I run this code and write a sentence, this code prints meaningless figures instead of reverse version of my sentence. I need helping locating the error
#include <stdio.h>
#include <string.h>
void reverser(char*);
int readmassage(char[], int);
int main()
{
char mysentence[30];
readmassage(mysentence, 30);
reverser(mysentence);
printf("%s", mysentence);
system("pause");
return 0;
}
void reverser(char *massage)
{
char temp,*p;
p = massage + strlen(massage)-1;
while (p > massage) {
temp = *massage;
*massage = *p;
*p-- = temp;
}
}
int readmassage(char massage[], int lenght)
{
int ch, i = 0;
while (ch = getchar() != '\n') {
if (lenght > i)
massage[i++] = ch;
}
massage[i] = '\0';
return i;
}
Your problem is here:
temp = *massage;
*massage = *p;
*p-- = temp;
massage always points to the first character in your string here. So you keep overwriting the first character, and then writing the new first character to the last character on the next go round. The effect is that you essentially rotate the string by one character instead of reversing it. If you change *massage = *p; to *massage++ = *p; (or create a new incrementing pointer variable to correspond to p which you initialize to massage), it'll probably work.
What I'm saying is that your "start of the string" pointer needs to be... massaged. ba dum chshhhh
EDIT: And you also need to change this, in readmessage:
while (ch = getchar() != '\n')
to:
while ((ch = getchar()) != '\n')
Otherwise, rather than the input character, you're actually setting ch to 0 or 1, depending on whether getchar() is returning '\n' or not. This is because due to the order of operations, != actually gets executed before =, and != gives you 1 if the expression is true and 0 if it is false. This 0 or 1 then gets stored in ch by the = operator.
You could also just replace all of readmessage with fgets, as it's included in the standard library and meant for exactly this sort of thing (unless reimplementing it was part of your assignment, of course).
EDIT:
Adding explanation. There are some issues with your code, few major, few not that serious
Don't use void main(). It's not the best thing to use.
Indenting your code will make it easier to read
Let's look at the readmassage function.
You are assigning the result of getchar() to an int. That's not right. it should be a char
here's a version of your code with minor fixes
#include <stdio.h>
#include <string.h>
void reverser(char*);
int readmassage(char[], int);
void main()
{
char mysentence[30];
readmassage(mysentence, 30);
printf("Input: %s", mysentence);
reverser(mysentence);
printf("Output: %s", mysentence);
system("pause");
return 0;
}
void reverser(char*massage)
{
char temp,*p;
p = massage + strlen(massage)-1;
while (p > massage) {
temp = *massage;
*massage = *p;
*p-- = temp;
}}
int readmassage(char massage[], int lenght)
{
char ch;
int i = 0;
while (ch != '\n')
{
ch = getchar();
printf("Here\n");
if (lenght > i)
{
massage[i++] = ch;
printf("%c\n", massage[i]);
}
}
massage[i] = '\0';
return i;
}
When you try this you will find that the input string gets read fine, just be sure to not to hi Enter after every character and instead type the full string out as \n is a valid character that can be in the stream and will terminate the loop the next iteration.
This is why you should use a char array reading function like fgets.
Once you get here you can see that the reverser is just following a slightly flawed reversing logic.
grammatical errors aside, fixing this you can get
here you go
#include <stdio.h>
#include <string.h>
void reverser(char* message)
{
int start, end;
start = 0;
end = strlen(message) - 1;
char temp;
while (start < end) {
temp = message[start];
message[start] = message[end];
message[end] = temp;
start++;
end--;
}
}
void readmessage(char message[], int length)
{
fgets(message, length , stdin);
}
int main()
{
char mysentence[30];
readmessage(mysentence, 30);
printf("Read the string\n");
reverser(mysentence);
printf("%s\n", mysentence);
return 0;
}
please debugg to find out the reason sometimes.. It will help you..
The problem is when you call readmassage(mysentence, 30) inside the function you have the string input.
When the flow comes back to the method the value is no more there as you had passed mysentence by value..
And you send null to reverse()..
Pass by reference will work..

Reversing a string in C using Visual Studio

I'm building a program for reversing a string in visual studio, and while I run the code and enter a word I want to reverse, the program crashes.
#include <stdio.h>
#include <conio.h>
#include <string.h>
main(void) {
char r[256];
int i, d;
printf("\nEnter the word you want to reverse : ");
gets_s(" %s", r, sizeof(r));
d = strlen(r);
for (i=d;i!=0;i--) {
printf("%s",i);
}
return 0;
}
Please note that I tried your program on Linux, so no MS Visual C++ and more specifically no conio.h and gets_s.
There are multiple problems with your program:
Your call to gets_s is incorrect, according to this and this, gets_s is defined as:
char *gets_s(
char *buffer,
size_t sizeInCharacters
);
You are calling it with illegal arguments. Instead of gets_s(" %s", r, sizeof(r)); you need to call it like this:
gets_s(r, 256);
the first parameter is pointer to the string buffer where the gets_s function will store the line from input and the second is the size of the buffer, note that in char r[256] you can store 255 characters and terminating zero (\0).
Your for loop is incorrect instead of for (i=d;i!=0;i--) { you need to do it like this:
for (i=d-1;i>=0;i--) {
now the loop starts from last character instead of \0 and ends when the i < 0 ie. the last print will be when i=0.
And your final mistake is that you are using printf incorrectly instead of printf("%s",i); you need to do:
printf("%c",r[i]);
because you are printing characters: "%c" is for char output and r[i] is i-th character from string r (don't forget that we count from 0).
So, in total this is how the program should look like:
#include <stdio.h>
#include <conio.h> // does not exist on GCC (Linux)
#include <string.h>
main(void) {
char r[256]; // 255 characters + \0
int i, d;
printf("\nEnter the word you want to reverse : ");
gets_s(r, 256); // store at most 255 characters + \0
// does not work on GCC (Linux) even with -std=C11
d = strlen(r);
// start from last character and include first
for (i=d-1;i>=0;i--) {
// %c - character, r[i] gets the i-th character from string r
printf("%c",r[i]);
}
return 0;
}
void rev(char *s)
{
char *start, *end;
end = start + strlen(s) - 1;
for (start = s; end > start; ++start, --end) {
char tmp;
tmp = *start;
*start = *end;
*end = tmp;
}
}
Use the fgets function, and also put the reversing code in its own function, like I did. So the final code is
int main()
{
char line[80];
fgets(line, 80, stdin);
/* don't allow empty string */
if (*line == '\0') {
fprintf(stderr, "Empty string is not a string\n");
return 1;
}
/* remove the \n placed by fgets */
remnl(line);
rev(line);
printf("%s\n", line);
return 0;
}
void remnl(char *s) { s[strlen(s) - 1] = 0; }
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main(void) {
char r[256];
int i, d;
printf("\nEnter the word you want to reverse : ");
gets_s(r, sizeof(r));
d = strlen(r) - 1;
for (i = d; i >= 0; i--) {
printf("%c", r[i]);
}
_getch();
return 0;
}

Resources