while(*p++) loop doesn't print the first element of the string - c

I have a stored a string in a pointer variable which has memory in heap section. When I print the string character by character the first element is skipped.
Example: if char *p="hello" when i print character by character using while(*p++) loop 'h' is skipped and output is "ello" please can any one explain it?
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p=(char*)malloc(sizeof(char)*20);
printf("enter string\n");
scanf("%s",p);
while(*p++)// value is assign and address is increased
{
printf("%c",*p);//why first character is skipped??
}
return 0;
}

To see the first letter, change *p to p[-1], because p++ has already incremented p, so by the time you first use *p, p already points to the 2nd letter (with index 1).
There are many other ways to solve it, e.g.
for (; *p; ++p) {
putchar(*p);
}

Because while(*p++) increments the value as soon as the loop starts. By the time the printf statement is reached, p has already been incremented.
p = 0
while(p++) { // p = p + 1
printf('%d', p); // p = 1 when this executes
}

while(*p++) after this statement p is incremented and moved ahead. So at printf() p already points to 2nd character.

The line while(*p++) will check the value of *p and then increment p, before entering the body of the loop. You can improve the code by using a for loop
for ( ; *p; p++ )
printf( "%c", *p );
or by incrementing the pointer after using it, in the body of the loop
while(*p)
printf( "%c", *p++ );

Related

Problem while printing string using Pointers in C Programming

Respected Experts ,
I am a newbie to C programming Language .
I am trying to print a string in C Language . The code runs successfully but when i
enter the string , it does not displays the string entered by the user in return
I have attached the screenshot of the code which I am trying to execute .
Please help me out .
#include<stdio.h>
int main()
{
char str[20];
char *pt;
printf("Enter any string :\n");
gets(str);
pt=&str[0];
for(*pt=0; *pt != '\0'; *pt++)
{
printf("%c", *pt);
}
}
The initialization *pt = 0; is causing the continuation test *pt != 0 to fail immediately, so your loop stops before printing anything.
You already initialized pt before the loop, so you don't need that step in the for() header. And you should be incrementing the pointer, not the character that it points so, so the update should be pt++.
for (; *pt != '\0'; pt++) {
printf("%c", *pt);
}
BTW, ptr = &str[0]; can be simplified to just ptr = str;. It's also more idiomatic to put this in the for header, so it would be:
for (pt = str; *pt != '\0'; pt++)
First - NEVER NEVER NEVER use gets, not even in toy code. It was deprecated in the 1999 standard and has been removed from the standard library as of the 2011 standard. It will introduce a point of failure / major security hole in your code. Use fgets instead, just be aware it will store the newline to your buffer if there's room.
Restructure your for statement as follows:
for ( pt = str; *pt != '\0'; pt++ )
The first expression sets pt to point to the first character in str (in this context, str is equivalent to &str[0]). The second compares the value of the element that pt points to against the string terminator. Since you are trying to check the value of the pointed-to object, you must use the * operator to deference pt. The final expression advances pt to point to the next character in the string.
Finally, is there a reason you're printing the string out character by character instead of just writing printf( "%s\n", str ); ?

Reverse of a string in C program?

