what is wrong in this strcmp()? - c

I try to write simple C function with strcmp(). But I always get Segmentation fault (core dumped). What is wrong ?
char *arr={"abcdefg"};
char *a = arr[1];
if(strcmp(a, 'b') == 0)
{
printf("it is b \n");
}

What is wrong?
You did not let yourself be helped by the compiler.
Using -Wall -Wextra on GCC (which is by no means the best you can get but rather the bare minimum you should always use), I get:
testme.c: In function ‘main’:
testme.c:6:11: warning: initialization makes pointer from integer without a cast [enabled by default]
char *a = arr[1];
^
You took arr[1] -- which is the char value 'b' -- and turned it into a char *. Your a is now pointing to whatever is at address 0x62 (assuming ASCII), which is most definitely not what you intended. You probably wanted &arr[1], or arr + 1.
Or you wanted a char -- then you shouldn't declare char *, and strcmp() would be the wrong thing to use in the first place.
testme.c:8:1: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
if(strcmp(a, 'b') == 0)
^
In file included from testme.c:1:0:
/usr/include/string.h:144:12: note: expected ‘const char *’ but argument is of type ‘int’
extern int strcmp (const char *__s1, const char *__s2)
^
strcmp() expects two C strings (char const *). Your second argument 'b' is of type int... you probably wanted "b".
Which still would not compare equal, because "bcdefg" is not equal "b"...
Or you wanted a one-character comparison... that would be if ( a == 'b' ) then, with a being of type char, not char * (see above).
testme.c:10:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
printf("it is b \n");
^
testme.c:10:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
Please do us all the favour of posting complete code, includes, int main() and all, so we can copy & paste & compile, and still have line numbers match.

I think this is what you have been trying to achieve :
#include <stdio.h>
#include <string.h>
int main(void)
{
char *arr = {"abcdefg"};
char a = arr[1];
if( a == 'b' )
{
printf("it is b \n");
}
}

You're doing a number of things wrong here. strcmp is for comparing strings. The simplest way to do what you want is
char *arr= {"abcdefg"};
char a = arr[1];
if(a == 'b')
{
printf("it is b \n");
}
If you still want to do it with strcmp, you need to make a a string by appending the null terminator \0 to it.
char *arr= {"abcdefg"};
char a[] = {arr[1], '\0'};
if(strcmp(a, "b") == 0)
{
printf("it is b \n");
}

Related

Comparing every char in a string to a constant

