简体   繁体   中英

how puts function , pointer and string work? why would strchr() get characters after the searched character?

The example is below. In my understanding, t and p are the same pointers pointing to the address of a string? I get confused with pointer and string. Would puts(p) give the address of the string instead of characters? Also, I can't figure out how strchr funcition works. ++p would point to the next character after ':', that is how it works, is it correct? Please help! Thanks.

char *t = "MEAS:VOLT:DC?";
char *p;  
p = t;     
puts( p );
while(( p = strchr( p, ':' )) != NULL )
{ puts( ++p )}}

What is a pointer? A pointer is variable that stores an address (memory location). This can be the address of another variable

int n = 9;
int *ptr = &n; // stores the address of n

or it can be the start of a memory block, for example a dynamically allocated memory block:

int *fields = malloc(len * sizeof *fields);

Whatever address a pointer is pointing to, we use pointers to directly access the memory that is stored in the pointer (we also say where the pointer is pointing to ).

What are strings? What you've got to understand is that C does not have a string type like other programming languages do. In C a string is just a sequence of 8-bit values (representing characters) that end with the '\\0' -terminating byte. The natural type for a single character is a char , that's why we use char* or char[] to get a string.

When you do

const char *str = "Hello";

str points somewhere in memory and it looks like this:

b = base address of the first character in the
    sequence

b     b+1   b+2   b+3   b+4   b+5
+-----+-----+-----+-----+-----+------+
| 'H' | 'e' | 'l' | 'l' | 'o' | '\0' |
+-----+-----+-----+-----+-----+------+

The integer values of character constants like 'H' are determine by the ASCII table. So in reality the memory looks like this:

b = base address of the first character in the
    sequence

b     b+1   b+2   b+3   b+4   b+5
+----+-----+-----+-----+-----+-----+
| 72 | 101 | 108 | 108 | 111 |  0  |
+----+-----+-----+-----+-----+-----+

So str points to that location b , str[0] is the first character, str[1] is the second, etc. As you see, to get a string, all you need is access to the first character in the sequence. That's the reason why we use a char* pointer to address strings, because with the char* pointer we have access to the first and the subsequent characters in the string.

A function like puts(str) does the following:

  • is the current character the '\\0' -terminating byte?
    • if yes, then exit
    • if no, then print the character and advance to the next one

So puts(str) does not print the address where the pointer is pointing, it prints the contents of the memory where the pointer is pointing to.

A function like strchr works like this:

man strchr

 char *strchr(const char *s, int c); 

DESCRIPTION

The strchr() function returns a pointer to the first occurrence of the character c in the string s .

Now that you know about the memory layout of strings, this should be easy to understand. Let's take a look at this:

const char *str = "Hello";
char *f = strchr(str, 'l');

Remember, the memory layout for where str is pointing to is:

b = base address of the first character in the
    sequence

b     b+1   b+2   b+3   b+4   b+5
+-----+-----+-----+-----+-----+------+
| 'H' | 'e' | 'l' | 'l' | 'o' | '\0' |
+-----+-----+-----+-----+-----+------+
               ^
               ¦
       first occurrence
            of 'l'

so what strchr returns is a pointer pointing to b+2 (or str+2 , because in my example b is the value that the pointer str is storing).

That's why when do you puts(str) you get Hello , and when you do puts(f) you get llo .

A simple implementation for strchr is:

char *strchr(const char *s, int c);
{
    // stop when the \0-terminating byte is reached
    for(size_t i = 0; s[i] != '\0'; ++i)
    {
        if(s[i] == c)
            return &s[i];  // or return s+i; using pointer arithmetic
    }

    return NULL; // c is not found in the string
}

So what does this do?

while(( p = strchr( p, ':' )) != NULL )
{ 
    puts( ++p )
}

The first time that strchr returns a value that is not NULL , it will return a pointer to the first occurrence of the colon : . puts(++p) is equivalent to

p = p + 1; // let p point to the next next character after the colon
puts(p);   // prints the string

then strchr is executed again, because there is one more colon : in the string, it will not return NULL but the location of where : is stored. The next time the loop is executed, there are no more colons and strchr will return NULL , thus ending the loop. So the output will be:

MEAS:VOLT:DC?       // puts( p );
VOLT:DC?            // 1. puts( ++p ); of the loop
DC?                 // 2. puts( ++p ); of the loop

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM