I decided to try to make a concatenating function as strcat doesn't work for chars, only strings.
#include <stdio.h>
#include <string.h>
char concat(char a[], char b[]);
int main ()
{
char *con = concat("hel", "lo");
return(0);
}
char concat(char a[], char b[]){
int lena = strlen(a);
int lenb = strlen(b);
char con[lena+lenb];
con[0] = a;
con[lena] = b;
printf("%s", con);
return con;
}
This code prints "Ã…ÃÆ". Not sure where I am going wrong?
Thanks
First, you shouldn't return reference to temporary
char con[lena+lenb];
(note that the garbage you get doesn't come from that since you print within the function)
Second, you don't allocate enough memory: should be (with first problem fixed):
char *con = malloc(lena+lenb+1);
then use strcpy/strcat anyway, it's faster, and your original code doesn't do anything useful (mixing chars with array of chars & the size of the arrays isn't known at this moment: that's the reason of the garbage you're getting):
strcpy(con,a);
strcat(con,b);
Or as some suggest that they're unsafe functions, and since we know the size of inputs we can write:
memcpy(con,a,lena);
memcpy(con+lena,b,lenb+1);
Also: the prototype of concat is really wrong. It should be:
char *concat(const char *a, const char *b){
(as it returns a pointer on chars not a char. And the arguments should be constant pointers so you can use your function with any string)
and you're done (don't forget to free the string when you're done with it)
Fixed code (tested, surprisingly returns hello, maybe because it compiles without errors with gcc -Wall -Wwrite-strings -Werror. My advice: turn the warnings on and read them. You'll solve 80% of your problems that way):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *concat(const char *a, const char *b);
int main ()
{
char *con = concat("hel", "lo");
printf("%s\n",con);
return(0);
}
char *concat(const char *a, const char *b){
int lena = strlen(a);
int lenb = strlen(b);
char *con = malloc(lena+lenb+1);
// copy & concat (including string termination)
memcpy(con,a,lena);
memcpy(con+lena,b,lenb+1);
return con;
}
Related
I need to put 3 strings on an array[3][3].
I tried to do it with pointers, but I only receive a single character.
#include <stdio.h>
int array[3][3]
char thing[5] = "thing";
main()
{
thing = array[0][0];
printf("%s", array[0][0];
}
Try this. With due respect your code absolutely incorrect and need many changes. You need to update your programming skills too.
#include <stdio.h>
#include <string.h>
char array[3][6]={0};
char *thing = "this";
main()
{
strcpy(array[0],thing);
printf("%s\n", array[0]);
}
I'm new to C and I'm having a hard time understanding how to call methods with pointers. Currently this code should reverse a null-terminated string, but I get the errors
main.c:8:12: error: use of undeclared identifier 'sas'
char* N = sas;
^ main.c:10:10: warning: incompatible integer to pointer conversion passing 'char' to parameter of type
'char *'; remove * [-Wint-conversion]
reverse(*N);
^~ ./header.h:3:27: note: passing argument to parameter 'N' here EXTERN void reverse(char *N);
My actual code is this:
Main:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
int main(int argc, char *argv[])
{
char* N = sas;
reverse(*N);
}
reverse:
#include <stdio.h>
#include "header.h
#include <stdlib.h>
void reverse(char *str)
{
char* end = str;
char temp;
printf("this is *str: %c\n", *str);
if (str)
{
while (*end)
{
++end:
}
end--;
while (str < end)
{
temp = *str
*str++ = *end;
*end-- = temp;
}
}
}
header.h:
#define EXTERN extern
EXTERN void reverse(char *N)
thanks for the help and time!
int main(int argc, char *argv[])
{
char* N = "sas";
reverse(*N);
}
First you make N point to a string constant. Then you try to reverse what N points to. But since N points to a string constant, you're trying to reverse a string constant. By definition, constants cannot have their values changed.
First of all, there're many syntax errors within that piece of code:
'sas' what is that? your compiler thinks it's a variable but can't find any with that name. if you wanted to put a "sas" string, then:
char* N = "sas";
inconsistant brackets. More closing brackets than opening ones, and no opening bracket after declaring your function.
As I understand it, you are trying to reverse a string. This is just a slight modification of your code.
Full Source:
#include <stdio.h>
#include <stdlib.h>
void reverse(char *N);
int main(int argc, char *argv[])
{
char strSas[] = "sas";
reverse(strSas);
}
void reverse(char *str)
{
char* end = str;
char temp;
if(str) {
printf("this is *str: %c\n", *str);
while(*end) {
++end;
}
end--;
while(str < end) {
temp = *str;
*str = *end;
*end = temp;
++str;
--end;
}
}
}
I am starting to learn about pointers in C.
How can I fix the error that I have in function x()?
This is the error:
Error: a value of type "char" cannot be assigned to an entity of type "char *".
This is the full source:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
void x(char **d, char s[]) {
d = s[0]; // here i have the problem
}
void main() {
char *p = NULL;
x(&p, "abc");
}
In function x() you pass d which is a char ** (a pointer to a string pointer), and char s[] (an array of char, passed as similarly to a pointer to char).
So in the line:
d = s[0];
s[0] is a char, whereas char **d is a pointer to a pointer to char. These are different, and the compiler is saying you cannot assign from one to the other.
However, did your compiler really warn you as follows?
Error: a value of type "char" cannot be assigned to an entity of type "char *"
Given the code sample, it should have said char ** at the end.
I think what you are trying to make x do is copy the address of the string passed as the second argument into the first pointer. That would be:
void x(char **d, char *s)
{
*d = s;
}
That makes p in the caller point to the constant xyz string but does not copy the contents.
If the idea was to copy the string's contents:
void x(char **d, char *s)
{
*d = strdup(s);
}
and ensure you remember to free() the return value in main(), as well as adding #include <string.h> at the top.
A more proper way would be to use strcpy:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
void x(char **d) {
*d = malloc(4 * sizeof(char));
strcpy(*d, "abc");
}
int main() {
char *p;
x(&p);
printf("%s", p);
free(p);
return 0;
}
Outputs: abc
This question already has answers here:
Passing address of array as a function parameter
(6 answers)
Closed 9 years ago.
I'm writing a function that gets a string, allocates memory on the heap that's enough to create a copy, creates a copy and returns the address of the beginning of the new copy.
In main I would like to be able to print the new copy and afterwards use free() to free the memory. I think the actual function works although I am not the char pointer has to be static, or does it?
The code in main does not work fine...
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int make_copy(char arr[]);
int main()
{
char arrr[]={'a','b','c','d','e','f','\0'};
char *ptr;
ptr=make_copy(arrr);
printf("%s",ptr);
getchar();
return 0;
}
int make_copy(char arr[])
{
static char *str_ptr;
str_ptr=(char*)malloc(sizeof(arr));
int i=0;
for(;i<sizeof str_ptr/sizeof(char);i++)
str_ptr[i]=arr[i];
return (int)str_ptr;
}
OK, so based on the comments. A revised version:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
char* make_copy(char arr[]);
int main()
{
char arrr[]={"abcdef\0"};
char *ptr=make_copy(arrr);
printf("%s",ptr);
getchar();
return 0;
}
char* make_copy(char arr[])
{
static char *str_ptr;
str_ptr=(char*)malloc(strlen(arr)+1);
int i=0;
for(;i<strlen(arr)+1;i++)
str_ptr[i]=arr[i];
return str_ptr;
}
Or even better:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* make_copy(char arr[]);
int main()
{
char arrr[]={"abcdef\0"};
printf("%s",make_copy(arrr));
getchar();
return 0;
}
char* make_copy(char arr[])
{
char *str_ptr;
str_ptr=(char*)malloc(strlen(arr)+1);
return strcpy(str_ptr,arr);
}
You're on the right track, but there are some issues with your code:
Don't use int when you mean char *. That's just wrong.
Don't list characters when defining a string, write char arrr[] = "abcdef";
Don't scale string alloations by sizeof (char); that's always 1 so it's pointless.
Don't re-implement strcpy() to copy a string.
Don't cast the return value of malloc() in C.
Don't make local variables static for no reason.
Don't use sizeof on an array passed to a function; it doesn't work. You must use strlen().
Don't omit including space for the string terminator, you must add 1 to the length of the string.
UPDATE Your third attempt is getting closer. :) Here's how I would write it:
char * make_copy(const char *s)
{
if(s != NULL)
{
const size_t size = strlen(s) + 1;
char *d = malloc(size);
if(d != NULL)
strcpy(d, s);
return d;
}
return NULL;
}
This gracefully handles a NULL argument, and checks that the memory allocation succeeded before using the memory.
First, don't use sizeof to determine the size of your string in make_copy, use strlen.
Second, why are you converting a pointer (char*) to an integer? A char* is already a pointer (a memory address), as you can see if you do printf("address: %x\n", ptr);.
sizeof(arr) will not give the exact size. pass the length of array to the function if you want to compute array size.
When pass the array to function it will decay to pointer, we cannot find the array size using pointer.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *strdup(const char *str)
{
char *s = (char*)malloc(strlen(str)+1);
if (s == NULL) return NULL;
return strcpy(s, str);
}
int main()
{
char *s = strdup("hello world");
puts(s);
free(s);
}
Points
~ return char* inside of int.
~ you can free the memory using below line
if(make_copy!=NULL)
free(make_copy)
Below is the modified code.
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
char* make_copy(char arr[]);
int main()
{
char arrr[]={'a','b','c','d','e','f','\0'};
char *ptr;
ptr=make_copy(arrr,sizeof(arrr)/sizeof(char));
printf("%s",ptr);
printf("%p\n %p",ptr,arrr);
getchar();
return 0;
}
char* make_copy(char arr[],int size)
{
char *str_ptr=NULL;
str_ptr=(char*)malloc(size+1);
int i=0;
for(;i<size;i++)
str_ptr[i]=arr[i];
str_ptr[i]=0;
return str_ptr;
}
Here is my code:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int cmp(const void *a, const void *b) {
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcmp(*ia, *ib);
}
void print_array(char **array, size_t len) {
size_t i;
for(i=0; i<len; i++) {
printf("%s, ", array[i]);
}
putchar('\n');
}
int main(int argc, char *argv[]) {
char *strings[] = { "z1.doc", "z100.doc", "z2.doc", "z3.doc", "z20.doc"};
size_t strings_len = sizeof(strings) / sizeof(char *);
print_array(strings, strings_len);
qsort(strings, strings_len, sizeof(char *), cmp);
print_array(strings, strings_len);
system("PAUSE");
return 1;
}
the actual output is
z1.doc, z100.doc, z2.doc, z20.doc, z3.doc
and I want it to be
z1.doc, z2.doc, z3.doc, z20.doc, z100.doc
What am doing wrong?
The actual output is correct, the string "z100.doc" is less than "z2.doc". The strcmp compares character by character and when it gets to the '1' that is less than '2' and it stops there, so z100 < z2.
If you name the files z001.doc, z002.doc, z003.doc, z020.doc, z100.doc it will sort the way you want.
Change your comparator to say:
return (atoi(*ib + 1) - atoi(*ia + 1));
You want a natural sorting algorithm as opposed to the ASCIIbetical sorting algorithm provided by default. See Jeff's blog entry for a long rant about this, and some nice links to implementations of this natural algorithm. Just as a warning, the correct implementation (as opposed to the hacky answer you've accepted) is quite complicated, so don't try to implement it yourself, take someone else's (hopefully public domain or liberally licensed) implementation and use that instead.