explain this code

Thread Starter

TAKYMOUNIR

Joined Jun 23, 2008
352
Rich (BB code):
#include <stdio.h>
#include<ctype.h>
 void main(void)
 {
 char text[512], *ptr;
 int keystrokes=0, vowels=0, alphabetic=0;
printf("Enter text: ");
 gets(text);
for (ptr=text; *ptr; ptr++) {
 if (*ptr <='127' ||*ptr >= '0') keystrokes++;
  if (*ptr == 'a' || *ptr == 'e' || *ptr == 'i' || *ptr == 'o' || *ptr == 'u' ||*ptr == 'A' || *ptr == 'E' || *ptr == 'I' || *ptr == 'O' || *ptr == 'U')
 vowels ++;
  if ((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z')) alphabetic++;
  }
 printf("There were:\r\n");
 printf(" %d vowel%s\r\n", vowels, vowels == 1 ? "" : "s");
 printf(" %d alphabetic%s\r\n", alphabetic, alphabetic == 1 ? "" : "s");
 printf(" %d keystroke%s\r\n", keystrokes, keystrokes == 1 ? "" : "s");
  return 0;
 }
what the different between *ptr and ptr in this code and also how this code work(printf(" %d keystroke%s\r\n", keystrokes, keystrokes == 1 ? "" : "s");
 
Last edited:

takao21203

Joined Apr 28, 2012
3,702
Rich (BB code):
char text[512], *ptr;
is misleading.

Rich (BB code):
char text[512];
char* ptr;
and...

Rich (BB code):
ptr= &txt;
*ptr=65;
ptr+=1;
*ptr=66;
 

ErnieM

Joined Apr 24, 2011
8,377
what the different between *ptr and ptr in this code
Generally when one defines "ptr" as:

char *ptr;

is is a pointer to a character. "ptr" is the address of this item, and "*ptr" is the content of that address. The asterisk "de-references" the address popping off one level of indirection.

I have also heard it said that the asterisk * is a star, and one can thing of "*ptr" as "star-pointer," which is a quick mental step to "stored (at) pointer."

how this code work(printf(" %d keystroke%s\r\n", keystrokes, keystrokes == 1 ? "" : "s");
Ugh. I don't use printf as in my micro work it is a huge routine so I don't know all it's details, and it has plenty as it attempts to be all things to all people. Here the argument has 3 parts:

PART 1:
" %d keystroke%s\r\n" print specifier. %d means integer number (AFAIK), keystrokes here within the quotes is literal text, %s means a string. \r\n is carriage return-line feed.

PART 2:
keystrokes, the integer to print in part 1.

PART 3:
keystrokes == 1 ? "" : "s"
tricky devil. The author is using the C short form of if-then-else to make the output say "1 keystroke" or "2 keystrokes" using this. The specifier is looking for a string, and this is returning "" for 1 keystroke or "s" for more then 1 (though for zero also, so there seems to be a bug).
 

WBahn

Joined Mar 31, 2012
30,058
what the different between *ptr and ptr in this code and also how this code work(printf(" %d keystroke%s\r\n", keystrokes, keystrokes == 1 ? "" : "s");
As others have pointed out, and I am just saying it every so slightly differently, when you have a variable defined as:

char *ptr;

The variable that is created is called 'ptr' but what is stored in 'ptr' is not a value of type char, but rather the address at which such a value is stored.

As will all (automatic) variables in C, the variable 'ptr' starts out uninitialized and therefore has a random value stored in it. If you try to use it in that condition, the most likely thing that will happen is that your program will attempt to access memory that doesn't belong to it and the OS will kill your program, reporting an Unhandled Exception or Access Violation or something similar.

When you define an array:

char text[512];

The "variable" that is created is named 'text' and it also stores the address at which a value of type char is stored, but in this case we told the compiler to actually create storage for 512 such variables, all in a successive block of memory, and to store the address of the first one of these as the value of 'text'. Now, there is a subtle distinction between 'ptr' as a variable and 'text' as a "variable", but not one that matters to us here.

So when you have

for (ptr=text; *ptr; ptr++)

You first set the value of 'ptr' equal to the value of 'text', which means that both now have the address of the same piece of memory in them.

Given a variable that has an address stored in it (called a pointer variable), we can get at the value that is stored at that address by "dereferencing" the pointer. There are a couple ways to do this. The first is to use the dereference operator, which is the asterisk. So the code:

y = *ptr;

says to set y equal to the value of the character value stored at the address contained in the variable ptr.

Another is to use the array dereference operator.

y = ptr[0];

is exactly the same thing. In general, appending an integer expression that evaluates to n inside square brackets after a pointer says to begin at the address stored in the pointer and then count forward in memory far enough to access the nth item of whatever type of object the pointer points to.

So the following two lines are identical (in fact, the compiler is free to translate one into the other at will)

y = ptr[7];
y = *(ptr+7);

And, since addition is commutative, these are also equivalent to

y= *(7+ptr);
y = 7[ptr];

Getting back to our for() loop:

for (ptr=text; *ptr; ptr++)

ptr=text; // Make ptr point to the first character in the array text[]
*ptr // As long as the value at the address pointed to by ptr is not 0
ptr++ // Increment the value of the address (NOT the value stored AT the address) so that ptr now points to the next character in the text[] array.

Turning to the printf() statement:

printf(" %d keystroke%s\r\n", keystrokes, keystrokes == 1 ? "" : "s");

The %d says to print the first argument as a decimal integer.

The %s says to assume the second argument is an address and to assume it is the address of the first character of a string of characters. Print each character starting at that address until you come upon one whose value is zero.

The \r says to return the cursor to the beginning of the current line without advancing to the next line.

The \n says to move the cursor to the beginning of the next line (making the \r irrelevant).

keystrokes == 1 ? "" : "s"

This is the conditional operator and, in this case, implicitly binds as:

( (keystrokes == 1) ? ("") : ("s") )

This of this as

(a?b:c)

If a is true (any value other than exactly zero), the expression evaluates to b, otherwise, it evaluates to c.

So, in this case, is keystrokes is exactly equal to 1, the expression will evaluate to the address of an empty string, otherwise it will evaluate to the address of a string consisting only of the character 's'.

The point is to automatically turn the word 'keystroke' into 'keystrokes' if there is anything other than exactly one keystroke.

In general, be careful when using the conditional operator. It is very low on the precedence of operators and therefore has a tendency to bind to things to either side of it in ways you might not expect or want. I recommend always isolating it explicitly with parentheses to force it to bind the way you intended.
 
Top