atoi from string to Integer using char pointer - c

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.

Related

My compiler returned "assignment to 'int *' from incompatible pointer type 'char *' [-Wincompatible-pointer-types]" when I ran my C program

#include <stdio.h>
int main()
{
char grade = 'A';
int *p = &grade;
printf("The address where the grade is stored: %p\n", p);
printf("Grade: %c\n", grade);
return 0;
}
I get this error each time I compile the code on VScode but never on code blocks.
warning: incompatible pointer types initializing 'int *' with an
expression of type 'char *' [-Wincompatible-pointer-types]
int *p = &grade;
^ ~~~~~~
1 warning generated.
 ./main
The address where the grade is stored: 0x7ffc3bb0ee2b
Grade: A"
The warning tells you exactly what it is. It says:
incompatible pointer types initializing 'int *' with an expression of type 'char *'
This means that p is of type int *, that &grade is of type char *, and that these two pointers are not compatible. The solution is to change the declaration of p to:
char *p = &grade;
One more thing. Usually you can safely do implicit conversions to and from any pointer to void *, but not when passed as argument to a variadic function. If you want to print the address, use this:
printf("%p", (void *)p);
But only cast when needed. Never do it just to get rid of warnings. Here is an answer I wrote about that: https://stackoverflow.com/a/62563330/6699433
As an alternative, you could use a void pointer directly:
void *p = &grade;
printf("%p", p);
But then you would need to cast if you want to dereference it. For example:
char c = *(char*)p;
That cast is not necessary if p is declared as char *.

while giving string value to integer what is happening?

