segmentation fault when returning string from function - c

I was wondering what this code should print. I wanted to check whether it prints we can, can we or we can, but instead i got segmentation fault.
Here is the code:
char* mysubstr() {
char* x = "Yes we can, can we";
char* y = "we can";
char* tmp = x;
while(*tmp) {
if (*tmp == *y)
return *tmp;
tmp++;
}
return x;
}
void main() {
printf("%s", mysubstr());
}
I think the wrong part is the return *tmp;, but why? What's wrong with that?

Your compiler basically already told you what is wrong:
return makes pointer from integer without a cast
This is because you define a function returning a char * but you return a char.
With char *tmp = x; you define a pointer and in your return statement you dereference it.
Hence you return (char*)'w'
If you use that return value for printf value 'w' is taken an address which causes your crash.
You should just do return tmp;
This is not the only issue in your code.
Your function name indicates you want to make some substring function.
Bur your code returns immediately it found a match of first letter in second string. You don't verify if the other character also are same.

Following works:
char* mysubstr()
{
char* x = "Yes we can, can we";
char* y = "we can";
char* tmp = x;
while(*tmp)
{
if(*tmp == *y)
{
return (char*) tmp;
}
tmp++;
}
return (char*) x;
}
int main()
{
printf("%s", mysubstr());
return 0;
}
And the answer is:
**We can, can we**

Related

return a pointer in C, find value in string

I'm trying to learn C. I have a problem that asks me to loop through a string, find a value and return it.
int main(void)
{
char *hello = "Hello";
char *found_char = find_char(hello, 'e');
printf("Found char: %s\n", found_char);
}
char *find_char(char *str, int c)
{
int x;
for (x = 0; str[x] != 0; x++){
if (c == str[x]){
return str[x];
}
}
}
and I get the following error
warning:returning 'char' from a function with return type 'char *' makes pointer from integer without a cast
I have a feeling I'm returning the wrong type, but I'm still a little fuzzy on how pointers work in C. Could anyone point out what I'm doing wrong, or what is going on this the pointer in the example problem?
str[x] is a char (specifically, it is an object of char type).
&str[x] is a pointer to char, also called a char *.
Your function is declared to return char *. So return a pointer to the char.
you need to return a pointer to the string you found
return str[x];
should be
return &(str[x]);
Note that you function is identical to the standard strchr function http://man7.org/linux/man-pages/man3/strchr.3.html
Learn and understand from what the error is. It says that your returning a char but your function is defined to return pointer to a char(char)*
Instead of return str[x];, return a pointer to a char using return &str[x];.
Also there's a workaround.
You can declare your function as
char find_char(){...}
instead of
char *find_char(){...}.
Also change your printf() statement.
Here's the changes i made:
int main(void)
{
char *hello = "Hello";
char found_char = find_char(hello, 'e');
printf("Found char: %s\n", found_char);
}
char find_char(char *str, int c)
{
int x;
for (x = 0; str[x] != 0; x++){
if (c == str[x]){
return str[x];
}
}
}

Replacing a character in string

#include <stdio.h>
#include <string.h>
void replace (char a[]){
char *y;
*y = 'm';
char *p = a;
p = strchr(p, 'g');
while (p){
*p = *y;
p++;
p = strchr(p, 'g');
}
}
int main (){
char x[10];
gets(x);
replace(x);
puts(x);
return 0;
}
What's wrong with this replace function?
It doesn't output a string instead it says segmentation fault.
You're trying to write to a wild pointer here:
char *y;
*y = 'm';
y doesn't point anywhere in particular, so you get Undefined Behaviour (a seg fault in your particular case).
You are assigning value using an uninitialized pointer, y.
Why do you use pointer y anyway, instead of
*p = *y;
you can just say
*p = 'm';
y is not allocated. It is just a pointer and a pointer must point to a space in the memory. But you didn't allocate any space in the memory. So when you defferentiate it, is going to deferentiate the garbage address that a non itialized pointer has. Crash...
So rather than
char *y;
*y='p';
just write:
char y='p'; ///no pointer
Then a first improvment at the function. The function is too specific, just for a character, I would write like:
void replace (char a[],char from, char to)
{
char *p = a;
while(*p)
{
if(*p==from) *p=to;
p++;
}
}
If you compile your program with warnings enabled you should get a warning like this (with the GCC compiler):
warning: ‘y’ is used uninitialized in this function [-Wuninitialized]
*y = 'm';
^
Before you dereference the pointer y you need to know that it points to a valid object, but in your case y has not been assigned a value so it can point anywhere. Also you don't need any extra pointer; here is a more concise (and more general) version of the function:
static void replace(char old, char new, char s[])
{
s = strchr(s, old);
while (s != NULL) {
*s = new;
s = strchr(s, old);
}
}
Or without using strchr:
static void replace(char old, char new, char s[])
{
int i = 0;
while (s[i] != '\0') {
if (s[i] == old) {
s[i] = new;
}
i++;
}
}