I found this program for reversing this program online.
I have just started learning C.
I am not able to understand few things here.
Why while is ended with ;
what does while(str[++i]!='\0'); mean?
Is rev[j++] = str[--i]; same as writing j++; and i--; inside the while loop?
This is the program:
#include<stdio.h>
int main(){
char str[50];
char rev[50];
int i=-1,j=0;
printf("Enter any string : ");
scanf("%s",str);
while(str[++i]!='\0');
while(i>=0)
rev[j++] = str[--i];
rev[j]='\0';
printf("Reverse of string is : %s",rev);
return 0;
}
while(str[++i]!='\0');
is equivalent to
while(str[++i]!='\0')
/*do nothing*/;
which is equivalent to
++i;
while (str[i]!='\0') {
++i;
}
and
while(i>=0)
rev[j++] = str[--i];
is equivalent to
while (i>=0) {
--i;
rev[j] = str[i];
++j;
}
Note that i is decremented before the statement since --i is a pre-decrement, whereas j is incremented after the statement since j++ is a post-increment.
I'll try to answer as best as i can...
Why while is ended with ;
This is valid syntax, it's often used to cause the program to wait at that line until a certain flag is set in an embedded scenario. In this case it's used to find the length of the string.
All strings are terminated with a null character, which is '\0', and the preincrement on i means that after that line i will hold the value for the length of the string.
Effectively its equivalent to this:
/* If the ith position of the string is not the end */
while (str[i] != '\0') {
/* Increment i and repeat */
i = i + 1;
}
The main concept here is the difference between postincrement and preincrement operators - might be worth reading up on that.
What does while(str[++i]!='\0'); mean?
See above.
3.Is rev[j++] = str[--i]; same as writing j++; and i--; inside the while loop?
If you're asking if its in the while loop, its entirely equivelant to:
while(i>=0) {
rev[j++] = str[i--];
}
Since there is only a single operation in the while loop the brackets aren't needed.
Just a note, and this is entirely subjective, but the majority of coding standards I've come accross use brackets even in this scenario.
Your questions seem to be related mainly to the syntax of C - it might be worth getting a book out or watching some tutorials to familiarise yourself with it.
The ; is there to close the loop
2: while(str[++i]!='\0'); means "Go throuch each char of str until the \0 char is reached".\0 is the ending char of a string
3: Yes
First of all, while(str[++i]!='\0'); increments i until it finds the last character. In C all strings end with \0 or NULL (both are the same).
The second one, no. It is not the same --i than i++.
Check the following code snipet:
int a,b,x=10,y=10;
a = x--;
b = --y;
At the end of execution, a = 10 but b = 9. This is because --y is a pre-decrement. It decrements the value first and then assigns its value to b.
Here's a commented version of the program:
// Include standard input output functions
#include<stdio.h>
// declares the main function. It accept an undefined number
// of parameters but it does not handles them, and returns an integer
int main(){
// declares tho arrays of 50 characters initialized with random values
char str[50];
char rev[50];
// declare and initialize two integer variables
int i=-1,j=0;
printf("Enter any string : ");
scanf("%s",str);
// executes the ';' instruction while the condition is satisfied.
// ';' is an empty statement. Thus do nothing.
// The only action executes here, is the increment of the i variable with
// a preincrement. Because the i variable was initialized with
// -1, the first control start checking if str[0] != '\0'
// If the post increment operator was used, the variable must
// have been initialized with 0 to have the same behaviour.
while(str[++i]!='\0');
// at the end of the previous while, the i variable holds the
// str lenght + 1 (including the '\0')
// starting from the end (excluding the '\0', using the pre-decrement on the i variable)
// assign to rev[j] the variable of str[i], then (post increment)
// increment the j variable
while(i>=0)
rev[j++] = str[--i];
// now j is equals to str lenth +1
// therefore in this position add the null byte
rev[j]='\0';
// print result
printf("Reverse of string is : %s",rev);
// return 0 to the OS
return 0;
}
; means the end of a statement in c.
while(condition)
{
//do something
}
do something means at least one statement should be executed. For this the ; is used here.
while(str[++i]!='\0'); '\0' represents end of the string. Here the loop is terminated at the end of the string and ++i increases i.
Is rev[j++] = str[--i]; same as writing j++; and i--; inside the while loop?
Yes. But as --i increases i before executing rev[j++] = str[--i] so i-- should be before rev[j] = str[i] and j++ increases j after executing rev[j++] = str[--i] so j++ should be after rev[j] = str[i]
The key here is understanding the difference in behaviour between prefix (++i), and postfix (i--) operators.
The prefix operator will increment its operand (i), and then evaluate to the new value.
The postfix operator will evaluate to its operands current value, and then increments the operand afterwards.
As for:
int i = -1;
while (str[++i] != '\0');
This is a loop with no block, because all of the statements can be expressed in the conditional. On each iteration:
Increment i by one.
Get the char at the position i evaluates to.
continue if it is not the NUL character.
This might be better understood when written as:
int i = -1;
do {
i++;
} while (str[i] != '\0');
The result of this operation is that i now holds the position of the NUL character in the string, since all valid character strings must end with the NUL character.
In the next section of the program, the prefix operator is used again to immediately get the character one position before the NUL character, and then one position before that, and so on, until we get the first character of the string, and then we're done.
while(i>=0)
rev[j++] = str[--i];
Why while is ended:
while(str[++i]!='\0')
Once str is an asciiz string it ends with a '\0' character. So while will end whenever the while reaches the end of the string.
The line above means:
=> ++i : Increments the string index before getting the corresponding character.
=> Checks if str[index] != '\0' // End of the string reached
On the end of while the i variable will contain the string length (excluding the '\0' character).
It would be easier to use this:
i = strlen(str);
Is rev[j++] = str[--i]; same as writing j++; and i--; inside the while loop?
No.
This line is the same as:
while(i>=0)
{
i = i - 1;
rev[j] = str[i];
j = j + 1;
}
--i : Gets the string character after decrementing i.
If you changed to i-- the code would get the str[i] before decrementing i, but it is not what you want.

How are these characters produced?

int main(void)
{
char s[] = "Hsjodi", *p;
for(p = s; *p; p++)
--*p;
puts(s);
return 0;
}
The output writes Grinch but I cant understand how this code executes. How can it write out Grinch when such letters G,r,i for example does not exist in the char array and when does loop terminates our exactly does *p means?
First of all, notice that for loop does not have any braces to create a block, so the loop body is only
--*p;
which is same as
--(*p);
Now, as per the above statement all the elements in the array, until the terminating null, has been reduced one place. That means, H is now G, s is now r and so on.NOTE
Also, the condition check in the loop *p is a short-hand form of writing *p != '\0' or *p != 0.
After the decrement through the loop, the modified array has been printed through puts().
NOTE: You may want to check the ASCII table for reference.