Sorry, I'm relatively new to c. What I'm trying to do is loop through a string and compare each char in the string to a char. If successful, I print some value. However I'm getting a segmentation fault.
My Code:
int i;
const char* perc = '%';
char mystr[7] = "hell%o";
for(i=0;i<sizeof(mystr);i++){
if(strcmp(mystr[i],perc)!=0){
printf("%d",i);
}
NOTE: I'm not using % for format strings here, I'm literally just looking for its position in the string.
Thank you.
strcmp() is for comparing strings. To compare characters, you can use == operator.
Also note that sizeof is not for getting length of strings but getting number of bytes used for the type. In this case it is used for char array, so it may work according to what you want to do because sizeof(char) is defined to be 1 and therefore the number of bytes will be equal to the number of elements. Note that the terminating null-character and unused elements after that will added to the count if they exists. To get the length of string, you should use the strlen() function.
int i;
const char perc = '%'; /* use char, not char* */
char mystr[7] = "hell%o";
int len = strlen(mystr); /* use strlen() to get the length of the string */
for(i=0;i<len;i++){
if(mystr[i] != perc){ /* compare characters */
printf("%d",i);
}
if(strcmp(mystr[i],perc)!=0){
Must be if(mystr[i]!= perc){. And const char* perc = '%'; should be const char perc = '%';
strcmp takes two strings (char*), but you are passing chars. Compiling with gcc and -Wall shows:
c.c: In function ‘main’:
c.c:5:20: warning: initialization of ‘const char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
5 | const char* perc = '%';
| ^~~
c.c:9:24: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [-Wint-conversion]
9 | if(strcmp(mystr[i],perc)!=0){
| ~~~~~^~~
| |
| char
In file included from c.c:1:
/usr/include/string.h:137:32: note: expected ‘const char *’ but argument is of type ‘char’
137 | extern int strcmp (const char *__s1, const char *__s2)
| ~~~~~~~~~~~~^~~~
Always remember: The compiler is one of the best friends of you.
The fixed program could be:
#include <stdio.h>
#include <string.h>
int main() {
int i;
const char perc = '%';
char mystr[7] = "hell%o";
for (i = 0; i < sizeof(mystr); i++) {
if (mystr[i] != perc) {
printf("%d", i);
}
}
}

Can someone explain output of this program?

The output of this program is:
XBCDO
HELLE
Can someone explain why this is so?
#include<stdio.h>
void swap(char **p, char **q) {
char *temp = *p;
*p = *q;
*q = temp;
}
int main() {
int i = 10;
char a[10] = "HELLO";
char b[10] = "XBCDE";
swap(&a, &b);
printf("%s %s", a, b);
}
You are confused about the difference between pointers and arrays. (It is a confusing part of the language.) swap expects pointers to pointers, but you have given it pointers to arrays. This is such a serious mistake that GCC warns about it even if you don't turn on any warnings (it ought to issue hard errors, but some very, very old code does stuff like this intentionally and they don't want to break that).
$ gcc test.c
test.c: In function ‘main’:
test.c:16:10: warning: passing argument 1 of ‘swap’ from incompatible pointer type [-Wincompatible-pointer-types]
swap(&a, &b);
^
test.c:3:1: note: expected ‘char **’ but argument is of type ‘char (*)[10]’
swap(char **p, char **q)
^~~~
test.c:16:14: warning: passing argument 2 of ‘swap’ from incompatible pointer type [-Wincompatible-pointer-types]
swap(&a, &b);
^
test.c:3:1: note: expected ‘char **’ but argument is of type ‘char (*)[10]’
swap(char **p, char **q)
^~~~
The mistake causes the program to have undefined behavior - it doesn't have to do anything that makes any sense at all.
The program you probably were trying to write looks like this:
#include <stdio.h>
static void swap(char **p, char **q)
{
char *temp = *p;
*p = *q;
*q = temp;
}
int main(void)
{
char a[10] = "HELLO";
char b[10] = "XBCDE";
char *c = a;
char *d = b;
swap(&c, &d);
printf("%s %s", c, d);
}
The output of this program is XBCDE HELLO, which I think is what you were expecting. c and d are actually pointers, and they are set to point to the first elements of the arrays a and b; swap works as expected when applied to c and d.
If it doesn't make any sense that c and d are different from a and b, you need to get your hands on a good C textbook and you need to read the chapter on pointers and do all the exercises. (If it doesn't have at least one entire chapter on pointers, with exercises, it's not a good C textbook.)

passing argument makes pointer from integer without a cast

I've read through several similar questions on Stack Overflow, but I've not been able to find one that helps me understand this warning in this case. I'm in my first week of trying to learn C though, so apologies if I've missed an obvious answer elsewhere on Stack Overflow through lack of understanding.
I get the following warning and note:
warning: passing argument 2 of ‘CheckIfIn’ makes pointer from integer without a cast [enabled by default]
if(CheckIfIn(letter, *Vowels) ){
^
note: expected ‘char *’ but argument is of type ‘char’
int CheckIfIn(char ch, char *checkstring) {
When trying to compile this code:
#include <stdio.h>
#include <string.h>
#define CharSize 1 // in case running on other systems
int CheckIfIn(char ch, char *checkstring) {
int string_len = sizeof(*checkstring) / CharSize;
int a = 0;
for(a = 0; a < string_len && checkstring[a] != '\0'; a++ ){
if (ch == checkstring[a]) {
return 1;
}
}
return 0;
}
// test function
int main(int argc, char *argv[]){
char letter = 'a';
char *Vowels = "aeiou";
if(CheckIfIn(letter, *Vowels) ){
printf("this is a vowel.\n");
}
return 0;
}
Vowels is a char*, *Vowels is just a char, 'a'. chars get automatically promoted to integers, which your compiler is allowing to be implicitly converted to a pointer. However the pointer value will not be Vowels, it will be the address equal to the integer encoding of the character 'a', 0x61 almost universally.
Just pass Vowels to your function.
In your case, the type conversion is from char to integer pointer. In some cases, the function takes void pointer as the second argument to accommodate for all the data-types.
In such cases, you would need to typecast the second argument as (void *)
This would be the function declaration in most well written modular functions:
int CheckIfIn(char ch, void *checkstring);
You would need to pass the argument as a void pointer, provided the Vowels is not a char pointer
if(CheckIfIn(letter, (void *)Vowels) ){
printf("this is a vowel.\n");
}

Pass a char pointer array to a function in C?

I have the following code:
int main(){
char **array;
char a[5];
int n = 5;
array = malloc(n *sizeof *array);
/*Some code to assign array values*/
test(a, array);
return 0;
}
int test(char s1, char **s2){
if(strcmp(s1, s2[0]) != 0)
return 1;
return 0;
}
I'm trying to pass char and char pointer array to a function, but the above code results in the following errors and warnings:
temp.c: In function ‘main’:
temp.c:6:5: warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration]
temp.c:6:13: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
temp.c:10:5: warning: implicit declaration of function ‘test’ [-Wimplicit-function-declaration]
temp.c: At top level:
temp.c:15:5: error: conflicting types for ‘test’
temp.c:15:1: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
temp.c:10:5: note: previous implicit declaration of ‘test’ was here
temp.c: In function ‘test’:
temp.c:16:5: warning: implicit declaration of function ‘strcmp’ [-Wimplicit-function-declaration]
I'm trying to understand what the problem is.
First of all, you should include the necessary header files. For strcmp you need <string.h>, for malloc <malloc.h>. Also you need to at least declare test before main. If you do this you'll notice the following error:
temp.c: In function ‘test’:
temp.c:20:5: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
/usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
This indicates that test() should have a char * as first argument. All in all your code should look like this:
#include <string.h> /* for strcmp */
#include <malloc.h> /* for malloc */
int test(char*,char**); /* added declaration */
int main(){
char **array;
char a[5];
int n = 5;
array = malloc(sizeof(*array));
array[0] = malloc(n * sizeof(**array));
/*Some code to assign array values*/
test(a, array);
free(*array); /* free the not longer needed memory */
free(array);
return 0;
}
int test(char * s1, char **s2){ /* changed to char* */
if(strcmp(s1, s2[0]) != 0) /* have a look at the comment after the code */
return 1;
return 0;
}
Edit
Please notice that strcmp works with null-terminated byte strings. If neither s1 nor s2 contain a null byte the call in test will result in a segmentation fault:
[1] 14940 segmentation fault (core dumped) ./a.out
Either make sure that both contain a null byte '\0', or use strncmp and change the signature of test:
int test(char * s1, char **s2, unsigned count){
if(strncmp(s1, s2[0], count) != 0)
return 1;
return 0;
}
/* don' forget to change the declaration to
int test(char*,char**,unsigned)
and call it with test(a,array,min(sizeof(a),n))
*/
Also your allocation of memory is wrong. array is a char**. You allocate memory for *array which is itself a char*. You never allocate memory for this specific pointer, you're missing array[0] = malloc(n*sizeof(**array)):
array = malloc(sizeof(*array));
*array = malloc(n * sizeof(**array));
Error 1
temp.c:6:13: warning: incompatible implicit declaration of
built-in function ‘malloc’ [enabled by default]
Did you mean this?
array = malloc(n * sizeof(*array));
Error 2
temp.c:15:5: error: conflicting types for ‘test’
temp.c:15:1: note: an argument type that has a default promotion can’t
match an empty parameter name list declaration
temp.c:10:5: note: previous implicit declaration of ‘test’ was here
You are passing the address of the first element of an array a:
test(a, array);
So the function signature should be:
int test(char* s1, char** s2)
You have several problems. The first is that the prototype is wrong. The data type for a decays to a char pointer when passing to a function, so you need:
int test (char* s1, char** s2) { ... }
However, even when you fix this, the test declaration isn't in scope when you first use it. You should either provide a prototype:
int test (char* s1, char** s2);
before main, or simply move the whole definition (function) to before main.
In addition, don't forget to #include the string.h and stdlib.h headers so that the prototypes for strcmp and malloc are available as well.
When you pass an array of char to your function, the argument decays to a pointer. Change your function arguments to
int test(char* s1, char **s2);
^
^
and your code should at least compile

atoi from string to Integer using char pointer

Here is the code I have written which splits a string in c and then I want to return the first integer value pointed by the char pointer.
#include<stdio.h>
void main(){
int month[12]={0};
char buf[]="1853 was the year";
char *ptr;
ptr = strtok(buf," ");
printf("%s\n",ptr);
int value = atoi(*ptr);
printf("%s",value);
}
EDIT:It gives me segmentation fault.
The problem is it is printing 1853 as the year, But I want to convert this into integer format.How can i retrieve that value as an integer using the pointer?
you are here trying to use an integer as a string:
printf("%s",value);
you should do
printf("%d",value);
Edit: yes, and also do int value = atoi(ptr); as added in another answer.
main should also be int, not void.
Also, what compiler are you using? With gcc 4.6 I got these errors and warnings when trying to compile your code (after adding some includes):
ptrbla.C:5:11: error: ‘::main’ must return ‘int’
ptrbla.C: In function ‘int main()’:
ptrbla.C:11:30: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
/usr/include/stdlib.h:148:12: error: initializing argument 1 of ‘int atoi(const char*)’ [-fpermissive]
ptrbla.C:12:26: warning: format ‘%s’ expects argument of type ‘char*’, but argument 2 has type ‘int’ [-Wformat]
I'd think you could get at least some of these from most compilers.
int value = atoi(ptr);
No need to dereference, atoi() expects a const char*, not a char.
printf("%d",value);
And you print an integer using %d or %i. %s is for string only.
BTW, maybe you would like to use strtol instead
char buf[]="1853 was the year";
char* next;
long year = strtol(buf, &next, 10);
printf("'%ld' ~ '%s'\n", year, next);
// 'year' is 1853
// 'next' is " was the year"
Use:
int value = atoi(ptr);
atoi should get a character pointer, which is what ptr is. *ptr is the first character - 1 in this case, and anyway isn't a pointer, so it's unusable for atoi.

Resources