In my C program i assign a string in one integer variable and i print with percentage %s it will print that string with warning integer to pointer without cast and print with %d it print 134513904 then i change my string value and print with %d "134513904" is printing what is this value and how integer variable storing a string value in int variable?
enter code here
#include<stdio.h>
main()
{
int a="naveen";
printf("%d\n",a);
printf("\n%s\n",a);
if("naveen")
{
printf("hi");
}
int_point.c: In function ‘main’:
int_point.c:22:8: warning: initialization makes integer from pointer without a cast [enabled by default]
int a="naveen";
^
int_point.c:24:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("\n%s\n",a);
^
134513920
naveen
hi
The following assigns a pointer (not a string) to s:
const char *s = "navven";
That means the following assigns a pointer (not a string) to a:
int a = "naveen";
Computers don't really see a difference between a pointer and number. They're both things that fit in their registers. And some people take advantage of that fact. So while the compiler warns you that you are doing something wrong, it still lets you treat the pointer as a number.
So a is ends up with the value of the pointer if it were an int. That's not safe to do. Not quite. While you can't use an int safely, you can use an intptr_t safely.
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
int main(void) {
const char *p1 = "naveen";
printf("%p %s\n", p1, p1);
intptr_t i = (intptr_t)p1;
printf("0x%" PRIxPTR "\n", i);
const char *p2 = (const char*)i;
printf("%p %s\n", p2, p2);
return 0;
}
Output:
0x51ee878764 naveen
0x51ee878764
0x51ee878764 naveen

what is wrong in this strcmp()?

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

2-D character array

#include<stdio.h>
int main()
{
char str[3][10]={
"vipul",
"ss",
"shreya"
};
Why this won't work:
printf("%s",str[1][0]);
If i want to access str whereas
printf("%s",&str[1][0]);
or this would do it perfectly
printf("%s",str[1]);
Can anyone explain ?
Why is the first code giving an error
prog.c: In function ‘main’:
prog.c:9:5: error: format ‘%s’ expects argument of type ‘char *’, but
argument 2 has type ‘int’ [- Werror=format]
cc1: all warnings being treated as errors
Why does the argument has type int?
printf("%s",str[1][0]);
The problem is in this line. When For %s format specifier, printf() expects a pointer to a null terminated string. Whereas str[1][0] is simply a char (specifically the first s in "ss"), which is promoted to int (default argument promotions). That's exactly what the error message says.
Well
str[1] is a char* and str[1][0] is a char.
But when you use %s, printf() expect a pointer so you try to cast the char into a pointer.
So your char is promoted to an int.
It is said in the error:
format ‘%s’ expects argument of type ‘char *’
and your argument str[1][0] is a char, not the expected char *. In C, a char is treated as an int.
In first case printf("%s",str1[1][0]); you are passing single character to printf function and format specifier that you use it %s. For %s printf function expects string of character and not character.So it gives error.
As in 1st printf function you are specifying %s and you are passing character, argument promotion will takes place and char will promoted to int.
•The default argument promotions are char and short to int/unsigned int and float to double
•The optional arguments to variadic functions (like printf) are subject to the default argument promotions
More on Default argument promotion and here.
on your line error:
printf("%s",str[1][0]);
you try to print a string where you have a character ("%c" in printf)
so to only print one of ur 2D array you would have to do something like that:
int main()
{
int i;
char str[3][10]=
{
"vipul",
"ss",
"shreya"
};
i = 0;
while(str[0][i] != '\0')
{
printf("%c",str[0][i]);
i++;
}
}
which is pretty ugly ^^
instead you could print all ur 2D array with 3 single iteration with that:
int main()
{
int i;
char str[3][10]=
{
"vipul",
"ss",
"shreya"
};
i = 0;
while(i < 3)
{
printf("%s\n",str[i]);
i++;
}
}

How does the C program generate such an output?

void main()
{
char str[2][7] = {"1234567", "abcdefg"};
char** p = str;
printf("%d\n", *(p+1));
printf("%c\n", *(p+1));
}
The output is:
1631008309
5
Edit: Thank you. I see the '5' is only 0x35, other than str[0][4] I supposed to be. Why can't I get out str[0][4] instead of this strange 1631008309??
OMG, I'm foolish enough to ask this question! Thank you all, guys.
You're pointing a char** at the beginning of the memory allocated to your 2-d array.
When you add 1 to a pointer it moves you along by the sizeof the type pointed to, in this case the sizeof a char *, which is evidently 4 bytes in your system. Then you're dereferencing it and treating the result as an int (%d), which gives you the a765 I mentioned in my comment to unwind. When you dereference it and treat it as a char you correctly get 5.
[I see that unwind has deleted their answer, so just for completeness I'll add that the "a765" is the ASCII interpretation of the larger number you get (0x61373635).]
This line:
char** p = str;
makes no sense. str is an array of 2 arrays of 7 chars. When used in an expression context, it evaluates to a pointer to its first element, equivalent to:
&str[0]
which has type "pointer to array of 7 chars". That is in no way similar to a "pointer to pointer to char", which is the type of p. Any of these would make sense instead:
char *p = str[0];
char *p = str[1];
char (*p)[7] = str;
Using %d does not convert an ASCII string of alphanumerics into a number. Using %d means it expects that the value found will be interpreted as a binary representation of the number and converted TO ASCII for printing.
Note that the C standard defines that the main() program returns an int, not void.
Given the code:
#include <stdio.h>
int main()
{
char str[2][7] = {"1234567", "abcdefg"};
char** p = str;
printf("%d\n", *(p+1));
printf("%c\n", *(p+1));
return(0);
}
When compiled withgcc -o x -Wall x.c, you get the warnings:
x.c: In function ‘main’:
x.c:5: warning: initialization from incompatible pointer type
x.c:6: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘char *’
x.c:7: warning: format ‘%c’ expects type ‘int’, but argument 2 has type ‘char *’
(If you omit the -Wall, you don't get the format warnings.)
This tells you that you are passing a pointer to printf(). Printing a pointer is not going to be all that useful. However, the previous warning also tells you that you are mis-initializing the variable p. However, the net result is that p points to the start of the space in str. When you print
One interesting little quirk: normally, a string such as "1234567" includes a terminating NUL '\0'; in your arays, because you specified that the length of the array is 7, not 8, the terminating null is missing. Be careful how you print the strings!
Here's another variant of the code:
#include <stdio.h>
int main()
{
char str[2][7] = {"1234567", "abcdefg"};
char** p = str;
printf("%d\n", *(p+1));
printf("%c\n", *(p+1));
printf("%p %p %p -- %p %p %p\n", str, &str[0], &str[0][0], p, p+1, *(p+1));
printf("%.4s\n", (p+1));
return(0);
}
That gives me the following output (from an Mac):
1631008309
5
0xbffffa5e 0xbffffa5e 0xbffffa5e -- 0xbffffa5e 0xbffffa62 0x61373635
567a
Note that the addresses str, &str[0] and &str[0][0] all have the same value, and that p+1 is four bytes further along. When treated as a string, it prints the last three bytes of the first initializer and the first byte of the second.
Also, for fun, compiled with gcc -m64 -o x64 x.c, the output is:
1701077858
b
0x7fff5fbff9e0 0x7fff5fbff9e0 0x7fff5fbff9e0 -- 0x7fff5fbff9e0 0x7fff5fbff9e8 0x676665646362
bcde
I understand your confusion, the two statements is exactly the same.
Both statements cast *(p + 1) to an pointer to an integer prior dereferencing it, the default is to cast everything to an integer in a va_arg argument.
printf then truncates the integer to a char prior printing it in the second printf statement.
This code snippet makes it more clear what is going on:
void main()
{
char str[2][7] = {"1234567", "abcdefg"};
char** p = str;
printf("%d\n", *(p+1));
printf("%c\n", *(p+1));
int n = *(p+1);
char c = *(p+1);
printf("0x%08X\n", n);
printf("0x%08X\n", c);
}
Which outputs:
1631008309
5
0x61373635
0x00000035
Type safety in stdarg is explained here: stdarg

Resources