Using pointers, I am able to get to the actual character('i' in ElGenerico) that I want to print. But some weird character is getting printed on the screen, rather than my desired character.
#include<stdio.h>
int main()
{
char *name[]={"Sami","Kevin","ElGenerico"};
printf("%c",(*(name+2)+7));
return 0;
}
With my use of %s output specifier, the output of this code is "ico".
But I want to print only the character 'i'. So I tried using %c, instead of %s. It doesn't work. Instead, a double headed arrow is printed.
Can anyone please tell me where I am going wrong?
I recommend using bracket notation for improved readability.
Initially, you had this:
printf("%c",(*(name+2)+7));
You would still need to dereference with * to get the desired output.
That would give you this:
printf("%c",*(*(name+2)+7));
However, that's still a bit confusing and not very readable. You could make it much cleaner by using bracket notation, like this:
printf("%c", name[2][7]);
Now there's much less room for error and you still get the expected output.
Your final code would look something like this:
#include <stdio.h>
int main()
{
char* name[] = {"Sami", "Kevin", "ElGenerico"};
printf("%c", name[2][7]);
return 0;
}
You are pointing to the wrong address. Use this instead:
printf("%c",(*(name[2]+7)));
Since you are referring to the third element in the name array, you can use
name[2]
Then you wanted to put the 7th element of the word ElGenerico, hence we need to add 7 to the address:
name[2] + 7
After we get the correct address, then we print out the value of that address, and we use the * sign:
*(name[2] + 7)
printf("%c",*(*(name+2)+7));
I used this, and it's solved, thanks for the help #David and #rcs...
Related
I am reading Head First C book and in pointers chapter(and pointer arithmetic) i couldnt understand something.
I have to write arrays like this to print its 3rd element:
main(){
int drinks[] = {4, 2, 3};
printf("3rd order: %i drinks\n", *(drinks + 2));
}
But when using pointer i need to write like this
void skip(char*);
int main() {
char *msg_from_amy="dont call me";
skip(msg_from_amy);
}
void skip(char *msg){
puts(msg+6);
}
Shouldnt i need to write *(msg+6) to access 7th element? msg holds an address and msg+6 means ahead of 6 bytes from begining. so it is still an address, i need to write *(msg+6) to access stored value in that address from my perspective but it doesnt work. But why quoted one right answer, why i cant figure out.
Edit: Actually i asked wrongly my question. And edited code snippets. Here is output of:
puts(msg+6);
printf("%c\n", *(msg+6));
printf("%s\n", *(msg+6));
all me
a
I expected get "all me" output from 2nd printf like 1st one. But i think i understand the reason. its difference of puts and printf argument list. Thx for answers.
Btw why 3rd printf prints just a blank character?
I have to write arrays like this to print its 3rd element:
main(){
int drinks[] = {4, 2, 3};
printf("3rd order: %i drinks\n", *(drinks + 2));
}
No, you don't have to do that, and it is very non-idiomatic. Most people would use
printf("3rd order: %i drinks\n", drinks[2]);
Moving on ...
void skip(char *msg){
puts(msg+6);
}
Shouldnt i need to write *(msg+6) to access 7th element?
Yes, *(msg+6) to access 7th element or, better, msg[6]. But you're not trying to access the 7th element. You are providing to puts the substring that starts at the 7th element. msg+6 is just fine for that.
Here is output of:
puts(msg+6);
printf("%c\n", *(msg+6));
printf("%s\n", *(msg+6));
all me
a
I expected get "all me" output from 2nd printf like 1st one
I don't see why. The %c formatting directive converts and prints one character, which is good because that's what you pass as the corresponding argument. It's not about a difference between puts and printf. Rather, it's mostly about the deep difference between msg+6 and *(msg+6).
Btw why 3rd printf prints just a blank character?
No one can say. The behavior of your third printf call is undefined because the formatting directive %s, which expects a char * argument, is not correctly type matched with the corresponding argument *(msg+6), which is a char. Anything could happen. And this underscores my previous point: there is no deep difference in this regard between puts and printf. You appear to want:
printf("%s\n", msg+6);
I expected get "all me" output from 2nd printf like 1st one.
The %c specifier is intended to print exactly one character. Furthermore, it's impossible to go to msg+7 from *(msg+6).
Btw why 3rd printf prints just a blank character?
Because %s expects a pointer. *(msg+6) is not a pointer.
You should compile with -Wall -Wextra. That will make the compiler warn you about a lot of stuff.
If you need the value that msg points to, you need to deference it using the * operator. So, if you want to get the sixth element pointed by msg, you need to advance by 6 and then deference it. The problem with printf("%s\n", *(msg+6)); is that %s expects a string, but *(msg+6) is a character. You can try to change %s with %c.
Remember that a string in c is a collection of characters ended by the null character '\0'.
I was just wondering if you could clear something up for me.
Let's have some example code to explain my question:
#include <stdio.h>
int main(void)
{
char test[100];
printf("%s",test);
return 0;
}
If I am not totally mistaken, this should output randomly either some character that was at this memory address before I declared it or nothing if it was empty like in a virtual environment. So, this is my understanding. The memory held before I put something in is understood as a char and written to the terminal. For instance ascii 'a' = 97 = 01100001. That's why it outputs 'a'. Could have been anything else. Or nothing. And then it stops.
But if I put 'a' in the first position and then print it like this:
test[0] = 'a'
printf("%s",test);
It will output 'a' and additionally to that some character or nothing and then stop.
This is how I understand arrays: An array is a pointer to the first address and the brackets are a dereferences of the address after adding the number times sizeof(type) to it.
So, in that case, the random 01100001 (Ascii 'a') found in the memory in the first example should be indistinguishable for printf from the deliberately placed 01100001 (Ascii 'a') in the second example. Yet, when I run printf, I don't get 100 random outputs. I get one. And I don't assume random fields are in general set to '\0'.
Which means, my understanding must be wrong somewhere. Please help me understand where I make my mistake.
It doesn't, it's undefined behavior. Your program just accidentally prints the un"expected" value.
#include <stdio.h>
int main(void)
{
char test[100];
printf("%s",test);
return 0;
}
You can't expect the code above to do anything predictable, it might print something, it could segfault, there is no way to predict what will actually happen because the behavior of such program is strictly undefined.
I am originally a Java programmer who is now struggling with C and specifically C's pointers.
The idea on my mind is to receive a string, from the user, on a command line, into a character pointer. I then want to access its individual elements. The idea is later to devise a function that will reverse the elements' order. (I want to work with anagrams in texts.)
My code is
#include <stdio.h>
char *string;
int main(void)
{
printf("Enter a string: ");
scanf("%s\n",string);
putchar(*string);
int i;
for (i=0; i<3;i++)
{
string--;
}
putchar(*string);
}
(Sorry, Code marking doesn't work).
What I am trying to do is to have a first shot at accessing individual elements. If the string is "Santillana" and the pointer is set at the very beginning (after scanf()), the content *string ought to be an S. If unbeknownst to me the pointer should happen to be set at the '\0' after scanf(), backing up a few steps (string-- repeated) ought to produce something in the way of a character with *string. Both these putchar()'s, though, produce a Segmentation fault.
I am doing something fundamentally wrong and something fundamental has escaped me. I would be eternally grateful for any advice about my shortcomings, most of all of any tips of books/resources where these particular problems are illuminated. Two thick C books and the reference manual have proved useless as far as this.
You haven't allocated space for the string. You'll need something like:
char string[1024];
You also should not be decrementing the variable string. If it is an array, you can't do that.
You could simply do:
putchar(string[i]);
Or you can use a pointer (to the proposed array):
char *str = string;
for (i = 0; i < 3; i++)
str++;
putchar(*str);
But you could shorten that loop to:
str += 3;
or simply write:
putchar(*(str+3));
Etc.
You should check that scanf() is successful. You should limit the size of the input string to avoid buffer (stack) overflows:
if (scanf("%1023s", string) != 1)
...something went wrong — probably EOF without any data...
Note that %s skips leading white space, and then reads characters up to the next white space (a simple definition of 'word'). Adding the newline to the format string makes little difference. You could consider "%1023[^\n]\n" instead; that looks for up to 1023 non-newlines followed by a newline.
You should start off avoiding global variables. Sometimes, they're necessary, but not in this example.
On a side note, using scanf(3) is bad practice. You may want to look into fgets(3) or similar functions that avoid common pitfalls that are associated with scanf(3).
Can someone explain how to convert a string of decimal values from ASCII table to its character 'representation' in C ? For example: user input could be 097 and the function would print 'a' on the screen, but also user could type in '097100101' and the function would have to print 'ade' etc. I have written something clunky that does the opposite operation:
char word[30];
scanf("%s", word);
while(word[i]!=0)
{
if(word[i]<'d')
printf("0%d", (int)word[i]);
if(word[i]>='d')
printf("%d", (int)word[i]);
i++;
}
but it works. Now I want to have function that works in a similar way but of course does decimal > char conversion. The point is, I cannot use any functions like 'atoi' or something like that (not sure about names, never used them ;)).
You can use this function instead of atoi:
char a3toc(const char *ptr)
{
return (ptr[0]-'0')*100 + (ptr[1]-'0')*10 + (ptr[0]-'0');
}
So, a3toc("102") will return the same thing as (char) 102, which is an 'f'.
If you don't see why, substitute in the values: ptr[0] is '1', so the first part becomes ('1'-'0')*100 or 1*100 or 100, which is what that first 1 in 102 represents.
Tokenize the input string. I'm assuming you are forcing that every letter MUST be represented in 3 characters. So break the string that way. And simply use explicit type casting to get the desired character.
I don't think I should be giving you the code for this, since it is pretty easy and seems more like a Homework question.
Hey guys, i'm working on a program that gets a postfix expression and calculates it..
I have two functions:
Converts infix to postfix
Calculate the postfix
When I try small expressions, like 1+1 or (1+1)*1, it works fine
but when i use all the operands I get something nasty,
Here is the example:
2*2/2+1-1
gets something like:
222/*11-+T_CHECKÖÐ7?█Ã
If you see, the expression is right until the 'T'
I believe it's some parameter mistake, so i'll put the header and return values here
1st)
char* convert(char *infix);
char *post = (char *)malloc(sizeof(char)*tamP);
return post;
2nd)
int evaluate(char *postfix)
while (*postfix != '\0')
return result;
Caller)
char* post = convert(infix);
result = evaluate(post);
Thanks
That kind of weird string looks more like a buffer overflow error. You are likely overwriting the null-terminator, so when the string is printed (or later used), it keeps going until it finds one, examining random program memory until it gets there.
Check that all of your string manipulations are correct.
It is possible that you are not adding the '\0' character at the end of 'post' (after the last sensible character) in the convert(char*) function. That's one reason I can think of.
Try setting the complete string to '\0' before you do anything with it:
memset(post, 0, tamP);
should do.