C pointers and calling methods? - c

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;
}
}
}

Related

C - Pass Array of Strings as Function Parameter

I need to pass a pre-allocated array of strings as a function parameter, and strcpy() to each of the strings within the string array, as in this example:
static void string_copy(char * pointer[]) {
strcpy(pointer[0], "Hello ");
strcpy(pointer[1], "world");
}
int main(int argc, const char * argv[]) {
char my_array[10][100];
string_copy(my_array);
printf("%s%s\n", my_array[0], my_array[1]);
}
And the resulting printed string would be 'Hello world'.
How do I pass a pre-allocated string array and fill out each string within a function as shown above?
When you are doing string_copy(my_array), you are passing a char (*)[100], i.e. pointer to char[100] array to your function. But your function is expecting a char *[], i.e. array of char pointers, because you have defined your function that way.
You can fix this by making changes so that your function (string_copy()) expects a char (*)[100], instead of a char *[].
For this, you can change your function definition as:
/* Your my_array gets converted to pointer to char[100]
so, you need to change your function parameter
from `char *pointer[]` to `char (*pointer)[100]`
*/
/* static void string_copy(char *pointer []) */
static void string_copy(char (*pointer) [100])
{
strcpy(pointer[0], "Hello ");
strcpy(pointer[1], "world");
}
* Alternative Solution *
A different design/solution would be to change in your main() function so that you are actually passing a char *[], which decays into a char ** - which is fine - to string_copy(). This way you would NOT have to change your string_copy() function.
int main(int argc, const char * argv[]) {
char my_array[10][100];
int tot_char_arrs, i;
char *char_arr_ptr[10];
/* Get total number of char arrays in my_array */
tot_char_arrs = sizeof(my_array) / sizeof(my_array[0]);
// Store all char *
for (i = 0; i < tot_char_arrs; i++)
char_arr_ptr[i] = my_array[i];
/* Actually passing a char *[].
it will decay into char **, which is fine
*/
string_copy(char_arr_ptr);
printf("%s%s\n", my_array[0], my_array[1]);
}
you need to use a pointer to the array. here is an example with 1 dimension array:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
static void string_copy(char **pointer) {
strcpy(pointer[0], "Hello ");
}
int main(int argc, const char * argv[]) {
char my_array[10];
char * p_array = my_array;
string_copy(&p_array);
printf("%s\n", my_array);
}
Your function can simply accept matrix dimensions and pass a const char * that stores the array of literals (pre-allocated) strings:
#include <stdio.h>
#include <string.h>
#define STRINGS_LENGTH 100
static void string_copy(size_t n, size_t m, char pointer[n][m], const char *strings_to_copy[])
{
for (size_t i=0; i< n; i++)
{
strcpy(pointer[i], strings_to_copy[i]);
}
}
int main( void )
{
const char *strings[] = { "hello", "World" };
char my_array[sizeof(strings)/sizeof(strings[0])][STRINGS_LENGTH];
string_copy(sizeof(strings)/sizeof(strings[0]), STRINGS_LENGTH, my_array, strings);
printf("%s %s\n", my_array[0], my_array[1]);
}
You can also change the structure of your code using dynamic allocation for your output array like:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
static bool string_copy(char *pointer[], const char *strings_to_copy[], size_t strings)
{
for (size_t i=0; i< strings; i++)
{
pointer[i] = malloc(strlen(strings_to_copy[i])+1);
if (pointer[i] != NULL)
strcpy(pointer[i], strings_to_copy[i]);
else
return false;
}
return true;
}
int main(void)
{
const char *strings[] = { "hello", "World" };
char *my_array[sizeof(strings)/sizeof(strings[0])] = {0};
if (string_copy(my_array, strings, sizeof(strings)/sizeof(strings[0])) )
{
printf("%s %s\n", my_array[0], my_array[1]);
}
for (size_t i = 0; i<sizeof(strings)/sizeof(strings[0]); i++)
free (my_array[i]);
}

