Pointer array and structure in C - c

I am nowhere lose to even guessing how come we get the given output . Can I please get some explanation? Also, any short and quick resources to try similar questions?
void main()
{
struct a
{
char ch[10];
char *str;
};
struct a s1={"Hyderabad","Bangalore"};
printf("\n%c%c",s1.ch[0],*s1.str);
printf("\n%s%s",s1.ch,s1.str);
getch();
}
Ans: HB, HyderabadBangalore

struct a s1={"Hyderabad","Bangalore"}; assigns "Hyderabad" to ch and "Bangalore" to str.
printf("\n%c%c",s1.ch[0],*s1.str); prints the first character of the strings. Since ch is an array, ch[0] represents its first character. Since str is a character pointer, it points to the first character of a string here. So, *s1.str will have value 'B'
printf("\n%s%s",s1.ch,s1.str); simply prints all characters of both strings.
Fundamentally, ch is equal to &ch[0], the address of the first character in the array. And, str is pointer variable which holds the address of first character of the string literal "Bangalore".

%c is only for single character. Example H.
$s is for string. Example Hyderabad.
s1.ch[0] points to first character of String ch ->H
*s1.str is a pointer. It points to the value stored at address of str. It will be ->B
Hence you get HB
\n means a new line (as in java).

Here is your output according to requested question
void main()
{
struct a
{
char ch[10];
char *str;
};
struct a s1={"Hyderabad","Bangalore"};
printf("%c%c",s1.ch[0],*s1.Str[0]);
printf("\t%s%s",s1.ch,s1.str);
getch();
}

Related

In this solution, if *inputString is a memory address (and the input is a char type) then does *inputString qualify as an array?

I was solving a challenge on CodeSignal in C. Even though the correct libraries where included, I couldn't use the strrev function in the IDE, so I looked up a similar solution and modified it to work. This is good. However, I don't understand the distinction between a literal string and an array. Reading all this online has left me a bit confused. If C stores all strings as an array with each character terminated by \0 (null terminated), how can there be any such thing as a literal string? Also if it is the case that strings are stored as an array, *would inputString store the address of the array or is it an array itself of all the individual characters stored.
Thanks in advance for any clarification provided!
Here is the original challenge, C:
Given the string, check if it is a palindrome.
bool solution(char * inputString) {
// The input will be character array type, storing a single character each terminated by \0 at each index
// * inputString is a pointer that stores the memory address of inputString. The memory address points to the user inputted string
// bonus: inputString is an array object starting at index 0
// The solution function is set up as a Boolean type ("1" is TRUE and the default "0" is FALSE)
int begin;
// The first element of the inputString array is at position 0, so is the 'counter'
int end = strlen(inputString) - 1;
// The last element is the length of the string minus 1 since the counter starts at 0 (not 1) by convention
while (end > begin) {
if (inputString[begin++] != inputString[end--]) {
return 0;
}
} return 1;
}
A string is also an array of symbols. I think that what you don't understand is the difference between a char pointer and a string. Let me explain in an example:
Imagine I have the following:
char str[20]="helloword";
str is the address of the first symbol of the array. In this case str is the address of h. Now try to printf the following:
printf("%c",str[0]);
You can see that it has printed the element of the addres that is 'h'.
If now I declare a char pointer, it will be poining to whatever char adress I want:
char *c_pointer = str+1;
Now print the element of c_pointer:
printf("%c",c_pointer[0]);
You can see that it will print 'e' as it is the element of the second adress of the original string str.
In addition, what printf("%s", string) does is to printf every elemet/symbol/char from the starting adress(string) to the end adress where its element is '\0'.
The linked question/answers in the comments pretty much cover this, but saying the same thing a slightly different way helps sometimes.
A string literal is a quoted string assigned to a char pointer. It is considered read only. That is, any attempts to modify it result in undefined behavior. I believe that most implementations put string literals in read-only memory. IMO, it's a shortcoming of C (fixed in C++) that a const char* type isn't required for assigning a string literal. Consider:
int main(void)
{
char* str = "hello";
}
str is a string literal. If you try to modify this like:
#include <string.h>
...
str[2] = 'f'; // BAD, undefined behavior
strcpy(str, "foo"); // BAD, undefined behavior
you're broken the rules. String literals are read only. In fact, you should get in the habit of assigning them to const char* types so the compiler can warn you if you try to do something stupid:
const char* str = "hello"; // now you should get some compiler help if you
// ever try to write to str
In memory, the string "hello" resides somewhere in memory, and str points to it:
str
|
|
+-------------------> "hello"
If you assign a string to an array, things are different:
int main(void)
{
char str2[] = "hello";
}
str2 is not read only, you are free to modify it as you want. Just take care not to exceed the buffer size:
#include <string.h>
...
str2[2] = 'f'; // this is OK
strcpy(str2, "foo"); // this is OK
strcpy(str2, "longer than hello"); // this is _not_ OK, we've overflowed the buffer
In memory, str2 is an array
str2 = { 'h', 'e', 'l', 'l', '0', '\0' }
and is present right there in automatic storage. It doesn't point to some string elsewhere in memory.
In most cases, str2 can be used as a char* because in C, in most contexts, an array will decay to a pointer to it's first element. So, you can pass str2 to a function with a char* argument. One instance where this is not true is with sizeof:
sizeof(str) // this is the size of pointer (either 4 or 8 depending on your
// architecture). If _does not matter_ how long the string that
// str points to is
sizeof(str2) // this is 6, string length plus the NUL terminator.