Problems with strcat

I have a weird problem with strcat in C. This is the code:
char *getip(char n[])
{
char *x[255];
strcat(x, n);
char *ip;
ip = strtok(x, "/");
return ip;
}
char *adrr(char n[])
{
char *ip[255];
strcat(ip, getip(n));
return ip;
}
int main(void)
{
scanf("%s", &n);
printf("IP : %s\n", getip(n));
printf("IP : %s", adrr(n));
}
The first printf returns exactly what I want it to return, and although the function adrr does seemingly nothing, the second printf returns some random character at the beginning and the end of what it should return.
There are many problems in your code:
you define x in getip as char *x[255], it should be char x[255]
you should initialize x before calling strcat or use strcpy.
ip points to the local array x, returning it to the caller invokes undefined behavior as the array it points to cannot be used after the function returns.
same problems in adrr()
n is not defined in main for scanf("%s",&n);
The first function seems to work as expected out of pure luck, it may fail when compiled on a different system, or even just on a different day ;-)
Here is a solution:
#include <stdio.h>
char *getip(char *dest, const char *src) {
for (i = 0; src[i] != '\0' && src[i] != '/'; i++) {
dest[i] = src[i];
}
dest[i] = '\0';
return dest;
}
int main(void) {
char n[256];
char ip[256];
if (scanf("%255s", n) == 1) {
printf("IP: %s\n", getip(ip, n));
}
return 0;
}
n in main does not exist
I think you think about char buf[10] but write char *buf[10]
If you return a pointer to a memory that only exists inside a function than the result is undefined. Make it static or dynamic.

What is wrong with my version of strchr?

My assignment is to write my own version of strchr, yet it doesn't seem to work. Any advice would be much appreciated.
Here it is:
char *strchr (const char *s, int c) //we are looking for c on the string s
{
int dog; //This is the index on the string, initialized as 0
dog = 0;
int point; //this is the pointer to the location given by the index
point = &s[dog];
while ((s[dog] != c) && (s[dog] != '\0')) { //it keeps adding to dog until it stumbles upon either c or '\0'
dog++;
}
if (s[dog]==c) {
return point; //at this point, if this value is equal to c it returns the pointer to that location
}
else {
return NULL; //if not, this means that c is not on the string
}
}
You are trying to store an address into point but it's an int-variable. You should do something like this:
char *strchr(char *s, char c) {
int pos = 0;
while (s[pos] != c && s[pos] != '\0')
pos++;
if (s[pos] == c)
return &s[pos];
else
return NULL;
}
By the way: s should be char * not const char * because your returning an pointer to achar, and that wouldn't be a good style ;) (or return const char *)
You return "point" which was originally initialized to beginning of string and not moved since then. You don't need that variable at all, but could simply return &s[dog] (although I would prefer something more descriptive than dog as a variable name).
In fact you would survive with something as simple as this:
while (*s != c && *s)
++s;
return (*s == c) ? s : NULL;
int point;
This is not the declaration of a pointer, here is how to declare a pointer to an int:
int *bla;
In your case &s[dog] is a pointer to a const char, so you want to declare point this way:
const char *point;
And as others pointed out, you are actually ignoring this pointer in your function afterwards.
Here in your code
int point; //this is the pointer to the location given by the index
point = &s[dog];
you are trying to convert a pointer to char to an int, when
char* point = &s[dog];
is what you want. You should have seen this from the return type of your function. You want to return a char* but you return an int (your variable point) or NULL. As you never actually change point, you are actually returning the address of the first character in your array, so your code is not working as you would like anyway.
If you insist on this you would be better using
char* point = &s[dog];
while ((*point != c) && (*point != '\0')) {
++point;
}
return (*point == c) ? point : NULL;
But here it looks like you still have a conceptual problem as you want to compare a char with an int. You should work out if you need an int array or a char array. If you want a char array, change your input argument c to be of type char.

