Problems with strcat - c

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.

Related

Printf didn't display the first one, just after that ones

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* foo (const char* str)
{
char szo[125];
char* vege;
int i,j=0;
int db=1;
szo[0] = str[0];
for(i=1; i<strlen(str)+1; i++)
{
if(str[i] == str[i-1] )
{
db++;
}
else
{
j++;
szo[j] = db + '0';
j++;
szo[j] = str[i];
db=1;
}
}
j++;
szo[j] = '\0';
vege = szo;
return vege;
}
int main()
{
char *s[] = {"hello", "world", "Mississippi"};
int i;
for (i = 0; i < sizeof(s) / sizeof(char *); ++i)
{
char *p = foo(s[i]);
printf("%s\n", p);
}
return EXIT_SUCCESS;
}
I've tried to do first a printf("\n"), then its good, but i have a empty first line.
Someone can please help me.Thanks a lot.
Or if anyone can help me, the original tasks say a free(p) in the main after the printf, how can i change everything to work with malloc?
szo ceases to exist right before foo() returns.
Yet you return a pointer to that array and try to use it outside the function.
If you're not ever going to call foo recursively, or in parallel in several threads, or as different arguments of another function, try static char szo[125]; and remember to document that the function returns a pointer to a static array so that you don't invoke UB in 6 months time
char *foo(const char *str) {
static char szo[125];
//...
return szo;
}
printf("%s\n", foo("something")); //ok
printf("%s\n", foo("some other thing")); //ok
//printf("%s\n%s\n", foo("something"), foo("some other thing")); //NO
char* foo (const char* str)
{
char szo[125];
...
vege = szo;
return vege;
}
you return pointer to the local variable which does not exist after the return from the function. One of the most common UBs

return pointer from a function in c

Write function that gets a string s and char c that checks whether the char shows in s, if yes return a pointer to the first place that c shows in s
Here is my code. I am not sure what I did about "return the pointer", is this correct?:
#include <stdio.h>
char *foo(char s[], char c)
{
int i;
char *ptr;
for(i=0;s[i];i++)
{
if(s[i]==c)
{
printf("result: %d",i);
*ptr=i;
return ptr;
}
}
}
void main()
{
char s[]="Error404";// some string
char c='r';// some char
foo(s,c);
}
First of all, your specification is unclear. Before you start coding, make sure that the specification makes sense. It doesn't say what to do if you don't find the character, so you can't write this function before you know that.
Your function must always return something, even if the character was not found. A common way to implement this would be to return a null pointer in that case.
Your pointer should point at the found character, not at i which is an integer, that doesn't make any sense.
Correct the code into something like this:
char* foo (char s[], char c)
{
char *ptr = NULL;
for(int i=0; s[i]!='\0'; i++)
{
if(s[i]==c)
{
ptr = &s[i]; // point at the address of item number i in s
break;
}
}
return ptr; // will return NULL if not found, otherwise a pointer to the found item
}
If s is a string, then s[i] represents the ith char in the string, while s + i represents a pointer to the ith char in the string. So you want to return s + i. You probably also want to return NULL if the char is not found.
#include <stdio.h>
char *foo(char s[], char c)
{
int i;
for(i = 0; s[i]; i++)
{
if(s[i] == c)
return (s + i);
}
return (NULL);
}

Trying to make a function in C that copies one string onto another