How to use a pointer to point only at half of an array

I'm new to C and pointers, so i have this problem. I want to tell to pointer how much memory it should point to.
char * pointer;
char arr[] = "Hello";
pointer = arr;
printf("%s \n", pointer);
This pointer will point to whole array, so i will get "Hello" on the screen. My question is how can i make pointer to only get "Hel".
You may try this:
char * pointer;
char arr[] = "Hello";
pointer = arr;
pointer[3] = '\0'; // null terminate of string
printf("%s \n", pointer);
If you always work with strings, then have a look at strlen for getting length of a string. If a string arr has length l, then you may set arr[l/2] = '\0', so that when you print arr, only its first half will be shown.
You may also want to print the last half of your string arr? You can use pointer to point to any place you want as the start. Back to your example, you may try:
char * pointer;
char arr[] = "Hello";
pointer = arr + 2; // point to arr[2]
printf("%s \n", pointer);
Have a check what you will get.
printf has the ability to print less than the full string, using the precision value in the format string. For a fixed number of characters (e.g. 3), it's as simple as
printf( "%.3s\n", pointer );
For a variable number of characters, use an asterisk for the precision, and pass the length before the pointer
int length = 3;
printf( "%.*s\n", length, pointer );
You don't know what a pointer is so I'll explain.
A pointer does not point to a string. It points to a char! Yes, a char. A string in C is really just a set of chars all one after the other in the memory.
A char* pointer points to the beginning of a string. The string ends when there is a '\0' (aka null) char. When you printf("%s",s), what printf does is a cycle like this:
int i;
for(i=0;1;i++) //infinite cycle
{
if(s[i]=='\0')
break;
printf("%c",s[i]);
}
Meaning it will not print a string but all the chars in a char array until it finds a null char or it goes into memory space that is not reserved to it (Segmentation fault).
To print just the 1st 3 characters you could do something like this:
void printString(char* s,int n) //n=number of characters you want to print
{
if(n>strlen(s))
n=strlen(s);
else if(n<0)
return;
char temp=s[n]; //save the character that is in the n'th position of s (counting since 0) so you can restore it later
s[n]='\0'; //put a '\0' where you want the printf to stop printing
printf("%s",s); //print the string until getting to the '\0' that you just put there
s[n]=temp; //restore the character that was there so you don't alter the string
}
Also, your declaration of pointer is unnecessary because it is pointing to the exact same position as arr. You can check this with printf("%p %p\n",arr,pointer);
How much of the string is printed is controlled by the NULL-character "\0", which C automatically appends to every string. If you wish to print out just a portion, either override a character in the string with a "\0", or use the fwrite function or something similar to write just a few bytes to stdout.
You could achieve the objective with a small function, say substring.
#include<stdio.h>
#include<string.h> // for accessing strlen function
void substring(char* c,int len)
{
if (len <= strlen(c)){
*(c+len)='\0';
printf("%s\n",c);
}
else{
printf("Sorry length, %d not allowed\n",len);
}
}
int main(void)
{
char c[]="teststring";
char* ptr=c;
substring(ptr,4); // 4 is where you wish to trim the string.
return 0;
}
Notes:
In C++ a built-in function called substring is already available which shouldn't be confused with this.
When a string is passed to a function like printf using a format specifier %s the function prints all the characters till it reaches a null character or \0. In essence, to trim a string c to 4 characters means you put c[4] to null. Since the count starts from 0, we are actually changing the 5th character though. Hope the example makes it more clear.

C's weird pointer arithmetics

I have a very stupid question, I just can't answer.
Can somebody tell me why the following code works?
char hello[]="Hello World\n";
char *hptr = hello;
while(*hptr)
{
printf("%c", *hptr++);//here the output must be "ello World", but C thinks otherwise!!!
}
You're using a post-increment:
*hptr++
This uses the value of hptr first, and then increments it. If you wanted to skip the first letter, you would use a pre-increment:
*++hptr
This increments the pointer value, then uses it as a function argument.
char hello[]="Hello World\n";
In this hello hold the address of the first index of the character array
char *hptr = hello;
here the character pointer hptr=address of the first index of your character array
while(*hptr)
{
printf("%c", *hptr++);
}
and in this loop it first prints the character at your first index of the character array and then increments it and then increments the address of hptr and then the second character is printed and this goes on till u reaches the null character.