Can someone explain this C code? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Can someone explain this reverse sentence code for me? How does the first and the second looping works? What's the point of each of them?
main(){
char arr[255], *p;
printf("Enter string: ");
gets(arr);
for(p=arr; *p!='\0'; p++);
for(p--; p>=arr; p--){
printf("%c",*p);
}
}
Input:
I love you
Output:
uoy evol I
The code is basically printing in reverse the input array.
for(p=arr; *p!='\0'; p++);
Sets p as the last (relevant) element of the array (the null character)
for(p--; p>=arr; p--){
printf("%c",*p);
}
starts from the last (none null) character and prints each one from last to first.
Question for you:
What happens if the input array is longet than 255 chars? (answer below)
buffer overflow
Suppose the input is Hello World. This gets stored in your buffer arr as
[H][e][l][l][o][ ][W][o][r][l][d][\0]...
Your pointer is set to arr, hence the pointer points to H
[H][e][l][l][o][ ][W][o][r][l][d][\0]...
^
|
p
The first loop advances (p++) until it meets the first null character (\0). It now looks like
[H][e][l][l][o][ ][W][o][r][l][d][\0]...
^
|
p
Now the second loop goes back (p--) until it reaches the first character again (actually, until the pointer equals the pointer to the beginning of the array), printing each character as it meets it. The first character \0 however is ignored with the little p-- here:
for(p--; p>=arr; p--)
^^^
The code looks clever, but it actually exhibits undefined behavior, which means the code may do anything.
The problem is the second loop:
for(p--; p>=arr; p--){
printf("%c",*p);
}
What it's intended to do is to start p at the last character of the string (excluding the terminating \0, then keep decrementing it until all the characters of the string have been output in reverse order.
The problem is the termination condition: after the intended end of the loop, p is arr, and then p-- subtracts one, and then p >= arr is false.
Unfortunately, an arithmetic operation on pointers may not result in a pointer that no longer points to the object (or one after the final object of an array), or it's undefined behavior.
That's what's happening here: p-- causes p to be off the array, and all bets are off as to what happens next.
Here's a correct way to write the second loop:
for (int i = (p-arr)-1; i >= 0; i--) {
printf("%c", p[i]);
}
I'd probably write the entire code using indexes to completely avoid pointer arithmetic. Maybe something like this:
int i = 0;
// Find the terminating \0 byte
while(p[i])i++;
// Iterate backwards through the string, outputting characters along the way.
while(--i >= 0)putc(p[i]);
Before explaining the code, I must say two things - first, the signature of the main function should be one of the following -
int main(void);
int main(int argc, char *argv[]);
and second, do not use gets. It's not safe to use. Use fgets instead. Now, coming to the code.
for(p = arr; *p != '\0'; p++) ;
In the above loop, p is assigned the base address of the array arr, i.e., the address of the first element of the array arr. The array arr contains a terminating null byte which means it is a string. The loop body is the null statement ; which means p is incremented till the null byte is encountered, i.e., when the test *p != '\0' fails. In the for loop
for(p--; p >= arr; p--) {
printf("%c",*p);
}
p is first decremented to point to the last character just before the null byte and then it is printed in each iteration till the condition p >= arr is true, i.e., till the first element of the array is reached. You should change your code to -
#include <stdio.h>
int main(void) {
char arr[255], *p;
printf("Enter string:\n");
fgets(arr, sizeof arr, stdin);
for(p = arr; *p! = '\0'; p++)
; // the null statement
for(p--; p >= arr; p--)
printf("%c", *p);
return 0;
}

Unexpected C code output

This is my c code:
#include <stdio.h>
int main(){
int x[] = {6,1,2,3,4,5};
int *p=0;
p =&x[0];
while(*p!='\0'){
printf("%d",*p);
p++;
}
return 0;
}
When run the output is 612345-448304448336
What are the digits after the minus sign and why is my code giving this?
The condition *p != '\0', which is the same as *p != 0, is never met because your array doesn't contain an element of value 0, and thus you overrun the array bounds and step into undefined behaviour.
Instead, you should control the array range directly:
for (int const * p = x; p != x + sizeof(x)/sizeof(x[0]); ++p) // or "p != x + 6"
{
printf("%d", *p);
}
You run the loop till you encounter a \0 but your array was never \0 terminated.
int x[] = {6,1,2,3,4,5};
creates an array which is not \0 terminated. You will have to explicitly add a \0 as the last element.
Since the array is not \0 terminated the while() loops run until a random \0 is encountered. Technically, this is Undefined Behavior because you are reading the contents of memory which is not allocated to your variable.
Suggested Solution:
int x[] = {6,1,2,3,4,5,0};
while(*p != 0)
Arrays in C are not Null Terminated. Which is why your loop goes beyond the end of your declared array. The digits follows 5 are just whatever happens to be in that memory space. If there hadn't been a null character following your allocation of the array the loop would have continued running until it made a SegFault.

Resources