#include <stdio.h>
main()
{
char* str;
char* strrev;
int i = 0;
int j = 0;
int c;
printf("Enter the string\n");
scanf("%[^\n]%*c", str);
while (*(str + i) != '\n')
{
i++;
}
for (c = i; c >= 0; c--)
{
*(strrev + j) = *(str + c);
j++;
}
}
This is my code to reverse a string. When I compile the code , it gives an error segmentation fault . Someone plz help me understand the error and realize my mistake.
Thanks
There are many issues:
You never allocate memory for str or strrev. This is why it crashes; writing to uninitialized pointers invokes undefined behavior, often resulting in a seg fault.
You're using scanf() with a complex conversion when you could just use fgets().
You should use strlen() rather than looping to find the end of the string.
char *str,*strrev;
first your char buffers where never initialized.
http://www.cplusplus.com/reference/cstring/strlen/
second use strlen to determine string len
regards
In addition to #unwind, even if you used str[100], the loop to find the length will fail. Since str doens not have a \n, the while() loop never ends.
// bad
char str[100];
scanf("%[^\n]%*c", str);
while (*(str + i) != '\n') {
i++;
}
// better
char str[100];
scanf("%99[^\n]%*c", str);
while (*(str + i) != '\0') { // look for \0
i++;
}
Following (some of) #unwinds pointers, here is some code that will reverse a string:
(you can use scanf(), but do not need such a complicated format string)
#include<stdio.h>
main()
{
char str[260],strrev[260];
int i=0, len;
printf("Enter the string\n");
scanf("%s",str);
len = strlen(str);
for(i=1;i<len;i++)
{
strrev[i-1] = str[len-i];
}
strrev[len]=0;
;
}
If you would like to avoid using scanf, then replace it with something like:
char str[260], strrev[260];
//...
fgets(buf, sizeof(str), stdin);
[EDIT-per comment] If still want to use a char *, do something like this:
#include<stdio.h>
main()
{
char *str, *strrev;
int i=0, len;
printf("Enter the string\n");
str = malloc(260);
strrev = malloc(260);
scanf("%s",str);
len = strlen(str);
for(i=1;i<len;i++)
{
strrev[i-1] = str[len-i];
}
strrev[len]=0;
free(str);
free(strrev);
}
Note: Other than keystroke counting, I am not sure how you would determine at run-time just how many characters will be entered by a user. So in this example, 260 bytes is assumed.
#include<stdio.h>
void main()
{
void mystrrev(char *);
char str[100];
char *p1;
p1=str;
printf("Enter the string..?\n");
scanf("%s",str);
mystrrev(p1);
printf("Reverse is =%s",p1);
}
void mystrrev(char *p1)
{
char rev[100];
char *r;
r=rev;
int i=-1,j=0;
while(*p1!='\0')
{
p1++;
i++;
}
while(i>=0)
{
p1--;
*r=*p1;
r++;
j++;
i--;
}
*p1='\0';
*r='\0';
while(j-1>=0)
{
r--;
j--;
}
while(*r!='\0')
{
*p1=*r;
p1++;
r++;
}
*p1='\0';
}
simple code
Related
When I am using gets() to scan input it is working perfectly ,but when I'm using fgets() to scan the input then the answer is coming out as 1 more than the actual length.
For example:--> For input "Hello"
fgets() is printing 6. BUT the answer should be 5.
Why? How to resolve
#include <stdio.h>
#include <string.h>
int string_length(char str[]);
int main()
{
char str[100];
printf("**********************************************\n");
printf("This is a program to reverse a string.\n");
printf("**********************************************\n");
printf("Enter a string: ");
fgets(str,100,stdin); // ----> when using this fgets() answer of length of string is coming out to be one more than the actual answer
gets(str); //This is giving the correct answer if used instead of fgets().
printf("%d",string_length(str));
return 0;
}
//function for calculating string length
int string_length(char str[])
{
int i;
for(i=0; str[i]!='\0'; i++);
return i;
//WAY__2
//OR by while loop
// int i,length=0;
// while (str[length] != '\0')
// {
// length ++;
// }
// return length;
//WAY__3
//OR by using strlen() function;
// int length = strlen(str);
// return length;
}
The function fgets can append the new line character '\n' to the entered sequence of characters. You should remove it as for example
str[ strcspn( str, "\n" ) ] = '\0';
As for the function gets then it is unsafe and is not supported by the C Standard. You should not use it.
As for your function string_length then it should be declared like
size_t string_length( const char str[] );
fgets reads also \n character from the file/stream. You need to remove it.
char *removeNL(char *str)
{
char *wrk = str;
if(wrk)
{
while(*wrk && *wrk != '\n' ) wrk++;
*wrk = 0;
}
return str;
}
Also use the correct type for sizes (size_t)
size_t string_length(const char *str)
{
size_t i;
for(i=0; str[i]!='\0'; i++);
return i;
}
You do not need the counter as you can use the pointer arithmetic to get the string length:
size_t string_length1(const char *str)
{
const char *end = str;
while(*end) end++;
return end - str;
}
int *i;
ters_cevir(){
char *term=i;
char *som=i;
char som1;
while (*term != '\0') { term++; }
while (*som != '\0') {
som1=som*;
*term=som;
term--;
som++;
}
}
int main() {
char *isim=malloc(sizeof(char));
i=&isim;
printf("Reverse words=");
scanf("%s",isim);
printf("Kelimenizin tersi:\n ");
ters_cevir(); // When I call this, it must make the reverse one that make from memory
while (*isim != '\0') {
printf("%c",*isim);
isim++;
sayac++;
}
return 0;
}
Hi I have modified your code. Please see below also see my comments:-
void ters_cevir(char *isim){
char *term=isim;
//char *som=isim;
//char som1;
while (*isim != '\0') { isim++; }
while (*term != '\0') {
//som1=som*;
*--isim=*term++//isim was pointing to the null character so we are pre decrement that pointer and post decrement term
//here we are coping the string in reverse order in isim
//term--;
//som++;
}
}
int main() {
char *isim=malloc(50);//you need enough space to store a string. you have just allocated only one byte which was not enough
//i=&isim;
printf("Reverse words=");
scanf("%s",isim);
printf("Kelimenizin tersi:\n ");
ters_cevir(isim); // now it will work fine. Here you are passing the address of isim
while (*isim != '\0') {
printf("%c",*isim);
isim++;
sayac++;
}
return 0;
}
Your code does not compile because of syntax errors such as som1=som*;
You should pass the string as an argument to ters_cevir(); instead of a global variable i with an incorrect type int *.
After fixing these problems, ters_cevir() will still not achieve the expected result because it overwrites the string from the end with characters from the start, with an off by one error.
You could correct this by swapping characters at *som and *term, but be careful to stop when som >= term otherwise you will reverse the string twice.
Futhermore, the code in main is completely broken.
Here is a corrected version:
#include <stdio.h>
char *reverse(char *str) {
char *term = str;
char *som = str;
char c;
while (*term != '\0') { term++; }
while (som < term) {
term--;
c = *som;
*som = *term;
*term = c;
som++;
}
return str;
}
int main() {
char buf[128];
printf("String to reverse: ");
if (scanf("%127[^\n]", buf) == 1) {
printf("Reversed string: %s\n", reverse(buf));
}
return 0;
}
I've been trying to practice programming so I decided to try to type the strcat() function myself, or a similar one you know. I typed this code in order to proceed it and I don't know where the problem is.
#include <stdio.h>
#include <stdlib.h>
void main(){
int i, j;
char a[100]; char b[100];
printf("enter the first string\n");
scanf("%s", &a);
printf("enter the second string\n");
scanf("%s", &b);
for(i =0; i<100; i++){
if(a[i] == '\0')
break;
}
// printf("%d", i);
for(j = i; j<100; j++){
a[j+1] = b[j-i];
if(b[j-i] == '\0')
break;
}
printf("%s", a);
}
there are no syntax errors(I hope)
the compiler gives me that result: It doesn't concatenate the strings, nothing happens.
It gives me the same array the same array the user entered, Does anyone has the answer?
PS: I don't know about the pointers yet.
Implementing strcat as a "naive byte-copy loop" is not hard, just do something like this:
#include <stdio.h>
#include <string.h>
char* strdog (char* restrict s1, const char* restrict s2)
{
s1 += strlen(s1); // point at s1 null terminator and write from there
do
{
*s1 = *s2; // copy characters including s2's null terminator
s1++;
} while(*s2++ != '\0');
return s1;
}
int main(void)
{
char dst[100] = "hello ";
char src[] = "world";
strdog(dst, src);
puts(dst);
}
Professional libraries will do the copy on "aligned chunk of data" basis, to get a slight performance boost.
I have tried make a program which is fills up a string array with string that is given by the user and after that i run into a problem with the idea that how coud i examine that how many words are in the array. I examined the whitespace characterts but it does not work well, i guess .Because whatever the array contains ,it writes flase value : e.g its contain 2 words when there is only 1 word in it.
int db =0;
char array[255];
void string(char str[]){
printf("Enter a string:");
scanf("%s",str);
}
void words(char str[]){
int i=0;
int len = strlen(str);
while( str[i]!=len)
{
if(str[i]==' ')
db++;
i++;
}
}
int main(int argc,char** argv){
string(array);
words(array);
printf("its contain %d words",db);
}
You have a few problems, but the main is using scanf instead of gets. If you'll run this function you'll see that scanf fails to read beyond whitespace, where gets doesn't: (my input was "123 456 789")
void string(char str[]){
printf("Enter a string:");
scanf("%s",str);
printf("%s\n", str); // the string was scanned until 1st whitespace
gets(str);
printf("%s\n", str); // proper string was read
}
The 2nd thing to note is warnings. The return type of strlen() isn't int, it's size_t (man). Also, you are comparing not matching types (char != int):
void words(char str[]){
int i=0; // change to size_t because it is checked against len
int len = strlen(str); // change to size_t
while( str[i]!=len) // should be i != len because you check the location in the string against the length, not against the char itself!!
{
if(str[i]==' ')
db++;
i++;
}
}
The 3rd thing is logic. What if your string has indeed 2 words: "hello world"? you would only count white_spaces and assume you have only one word. I would add something like:
void words(char str[]){
size_t i=0;
size_t len = strlen(str);
printf("%s\n", str);
while(i!=len)
{
if(str[i]==' ')
db++;
i++;
}
if(i) // if i is positive, there must have been a white_space -> add the 1st word because it wasn't counted (Assuming the string must start with a word and not a white_space!!)
i++;
}
This is how I would rewrite it:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int db =0;
char array[255];
void string(char str[]){
printf("Enter a string:");
gets(str);
}
void words(char str[]){
size_t i = 0;
size_t len = strlen(str);
while(i != len)
{
if(str[i]==' ')
db++;
i++;
}
if(i)
i++;
}
int main(/*no need for argc, argv. You can leave them there, but I prefer to omit if not used*/){
string(array);
words(array);
printf("its contain %d words",db);
return 0;
}
Note that there are still some issues:
What happens if more than one white space is entered between 2 words?
What happens if a white space is the first char (I assumed not, but can it be?)
What happens if the input string is too long?
Analyse main() function
int main(int argc,char** argv){
string(array);
words(array);
printf("its contain %d words",db);
}
when you are calling words(array) function what is array ? nothing. if you are taking array as a global then what's the the needs of passing to function & catching with str .
Next,
void string(char str[]){
printf("Enter a string:");
scanf("%s",str);
}
modify above function as below if you want to scan strings with white spaces.
void string(char str[]){
int len;//define it
fgets(str,len,stdin);//TO READ STRINGS WITH WHITESPACES
}
Next come to your logic, what you want to achieve with while( str[i]!=len) ?
Rotate loop upto NULL & and then modify the condition for finding no of words as below.
void words(char str[]){
int i=0;
// int len = strlen(str);
while( str[i]! = NULL)
{
if(str[i]==' ' && str[i+1] !=' ')
db++;
i++;
}
}
complete program as
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void words(char str[]);
int db =0;
char array[255];
void string(char str[]){
int n;// define it
printf("Enter a string:");
fgets(str,n,stdin);// now data is there in str not in array variable thats why call words() function from here only it's a better option
words(str);// call from here bcz now you have str
}
void words(char str[]){
int i=0;
printf("string = %s \n",str);
while( str[i] != '\0')
{
if( (str[i]==' ' && str[i+1] !=' ') || str[i+1] == '\0')
db++;
i++;
}
printf("db = %d \n",db);
}
int main(int argc,char** argv){
string(array);
printf("its contain %d words",db);
}
I hope it will helps.
I thought it's the easiest one. You have to start with your counter
int db = 1;
I want to inverse a string, so I wrote the following:
#include<stdio.h>
#include<conio.h>
#include<string.h>
char *inverseString(char *s);
char *inverseString(char *s)
{
char *s1;
int i = 0;
s1 = (char*)malloc (strlen(s)+1);
int j= strlen(s)-1;
for (; j>=0; j--) // dont know why for(; j> 0; j--) not work
{
s1[j] = s[i];
i++;
}
return s1;
}
void main(void)
{
char string[30];
printf("string: ");
gets(string);
printf("inverse string is : %s",inverseString(string));
getch();
}
But the result has a weird character at the end.
How can i fix it?
Thanks
You have to put a terminating zero character at the end of s1:
s1[strlen(s)] = 0;
Also, instead of executing the "expensive" strlen(s) many times you should calculate the length just once by putting it to a variable and then you should use the variable instead of the strlen(s) call:
size_t len = strlen(s);
You should free the allocated memory block after printing its string content by calling the free() function call.
In this case you don't have to forward declare inverseString() and be a bit more brave and use a larger buffer size, instead of 30 lets use a more common value, for example 0x100.
The string must be terminated by '\0'. This is what marks the end of string.
The null character is often represented as the escape sequence \0 in source code string literals or character constants.
Here's more elegant inplace reversal:
void strrev(char *p)
{
char *q = p;
while(q && *q) ++q;
for(--q; p < q; ++p, --q)
*p = *p ^ *q,
*q = *p ^ *q,
*p = *p ^ *q;
}
int main(int argc, char **argv)
{
do {
printf("%s ", argv[argc-1]); strrev(argv[argc-1]);
printf("%s\n", argv[argc-1]);
} while(--argc);
return 0;
}
First of all, here is a string-reversing topic, where a pretty cool method is described: Reversing a string in C.
Then, I would advice not to use gets() as it might be dangerous (gets() is actually the reason for your error to occur!).
Finally, here is the code, which might work well for you:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
/* No prototype for inverseString is required here, since the routine call occurs
after its implementation */
char *inverseString(char *s)
{
char * s1;
int i, j;
s1 = (char *)malloc(strlen(s)+1);
i = 0;
for (i = 0, j = strlen(s) - 1; j>=0; i++, j--)
{
s1[i] = s[j];
}
return s1;
}
void main(void)
{
char string[30];
printf("string: ");
scanf("%[^\n]", &string);
printf("inverse string is : %s", inverseString(string));
getch();
}
Here is a good answer where I took scanf("%[^\n]", &string) construction from.
You should terminate your string with NUL character \0.
char *inverseString(char *s)
{
...
...
s1[++i] = '\0';
return s1;
}
NOTE: Do not use gets to read strings (it is removed from the standard now) rather you can use fgets.
fgets(string, 30, stdin);