Reverse an input character string

I would like to reverse an input character string and I use the the pointer which points to the last character and make it print the string while the pointer address decreases. However, I could not get the whole string. Could anyone tell me what is wrong?
//Reverse a charater string
#include<stdio.h>
int main()
{
char a[50];
int l;
int *p;
printf("Please input a character string:\n");
scanf("%s",a);
l = strlen(a);
for (p = &a[l-1]; p >= a; p--)
{
printf("%c",*p);
}
printf("\n");
return 0;
}
Output:
Please input a character string:
asdfasdfasdf
fff
You have declared p as integer pointer. It should be a char pointer.
int *p;
should be
char *p;
The problem is the use of the int type for *p.
Since an int on your system is 32 bits wide (four times bigger than a char which is 8 bits on your system), when the pointer is being decremented, it is printing out every fourth character in the reverse of the string.
So, with your sample string, asdfasdfasdf, the pointer points to the last f, then the middle f, then the first f.
Similar example:
Please input a character string:
abcdefghijklmno
l is 15, a[l-1] is o
okgc
Press any key to continue . . .
If you change your pointer to the char type it will decrement properly, pointing to every character in the string in reverse order.
When you increment/decrement a pointer of type T*, the address contained in it changes by sizeof(T). Since you have declared p to be int*, the pointer address changes by sizeof(int). On your machine sizeof(int) == 4*sizeof(char), explaining the result you see. Change the type of p to char*.

Manipulating char arrays using pointers in c

So I tried this code
#include <stdio.h>
int main(void)
{
char string[] = "hello world";
char *my_ptr = string;
*my_ptr='Y';
printf("the first char of string is %c", *my_ptr);
}
OUTPUT_1 :-
the first char of string is Y
Now if I want to print the complete scentence in the string ("Yello world"). For that I changed 7th line to :-
printf("the whole string is %s", *my_ptr);
OUTPUT_2:-
Segmentation fault (core dumped)
But if I try changing it to this :-
printf("the whole string is %s", my_ptr);
OUTPUT_3 :-
the whole string is Yello world
Could someone please explain me why are the second case is failing ? AND
Why the third case prints correct ?
From my understanding *my_ptr (as well as my_ptr both) have the address of the first location, so why does the first one fail in printing a complete string , whereas the second one does well. Im a beginner so it would help if you could detail the reason behind such a behaviour in these cases.
my_ptr is of type char * it's a pointer on the first char of the string.
*my_ptr is of type char it's a character.
printf format string option %s takes a char *, it will loop over each character until it finds a string delimiter (0) :
First, *my_ptr, being Y
Then *(my_ptr + 1), being h
And so on...
When using printf with *my_ptr, The content of *my_ptr will be passed to printf as if it was a string pointer. Its value is 'Y' which is 89 in ascii.
printf will try to access the pointer at address 89 thinking it's a valid string pointer, but this address is most likely not readable and the kernel will kill the program trying to access memory it doesn't have access to.
This will work:
#include <stdio.h>
int main(void)
{
char string[] = "hello world";
char *my_ptr = string;
*my_ptr='Y';
printf("the first char of string is %c", *my_ptr);
printf("the whole string is %s", my_ptr);
}
my_ptr is a pointer to the entire string. *my_ptr is the value of the char at the beginning of the string.
printf("%s", char*)
printf("%c", char)
In the statement below:
printf("the whole string is %s", *my_ptr);
it will read the content from the address of *my_ptr. That produces Segmentation fault (core dumped) While in below:
printf("the whole string is %s", my_ptr);
The string will be read from the base address of string[ ]. To read the string you have to pass the base address from where character should be started to read untill '\0' character is found.
The reasaon is in C, %s is used for printing the string but u uses that to print the char which results in Core dump.
And in C, it is enough to give the base address to print the whole contents, no need to for using *addr.
If u want to access a particular character u can do so by *(a+0) for printing 1st char and *(a+1) for printin 2nd character and so on.
This:
printf("the whole string is %s", *my_ptr);
dereferences the pointer, so it passes a value of type char to printf(), which will then interpret it (due to the %s formatting specifier) as const char *, i.e. as a pointer to read-only character data. The value of a pointer is an address of a location in memory where some data is stored.
This will make printf() start reading characters from some very low address, where your program is not likely to be allowed to read. Thus the segmentation fault.

Resources