I have to make a function that accepts two string pointers as arguments - one having content, and one being empty, and that copies the content of the first one onto the second one.
How would I go about doing this? Here is the code I have, but it just crashes when run:
#include <stdio.h>
void strcopy1(char* mainStr[], char* emptyStr[], int size)
{
for(int i = 0; i < size; i++)
{
*emptyStr[i] = *mainStr[i]; //The issue is on this line. How do I do this?
}
}
int main(void)
{
char *s1 = "Barrel";
char *e1;
printf("mainStr is: %s\n", s1);
printf("emptyStr is: %s\n", e1);
strcopy1(&s1, &e1, 7);
printf("mainStr is: %s\n", s1);
printf("emptyStr is: %s\n", e1);
}
Thanks in advance.
Several problems:
You didn't allocate space for the destination string.
You don't need to pass pointers to the variables, just pass the pointer variables themselves.
You can't print the empty string before calling the function, since you haven't initialized any of its contents.
The elements of the arrays are char, not pointer to char, so you don't need to use *mainStr[i] or *emptyStr[i].
Code:
#include <stdio.h>
void strcopy1(char mainStr[], char emptyStr[], int size)
{
for(int i = 0; i < size; i++)
{
emptyStr[i] = mainStr[i];
}
}
int main(void)
{
char *s1 = "Barrel";
size_t len = strlen(s1) + 1; // Add 1 for the trailing null byte
char *e1 = malloc(len);
printf("mainStr is: %s\n", s1);
strcopy1(s1, e1, len);
printf("mainStr is: %s\n", s1);
printf("emptyStr is: %s\n", e1);
free(e1); // Always free dynamically-allocated memory
}
I think the problem lies in the line where you are calling the function. I found a solution for you that works fine.
copy_string(char *target, char *source)
{
while(*source)
{
*target = *source;
source++;
target++;
}
*target = '\0';
}
This function will do the trick for you.
First you're trying to display a non initialized String which is impossible.
Second, I don't understand why the parameters are an array of pointers.
Here's what I propose :
void strcopy1(char *mainStr, char *emptyStr) {
while (*mainStr) {
*emptyStr = *mainStr;
mainStr++;
emptyStr++;
}
*emptyStr = '\0';
}
int main(void)
{
char *s1 = "Barrel";
char *e1;
printf("mainStr is: %s\n", s1);
strcopy1(&s1, &e1);
printf("mainStr is: %s\n", s1);
printf("emptyStr is: %s\n", e1);
}
The following is your code with corrections annotated in-line:
// pointer to pointer is not needed, change argument to char *
//void strcopy1(char* mainStr[], char* emptyStr[], int size)
void strcopy1(char* mainStr, char* emptyStr, int size)
{
for(int i = 0; i < size; i++)
{
//*emptyStr[i] = *mainStr[i]; //The issue is on this line. How do I do this?
emptyStr[i] = mainStr[i]; //reference variable, not pointer to variable
}
}
int main(void)
{
char *s1 = "Barrel";
char *e1 = {0}; // initialize variable
e1 = malloc(strlen(s1)+1); //allocate memory to target string (+1 for NULL)
if(e1)//ensure e1 memory was created
{
printf("mainStr is: %s\n", s1);
printf("emptyStr is: %s\n", e1);
strcopy1(s1, e1, 7); //string variables are already pointers
//no need for the "address of" operator
printf("mainStr is: %s\n", s1);
printf("emptyStr is: %s\n", e1);
free(e1); //always free memory when explicitly created using malloc()
}
return 0;//add return to match your 'main' prototype
}
In answer to your question in comments:
After changing the e1 line to be "char *e1[7];" or "char e1 = " "; and removing the ampersands, it still crashes.
1) Changing char *e1 to char *e1[7] is creating char *[7], but you need either a char * or a char [7] for the job. Either will create containers adequate for use as a C string passed as an argument. (however char * needs memory allocated ([m][c]alloc) before use)
2) Regarding removing ampersands, this was explained above as well, but basically, the & is the address of operator, since C string names (variables) are already pointing to the address of the string, the & operator is not needed.

simple strcat implementation with pointers

so I was practicing writing c code with pointers using the K&R. For one problem with strcat function, I couldn't find out what was wrong with my code, which according to Visual Studio, returned the destination string unchanged after the strcat function. Any suggestion is appreciated!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int strcat(char* s, char* t);
int main(void)
{
char *s="hello ", *t="world";
strcat(s,t);
printf("%s",s);
return 0;
}
int strcat(char* s,char* t)
{
int i;
i=strlen(s)+strlen(t);
s=(char*) malloc(i);
while(*s!='\0')
s++;
while('\0'!=(*s++=*t++))
;
return 0;
}
I'm pretty sure that strcat returns a char* in the real implementation (holding the original value of the first string).
strcat is not supposed to alter the first parameter's address, so you shouldn't call malloc.
Point #2 means that you need to declare char *s as char s[20] in main (where 20 is some arbitrary number big enough to hold the whole string).
If you really want to alter the value of the an input parameter you will need to pass the address of the value - so it would need to be strcat(char **s, ...) in the function declaration/definition, and called with strcat(&s, ...) in main.
1) defining string in this way
char *s="hello "
means that you are defined a literal string. a literal string is saved into read only memory so you can not edit it
you have to define your string as a char array in order to be able to edit it
char s[100] = "hello ";
2) when you define your function in this way
int strcat(char* s,char* t)
you can not change the address of s into the function strcat(). So assigning memory with malloc() into the function will not change the s address when leaving the function
3) change your function strcat to
int strcat(char** s,char* t)
{
int i;
char *u, *v;
i=strlen(*s)+strlen(t);
v = *s;
u=(char*) malloc(i+1);
while(*v!='\0')
*u++ = *v++;
while('\0'!=(*u++=*t++));
*s = u;
return 0;
}
and you call it in the main with:
char *s="hello ", *t="world";
strcat(&s,t);
In
strcat(char* s, char* t)
the 's' is send by value. The value of 's' at call time is copied into the stack then strcat() is call. At the return of strcat the modified version is discard from the stack. So the calling value of 's' is never changed (and you create a memory leak).
Beward, in C every memory cell can be change, even parameters or instructions sections; some changes can be very hard to understand.
Since you are trying to do like the real strcat it's said that the first parameter
The string s1 must have sufficient space to hold the result.
so you don't need to use malloc
char *strcat(char* s, const char* t);
int main(void)
{
char s[15] = {0}; //
char *t = "world"; //const char * so you can't change it
strcpy(s, "Hello ");
strcat(s,t);
printf("%s\n",s);
return (0);
}
char *strcat(char* s, const char* t)
{
int i = 0;
while (s[i] != '\0')
i++;
while (*t != '\0')
s[i++] = *t++;
s[i] = '\0'; //useless because already initialized with 0
return (s);
}
#include<stdio.h>
#include<string.h>
#define LIMIT 100
void strcatt(char*,char*);
main()
{
int i=0;
char s[LIMIT];
char t[LIMIT];
strcpy(s,"hello");
strcpy(t,"world");
strcatt(s,t);
printf("%s",s);
getch();
}
void strcatt(char *s,char *t)
{
while(*s!='\0')
{
s++;
}
*s=' ';
++s;
while(*t!='\0')
{
*s=*t;
s++;
t++;
}
*s=*t;
}
Dear user,
you don't have to complicate things that much. The simpliest code for strcat, using pointers:
void strcat(char *s, char *t) {
while(*s++); /*This will point after the '\0' */
--s; /*So we decrement the pointer to point to '\0' */
while(*s++ = *t++); /*This will copy the '\0' from *t also */
}
Although, this won't give you report about the concatenation's success.
Look at this main() part for the rest of the answer:
int main() {
char s[60] = "Hello ";
char *t = "world!";
strcat(s, t);
printf("%s\n", s);
return 0;
}
The s[60] part is very important, because you can't concatenate an another string to it's end if it doesn't have enough space for that.