My strstr() returning null even if the string to be found is at the index 0

I implemented strstr() myself,the code works fine for all strings but when the string lies in the first index of the string,it returns null.
#include<stdio.h>
const char* mystrstr(const char *str1, const char *str2);
int main()
{
const char *str1="chal bhai nikal";
const char *str2="c",*result;
result=mystrstr(str1,str2);
if(*result!=NULL)
printf("found at %d location and the value is %s.",*result, str1+*result);
else
printf("Value not found");
getchar();
printf("\n");
return 0;
}
const char * mystrstr(const char *s1, const char *s2)
{
int i,j,k,len2,count=0;
char *p;
for(len2=0;*(s2+len2)!='\0';len2++); //len2 becomes the length of s2
for(i=0;*(s1+i)!='\0';i++)
{
if(*(s1+i)==*s2)
{
for(j=i,k=0;*(s2+k)!='\0';j++,k++)
{
if(*(s1+j)==*(s2+k))
count++;
else count=0;
if(count==len2)
{
p=(char*)malloc(sizeof(char*));
*p = i;
return p;
}
}
}
}
return NULL;
}
I haven't looked at your mystrstr function, just main.
const char *str2="c",*result;
result=mystrstr(str1,str2);
if(*result!=NULL)
printf("found at %d location and the value is %s.",*result, str1+*result);
else
printf("Value not found");
result is a const char *; *result is a const char.
Are you perhaps mixing NULL pointer and NUL zero-terminator?
result can be NULL; *result can be '\0'
Edit: possible solution
When strstr() fails to find the substring it returns NULL. Supposing your mystrstr() works the same way, you do
/* result=mystrstr(str1,str2); */
result=NULL;
and then
if(*result!=NULL) {/* ... */} else {}
but *result can try to dereference a NULL pointer, which is NOT what you want.
You want to test result itself
if (result != NULL) { /* ... */ } else {}
The problem is that you're returning an index in memory pointed to by a char* (and in this particular case, the matching index is 0, which your code is interpreting as a NULL when it checks the dereferenced result). If you want mystrstr() to have the same behavior as strstr(), you should change:
if(count==len2)
{
p=(char*)malloc(sizeof(char*));
*p = i;
return p;
}
to:
if(count==len2)
{
return s1+i;
}
so a pointer to the substring location is returned.
strstr() doesn't return an index (or a pointer to an index) - it returns a pointer to the character in the string passed as the first parameter where the instance of str2 is found (if it is found). I assume that your intent is for mystrstr() to follow that specification.
So, you'll also need to change the code that checks and deals with the returned value, but I'll leave that as an exercise for the reader.
What the above person said was ok. Because in his way, you don't need to declare a pointer to char p and use malloc to allocate memory for returning pointer to index. It can simplify your code.
But you need to change your main function accordingly.
const char* mystrstr(const char *str1, const char *str2);
int main()
{
const char *str1 = "chal bhai nikal";
const char *str2 = "bh", *result;
result = mystrstr(str1, str2);
if (result != NULL)
{
printf("found at %d location and the value is %s.\n", result - str1, result);
}
else
printf("Value not found");
getchar();
return 0;
}

Resources