Finding a unique character

My task is to compare some words and to find a character which is not used in both of them. Here is my code. But I'm getting a warning:
[Warning] passing argument 1 of 'ret' makes pointer from integer without a cast [enabled by default].
And when I'm trying to run it it says consolepauser.exe stopped working
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
char ret(char a[1][10],char b[3][10])
{
int i,j,p,t;
for (i=0;i<1;i++)
for (j=0;j<10;j++)
for (p=0;p<3;p++)
for (t=0;t<10;t++)
{
if (tolower(a[i][j]==tolower(b[p][t])))
{
p=3;
break;
}
if (p==2)
if (t==9) return tolower(a[i][j]) ;
}
return 'N';
}
int main(int argc, char *argv[]) {
char k[3][10]={"cHaOs","TOP","blAa"};
char b[1][10]={"SomeThIng"};
char q[1][10]={"HaPa"};
if (ret(b[1][10],k[3][10])='N') printf("No character") ;
else printf("%c",ret(b[1][10],k[3][10])) ;
return 0;
}
You should pass the parameters as:
if (ret(b, k) == 'N') printf("No character");
else printf("%c", ret(b, k));
[Warning] passing argument 1 of 'ret' makes pointer from integer without a cast
b[1][10] is a char, not a variable of type char [1][10], you should call ret() like this: ret(b, k). Others are similar.
Note: the valid indexes of char b[1][10]; are b[0][0], b[0][1], ..., b[0][9], the indexes in `b[1][10]1 are out-of-bounds, and will cause undefined behavior.
Here is a syntax fixed version of your code, you may want to compare it with your original code to find out other problems in it:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
char ret(char a[1][10],char b[3][10])
{
int i,j,p,t,e,r;
for (i=0;i<1;i++)
for (j=0;j<10;j++)
for (p=0;p<3;p++)
for (t=0;t<10;t++)
{
if (tolower(a[i][j])==tolower(b[p][t]))
{
p=3;
break;
}
if (p==2)
if (t==9) return tolower(a[i][j]) ;
}
return 'N';
}
int main(int argc, char *argv[]) {
int i,j,p,t,e,r;
char a,h;
char k[3][10]={"cHaOs","TOP","blAa"};
char b[1][10]={"SomeThIng"};
char q[1][10]={"HaPa"};
if (ret(b,k)=='N') printf("No character");
else printf("%c",ret(b,k));
return 0;
}

How to make a copy of a string and return its address, assign that to a pointer and print the new string in C? [duplicate]

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;
}

Segmentation fault while processing argv

This procedure should convert a string that contains a set of double numbers separated by comma (e.g. 7.2,9.5,-5.515) to a vector of double type.
void ToDoubleVec(int d,const char* commaSeparated,double *result)
{
int i;
result[0]=atof(strtok(commaSeparated,","));
for(i=1;i<d;i++)
result[i]=atof(strtok(NULL,","));
}
Here is the snippet of program that calls it:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc,char** argv)
{
...
int i,dim=atoi(argv[1]);
double *lower;
lower = malloc(dim*sizeof(double));
ToDoubleVec(dim,argv[2],lower);
...
}
Debugger's output:
40 lower = malloc(dim*sizeof(double));
(gdb) s
42 ToDoubleVec(dim,argv[2],lower);
(gdb) s
ToDoubleVec (d=2, commaSeparated=0x7fffffffe9d3 "2.3,-62.1", result=0x603010) at testPSO.c:11
11 result[0]=atof(strtok(commaSeparated,","));
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff77f56bb in ?? () from /lib/x86_64-linux-gnu/libc.so.6
Why doesn't it work? I was sure that I've allocated enough memory for the array and also parameters seems to be passed correctly.
You can reduce your code to this SSCCE (Short, Self-Contained, Correct Example), which crashes nicely when you leave out #include <string.h> and does not compile cleanly when you add #include <string.h>:
segv.c: In function ‘ToDoubleVec’:
segv.c:8:5: warning: implicit declaration of function ‘strtok’ [-Wimplicit-function-declaration]
segv.c:8:20: warning: initialization makes pointer from integer without a cast [enabled by default]
segv.c:14:20: warning: assignment makes pointer from integer without a cast [enabled by default]
Code:
#include <stdlib.h>
//#include <string.h>
static void ToDoubleVec(int d, const char* commaSeparated, double *result)
{
int i;
result[0] = atof(strtok(commaSeparated, ","));
for (i = 1; i < d; i++)
result[i] = atof(strtok(NULL, ","));
}
int main(void)
{
int dim = 2;
double *lower = malloc(dim*sizeof(double));
char arg[] = "7.2,9.5,-5.515";
ToDoubleVec(dim, arg, lower);
}
Passing the return value from a function such as strtok() which can return a null pointer directly to a function such as atof() which does not tolerate null pointers is foolhardy; it leads to crashes. If everything is correct, you'll be OK; if not, you'll crash and burn.
The unchecked memory allocation is a similar problem; you didn't even check that dim was non-zero (and non-negative) before doing the memory allocation in the original.
#include <assert.h>
#include <string.h>
#include <stdlib.h>
static void ToDoubleVec(int d, char *commaSeparated, double *result)
{
int i;
char *number = strtok(commaSeparated, ",");
if (number != 0)
{
result[0] = atof(number);
for (i = 1; i < d; i++)
{
number = strtok(NULL, ",");
if (number != 0)
result[i] = atof(number);
}
}
}
int main(void)
{
int dim = 2;
double *lower = malloc(dim*sizeof(double));
char arg[] = "7.2,9.5,-5.515";
assert(lower != 0);
ToDoubleVec(dim, arg, lower);
}
You could — and in one version of the code I did — add error printing to report if the tests on number failed. But the crash is caused by the implicit declaration of strtok() as returning int and not char *.
I have tried to compile your code, and the compiler warned me that strtok() takes as input a char* and not a const char*. Then I have tried this code, and it is working correctly:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void ToDoubleVec(int d, char* commaSeparated,double *result);
int main(int argc,char** argv)
{
int i,dim=atoi(argv[1]);
double *lower;
lower = malloc(dim*sizeof(double));
ToDoubleVec(dim,argv[2],lower);
for (i=0; i<dim; ++i) {
printf("%f\n", lower[i]);
}
return 0;
}
void ToDoubleVec(int d, char* commaSeparated,double *result)
{
int i;
result[0]=atof(strtok(commaSeparated,","));
for(i=1;i<d;i++)
result[i]=atof(strtok(NULL,","));
}
So try to change const char* to char*, and check the input you pass to your program, maybe it is not correct and this could be the problem.

Testing for the presence of a character in an string in C

What's wrong with this?
#include <stdio.h>
void main(){
char *s="some text";
printf("%d",is_in(s,'t'));
}
int is_in(char *s, char c){
while(*s){
if(*s==c) return 1;
s++;
}
return 0;
}
I get the following compile time error with GCC:
test.c:9: error: conflicting types for ‘is_in’
test.c:9: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
test.c:5: note: previous implicit declaration of ‘is_in’ was here
Have you tried putting the is_in function above main?
You are incrementing the character, not the pointer. Change *s++ to simply s++. In addition, you have forgotten to forward-declare your function "is_in". One other note: you should probably make your string a "const char*" instead of "char*", and, IMHO, explicit comparison with '\0' and using indexes is clearer:
#include <stdio.h>
int is_in(const char*, char);
int main(int argc, char* argv[]){
const char* str="some text";
printf("%d",is_in(s,'t'));
return 0;
}
int is_in(const char* str, char c){
int idx=0;
while ( str[idx] != '\0' ){
if ( str[idx] == c ){
return 1;
}
idx++;
}
return 0;
}

Resources