C simple string program does not compile

#include <stdio.h>
#include <string.h>
char Jones(char, char);
int main() {
char name[]="Andrew";
char surname[]="Jones";
char result[80];
result=Jones(name, surname);
puts(result);
return 0;
}
char Jones(char name, char surname)
{
char result[80];
int length;
length = strlen(surname);
for (int i=0; i<50; i++)
{
result[length+i] = name[i];
}
return result;
}
The program does not compile and i dont know why. It is supposed to read two strings and swap their places. It should display eg. "Jones Andrew".
Here's one problem:
char name[]="Andrew";
char surname[]="Jones";
char result[80];
wynik=Jones(name, surname);
This calls Jones() with character arrays (which will decay to character pointers), but the function is declared to accept single characters only.
You should change the function to take char *name, char *surname, since it really does seem to expect strings.
Further, you can't return a character array like you're doing in Jones(), you need to read up quite a bit on how to work with strings in C.
Also, wynik looks undeclared, that'll also make it fail to build.
There's a few errors:
char Jones(char, char);
This takes just a single char, not a char * which you need for a string.
result=Jones(name, surname);
Here result is an array. In C, you cannot assign to an array.
char Jones(char name, char surname)
{ char result[80];
...
return result;
}
Here you return result which is a local variable. But to return a string, you'd need to return a char*. But that char* would point to a local variable within the Jones function, which is no longer valid when the function ends. One solution is to pass in a buffer where you write the result that the caller owns.
Your algorithm for combining the surename and name is also wrong, you never do anything with the surename.
You'll need to do this:
char *Jones(char*, char* , char *);
int main() {
char name[]="Andrew";
char surname[]="Jones";
char result[80];
char *p;
p = Jones(name, surname, result);
puts(p);
return 0;
}
char *Jones(char *name, char *surname, char *result)
{
int length;
int i,k;
length = strlen(surname);
for (i=0; i<length ; i++)
{
result[i] = surname[i];
}
result[i++] = ' '; //add a space
length = strlen(name);
for (k=0; k<length ; k++, i++)
{
result[i] = name[k];
}
result[i] = 0; //add nul terminator to end the string
return result;
}
The conatenation could be simplified in many ways, e.g. to
strcpy(result, surename);
strcat(result, " ");
strcat(result, name);
or the Jones function could just do:
sprintf(result, "%s %s", surename, name);
In all cases, the function is rather fragile, as it's easy to overflow the result buffer if you pass in something else that does not fit within the result buffer.
1) The name and surname are char array and not single char so you have to change the input parameters types of your function Jones() the input parameters types should be char name[] (char array) or char *name (pointer to array of char)
2) You can not return an array defined locally and statically in the function. and if you want to return a string from the function, the string should be constant or it should be a buffer allocated dynamically (with malloc, calloc, realloc) into the function And for both cases the function type should be char *Jonas() and not char Jonas()
Or you can pass the result array via input parametr. and in this case you can fill it into the function.
void Jones(char *name, char *surname, char *result)
and in the main:
char result[80];
Jones(names, surname, result);
3) The following for loop is missing some thing
for (int i=0; i<50; i++)
{
result[length+i] = name[i];
}
The result elements from element 0 to element length are containing garbage because the result array is not initiated. so when you printf the result array you will get garbages printed. You have to initiate elements between 0 to length in the result array
#include <stdio.h>
#include <string.h>
char* Jones(char*, char*);
int main() {
char name[]="Andrew";
char surname[]="Jones";
puts(Jones(name,surname));
return 0;
}
char* Jones(char *name, char *surname)
{
strcat(surname," ");
strcat(surname,name);
return surname;
}

Resources