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);
Related
I have a char array s[11]="0123456789"; and I want to be able to take each digit s[i](using a for loop) and cast it somehow to a char*(I need a char* specifically because I need to use strncat on some other string)
I've been trying to do this for the past 4 hours and I couldn't get anything done.
Unless you're willing to temporarily modify s, or copy the character somewhere else... You're going to have a hard time.
Modify s temporarily.
int main() {
char s[11] = "0123456789";
for (int i = 0; i < strlen(s); i++) {
// Modify s in place.
const char tmp = s[i+1];
s[i+1] = '\0';
char *substr = &s[i];
// Do something with substr.
printf("%s\n", substr);
// Fix s
s[i+1] = tmp;
}
}
Or copy s[i] to a new string.
int main() {
char s[11] = "0123456789";
for (int i = 0; i < strlen(s); i++) {
// Create a temporary string
char substr[2];
substr[0] = s[i];
substr[1] = '\0';
// Do something with substr.
printf("%s\n", substr);
}
}
Or maybe just don't use strncat?
Assuming you're actually using strncat or similar... Those functions are pretty trivial, especially if you are appending only a single character. You might just create your own version.
void append_character(char *buffer, int buffer_size, char new_character) {
int length = strlen(buffer);
if (length + 2 < buffer_size) {
buffer[length] = new_character;
buffer[length+1] = '\0';
} else {
// No space for an additional character, drop it like strncat would.
}
}
Or you could do it as a simple wrapper around strncat:
void append_character(char *buffer, int buffer_size, char new_character) {
char new_string[2] = { new_character, '\0' };
strncat(buffer, buffer_size, new_string);
}
What you are requesting does not make any sense. A char is a small number. A pointer is the address of some memory. Converting a char to a pointer won't give you a valid pointer, but a pointer that will crash as soon as it is used.
For strncat, you need an array of characters containing a C string. You could create a string by writing char array[2]; (now you have an array with space for two characters), then array[0] = whateverchar; array[1] = 0; and now you have a C string with space for exactly one char and one trailing zero byte.
Yet another idea:
#include <stdio.h>
#include <string.h>
int main(void)
{
char src[11]="0123456789";
char dest[50]="abc";
char* p = src;
int i = 0;
int len = strlen(src);
for (i = 0; i < len; i++)
{
strncat(dest,p,1);
p++;
}
printf("src: %s\n", src);
printf("dest: %s\n", dest);
return 0;
}
Compiled with gcc under Ubuntu:
$ gcc hello_str.c -o hello_str
Output:
$ ./hello_str
src: 0123456789
dest: abc0123456789
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.
char * removeChar(char * str, char c){
int len = strlen(str);
int i = 0;
int j = 0;
char * copy = malloc(sizeof(char) * (len + 1));
while(i < len){
if(str[i] != c){
copy[j] = str[i];
j++;
i++;
}else{
i++;
}
}
if(strcmp(copy, str) != 0){
strcpy(str,copy);
}else{
printf("Error");
}
return copy;
}
int main(int argc, char * argv[]){
char str[] = "Input string";
char * input;
input = removeChar(str,'g');
printf("%s\n", input);
free(input);
return 0;
}
I don't know why every time I try to run it ,it always says uninitialized variable and sticks in the strcpy line and printf line.
Basically this function is to take a string, and a character and removes the that character from the string (because I am learning malloc so that's why I wrote the function like this).
After the while loop do:
copy[j] = '\0';
to NULL-terminate your string; that way it can work with methods coming from <string.h>, which assume that the string is nul-terminated.
PS: One warning you should see is about not returning copy in your function in any case, because now if the condition of the if statement is wrong, your function won't return something valid, so add this:
return copy;
at the end of your function (which is now corrected with your edit).
Other than that, the only warning you should still get are for the unused arguments of main(), nothing else:
prog.c: In function 'main':
prog.c:32:14: warning: unused parameter 'argc' [-Wunused-parameter]
int main(int argc, char * argv[]){
^~~~
prog.c:32:27: warning: unused parameter 'argv' [-Wunused-parameter]
int main(int argc, char * argv[]){
^~~~
While you copy over bytes from str to copy, you don't add a terminating null byte at the end. As a result, strcmp reads past the copied characters into unitialized memory, possibly past the end of the allocated memory block. This invokes undefined behavior.
After your while loop, add a terminating null byte to copy.
Also, you never return a value if the if block at the end is false. You need to return something for that, probably the copied string.
char * removeChar(char * str, char c){
int len = strlen(str);
int i = 0;
int j = 0;
char * copy = malloc(sizeof(char) * (len + 1));
while(i < len){
if(str[i] != c){
copy[j] = str[i];
j++;
i++;
}else{
i++;
}
}
// add terminating null byte
copy[j] = '\0';
if(strcmp(copy, str) != 0){
strcpy(str,copy);
}
// always return copy
return copy;
}
You never initialised input and the some compilers don't notice,
that the the value is never used before the line
input = removeChar(str, 'g');
in your code. So they emit the diagnostic just to be sure.
strcpy(str, copy)
gets stuck in your code, as copy never got a closing 0 byte and
so depends on the nondeterministic content of your memory at the
moment of the allocation of the memory backing copy, how long strcpy
will run and if you get eventually a SIGSEGV (or similar).
strcpy will loop until it finds a 0 byte in your memory.
For starters to remove a character from a string there is no need to create dynamically a character array and then copy this array into the original string.
Either you should write a function that indeed removes the specified character from a string or a function that creates a new string based on the source string excluding the specified character.
It is just a bad design that only confuses users. That is the function is too complicated and uses redundant functions like malloc, strlen, strcmp and strcpy. And in fact it has a side effect that is not obvious. Moreover there is used incorrect type int for the length of a string instead of the type size_t.
As for your function implementation then you forgot to append the terminating zero '\0' to the string built in the dynamically allocated array.
If you indeed want to remove a character from a string then the function can look as it is shown in the demonstrative program.
#include <stdio.h>
char * remove_char(char *s, char c)
{
char *p = s;
while (*p && *p != c) ++p;
for ( char *q = p; *p++; )
{
if (*p != c) *q++ = *p;
}
return s;
}
int main( void )
{
char str[] = "Input string";
puts(str);
puts(remove_char(str, 'g'));
return 0;
}
The program output is
Input string
Input strin
If you are learning the function malloc and want to use it you in any case should try to implement a correct design.
To use malloc you could write a function that creates a new string based on the source string excluding the specified character. For example
#include <stdio.h>
#include <stdlib.h>
char * remove_copy_char(const char *s, char c)
{
size_t n = 0;
for (const char *p = s; *p; ++p)
{
if (*p != c) ++n;
}
char *result = malloc(n + 1);
if (result)
{
char *q = result;
for (; *s; ++s)
{
if (*s != c) *q++ = *s;
}
*q = '\0';
}
return result;
}
int main( void )
{
char *str = "Input string";
puts(str);
char *p = remove_copy_char(str, 'g');
if ( p ) puts(p );
free(p);
return 0;
}
The program output will be the same as above.
Input string
Input strin
Pay attention to the function declaration
char * remove_copy_char(const char *s, char c);
^^^^^^
In this case the source string can be a string literal.
char *str = "Input string";
#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
The code says at many places "invalid indirection".Please help.
int main()
{
char *s1,*s2,*position;
printf("Enter string:\n");
gets(s1);
printf("Enter word to find:\n");
gets(s2);
*position=ststr(*s1,*s1);
if(*position)
printf("word is found at %c loc\n",*position);
else
printf("word not found");
getch();
return 0;
}
char *strstr(char *s1,char *s2)
{
int flag=1;
char i,j;
for(i=0; ;i++)
{
if(*s1[i]==*s2[0])
for(j=i;*s2;j++)
{
if(*s1[j]!=*s2[j])
flag=0;
}
}
if(flag)
return i;
else
return 0;
}
First, s1 and s2 in main have not been initialized to point anywhere meaningful. Either declare them as static arrays, or allocate memory to them at runtime using malloc() or calloc():
#define SIZE 20 // or some number big enough to hold your input
...
char s1[SIZE], s2[SIZE], *position; // s1 and s2 declared statically
Second, NEVER NEVER NEVER NEVER NEVER use gets(); it will introduce a point of failure in your program. Use fgets() instead:
if (fgets(s1, sizeof s1, stdin) != NULL)
// process s1
else
// check for EOF or error on read
EDIT
And like everyone else has pointed out, your comparison in the strstr() function needs to be either
*s1 == *s2
or
s1[i] == s2[i]
but first you need to deal with allocating your buffers in main properly.
One of the problems I'm noticing is whenever you do *s1[j]. The asterisk is dereferencing the array, and so is the [] notation.
s[i] really means *(s + i), so you don't have to dereference it again. The way you have it would read **(s + i), and since it's a single pointer you can't do that.
if(*s1[i]==*s2[0])
is such an example where my gcc complains:
error: invalid type argument of ‘unary *’ (have ‘int’)
if s1 is a pointer to char, s1[i] is a char. So you can't dereference it any more (with the *), i.e. s1[i] does not point to anything any more.
Try
if(s1[i]==s2[0])
instead.
You should also change the return value of strstr: you return an integer where you declare to return a pointer to a character. So try returning s1+i instead.
This here:
for(j=i;*s2;j++)
probably does not what you want. You're not advancing the pointer s2 anywhere in the loop, in fact you're just testing whether s2[0] (which is the same as *s2) is zero for each iteration. If s2 isn't the empty string, this loop will never terminate.
#include "stdio.h"
char *strstr(char *str, char *substr)
{
int len = strlen(substr);
char *ref = substr;
while(*str && *ref)
{
if (*str++ == *ref)
{
ref++;
}
if(!*ref)
{
return (str - len);
}
if (len == (ref - substr))
{
ref = substr;
}
}
return NULL;
}
int main(int argc, char *argv[])
{
printf("%s \n", strstr("TEST IS NOT DONE", "IS NOT"));
}
if(*s1[j]!=*s2[j])
*s1 means "the character where s1 is pointing".
s1[j] means "*(s1+j)" or "the character j positions after where s1 is pointing"
You have to use one or the other; not both.
#include <stdio.h>
char* my_strstr(char *s2, char *s1)
{
int i, j;
int flag = 0;
if ((s2 == NULL || s1 == NULL)) return NULL;
for( i = 0; s2[i] != '\0'; i++)
{
if (s2[i] == s1[0])
{
for (j = i; ; j++)
{
if (s1[j-i] == '\0'){ flag = 1; break;}
if (s2[j] == s1[j-i]) continue;
else break;
}
}
if (flag == 1) break;
}
if (flag) return (s2+i);
else return NULL;
}
int main()
{
char s2[] = "This is the statement";
char s1[] = "the";
char *temp;
temp = my_strstr(s2,s1);
printf("%s\n",temp);
return 0;
}