pointer to pointer

A

arnuld

Its just a very simple and basic program to learn exactly what is
described in comments here. Can you provide a better (and short)
exercise ?


/* A program to learn how to use a pointer to a pointer. Here we take an
array of char pointers. A char* in the array, of course, points
* to some char. Array has only one element. We change the value of char
pointed by array's element using a function.
*
* VERSION 0.0
*/
#include <stdio.h>

void replace_char_value(char* [], char);

int main(void)
{
char* arrc[2] = {0};
char c = 'c';
arrc[0] = &c;

printf("*arrc: %p, **arrc: %c\n", (void*)*arrc, **arrc);
replace_char_value(arrc, 'w');
printf("*arrc: %p, **arrc: %c\n", (void*)*arrc, **arrc);

return 0;
}


void replace_char_value(char* arr[], const char t)
{
**arr = t;
}

==================== OUTPUT =======================
[arnuld@dune programs]$ gcc -ansi -pedantic -Wall -Wextra pointer-to-
pointer.c
[arnuld@dune programs]$ ./a.out
*arrc: 0xbfffe8ab, **arrc: c
*arrc: 0xbfffe8ab, **arrc: w
[arnuld@dune programs]$
 
I

Ian Collins

Its just a very simple and basic program to learn exactly what is
described in comments here. Can you provide a better (and short)
exercise ?

Parse the arguments to a program. Don't forget argv is a pointer to
pointer!

Given ./a.out -a 10 -b 20

print out the values of a and b.
 
M

Mark Wooding

arnuld said:
Its just a very simple and basic program to learn exactly what is
described in comments here. Can you provide a better (and short)
exercise ?

Several linked-list idioms involve a pointer-to-a-pointer. The most
obvious ones are

* Removing an item from a singly-linked list.

* Inserting an item into a sorted singly-linked list.

* Building up a list in order, one at a time.

The last is especially simple, and will serve as an example of the
general technique. Suppose that you have a node structure like this

struct node {
struct node *next;
/* other members here */
};

You build a list in order by remembering where the trailing link is.
Initially, the trailing link is actually the list head pointer.

struct node *head, **tail = &head;
struct node *n;

To attach a new node n to the list, you do this:

*tail = n;
tail = &n->next;

and finally you terminate the list like this:

*tail = 0;

I encourage you to draw diagrams to see why this works.

Of course, you can abstract the core of the algorithm into a function.
If you do this in the obvious way, you will find that you need to pass
in the /address/ of the trailing-link pointer, which is a pointer to a
pointer to a pointer:

static link_to_end(struct node *n, struct node ***tail)
{
**tail = n;
*tail = &n->node;
}

This is the simplest natural example I know of for a `three-star'
pointer.

-- [mdw]
 
A

arnuld

Parse the arguments to a program. Don't forget argv is a pointer to
pointer!

Given ./a.out -a 10 -b 20

print out the values of a and b.


How about this. Two questions:

(1) How to write it better ?
(2) How to avoid OUTPUT-2 ?



/* A program given by Ian Collins on CLC. Parse input to C Program this
way:
* GIVEN: ./a.out a -10 b 2, print out values of a and b
*
* Assumptions: separator between 2 values is one space. User may enter
two elements together without any value but then program will
* take 2nd element as value of first element.
* VERSION 0.0
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void printElementAndValue(char** t);

int main(int argc, char* argv[])
{
/* char* pe; Pointer to element */
/* char* pv; Pointer to value */
char** t;

if(1 == argc)
{
printf("USE: ./a.out [ELEMENT1] [VALUE1] [ELEMENT2] [VALUE2] ....
\n");
exit(EXIT_FAILURE);
}
else if(0 == (argc % 2))
{
printf("Please enter proper input: [ELEMENT] [VALUE] \n");
exit(EXIT_FAILURE);
}

for(t = argv + 1; *t; ++t, ++t)
{
printElementAndValue(t);
}

return 0;
}


void printElementAndValue(char** t)
{
const char element_identifier = '-';
if(strchr(*t, element_identifier))
{
printf("%s = ", *t++);
printf("%s\n", *t);
}
else
{
printf("Improper input. Key identifier, '-', was not used ?\n");
}

}
==================== OUTPUT ==============================
[arnuld@dune programs]$ gcc -ansi -pedantic -Wall -Wextra PtoP_argv-
parse.c
[arnuld@dune programs]$ ./a.out -a 10 -b 3
-a = 10
-b = 3
[arnuld@dune programs]$



================= OUTPUT-2 ==========================
[arnuld@dune programs]$ ./a.out -a 10 -b *
-a = 10
-b = a.out
Improper input. Key identifier, '-', was not used ?
Improper input. Key identifier, '-', was not used ?
problem-scanf.c = PtoP_argv-parse.c
PtoP_argv-parse.c~ = scanf-problems.c
sequence-point.c = strcpy.c
Improper input. Key identifier, '-', was not used ?
[arnuld@dune programs]$
 
C

Chad

Parse the arguments to a program.  Don't forget argv is a pointer to
pointer!

Given ./a.out -a 10 -b 20

print out the values of a and b.

I don't get the point of this exercise. Maybe I'm missing "it'.
Anyways, here is what I came up with..

#include <stdio.h>

int main(int argc, char **argv)
{
int i;
char dash, letter;

for (i = 1; i < argc; i++) {
dash = argv[0];
letter = argv[1];

if (dash == '-' && letter == 'a') {
printf("a = %s\n", argv[++i]);
}
if (dash == '-' && letter == 'b') {
printf("b = %s\n", argv[++i]);
}
}

return 0;
}

[cdalten@localhost oakland]$ gcc -Wall -Wextra -ansi -pedantic
parseab.c -o parseab
[cdalten@localhost oakland]$ ./parseab -a 10 -b 20
a = 10
b = 20
[cdalten@localhost oakland]$ ./parseab -a 10
a = 10
[cdalten@localhost oakland]$ ./parseab -b 40
b = 40
[cdalten@localhost oakland]$ ./parseab
[cdalten@localhost oakland]$ ./parseab b 40
[cdalten@localhost oakland]$ ./parseab a 40
[cdalten@localhost oakland]$ ./parseab a 40 b 40
[cdalten@localhost oakland]$ ./parseab -b 40 -a 100
b = 40
a = 100
[cdalten@localhost oakland]$
 
C

Chad

I don't get the point of this exercise. Maybe I'm missing "it'.
Anyways, here is what I came up with..

And here is my attempt at the pointer solution. It's kind of ugly, but
it appears to work correctly...

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
char *letter ="";
char *number ="";

while (--argc > 0) {
letter = *++argv;
number = *++argv;

if (letter != NULL && (strcmp(letter, "-a")) == 0 ) {
if(number != NULL && (strcmp(number, "-b")) == 0 ) {
number = *++argv;
if (number != NULL) {
printf("No number provided for a\n");
printf("b = %s\n", number);
exit(EXIT_SUCCESS);
} else {
printf("No number provided for a and b\n");
exit(EXIT_FAILURE);
}
}
printf("a = %s\n", number ? number : "No number provided for a
\n");
}
if (letter != NULL && (strcmp(letter, "-b")) == 0 ) {
if(number != NULL && (strcmp(number, "-a")) == 0 ) {
printf("No number provided for b and a\n");
exit(EXIT_FAILURE);
}
printf("b = %s\n", number ? number : "No number provided for b
\n");
}
}

exit(EXIT_SUCCESS);
}
[cdalten@localhost oakland]$ gcc -g -Wall -Wextra -ansi -pedantic
parseab2.c -o parseab2
[cdalten@localhost oakland]$ ./parseab2
[cdalten@localhost oakland]$ ./parseab2 -a
a = No number provided for a

[cdalten@localhost oakland]$ ./parseab2 -a -b
No number provided for a and b
[cdalten@localhost oakland]$ ./parseab2 -a -b 10
No number provided for a
b = 10
[cdalten@localhost oakland]$ ./parseab2 -a 10 -b
a = 10
b = No number provided for b

[cdalten@localhost oakland]$ ./parseab2 -a 10 -b 20
a = 10
b = 20
[cdalten@localhost oakland]$ ./parseab2 -b 10 -a
b = 10
a = No number provided for a

[cdalten@localhost oakland]$ ./parseab2 -b 10 -a 50 20
b = 10
a = 50
[cdalten@localhost oakland]$
 
I

Ike Naar

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
char *letter ="";
char *number ="";

while (--argc > 0) {
letter = *++argv;
number = *++argv;

You iterate argc-1 times through this loop, and in each iteration
argv is advanced at least two times. That means that for certain
argument lists you're accessing non-existing elements of argv.

Let's take, for example, the argument list ``the quick brown fox''.
argc=5, argv[0]=progname, argv[1]="the", argv[2]="quick",
argv[3]="brown", argv[4]="fox", argv[5]=NULL.

In the first iteration, you handle argv[1] ("the") and argv[2] ("quick").
In the second iteration, you handle argv[3] ("brown") and argv[4] ("fox").
In the third iteration, you handle argv[5] (NULL) and argv[6] (and
here the program goes off the rails).
 
A

arnuld

I don't get the point of this exercise. Maybe I'm missing "it'.
Anyways, here is what I came up with..

#include <stdio.h>

int main(int argc, char **argv)
{
  int i;
  char dash, letter;

  for (i = 1; i < argc; i++) {
    dash = argv[0];
    letter = argv[1];

    if (dash  == '-' && letter == 'a') {
      printf("a = %s\n", argv[++i]);
    }
    if (dash  == '-' && letter == 'b') {
      printf("b = %s\n", argv[++i]);
    }
  }

  return 0;

}

...SNIP....


I think "Ian Collins" meant uknown number of arguments (rather than
two). Still even if he meant two arguments -a and -b, still your
program confuses a bit because at first it iterates for --argc times
but then at same time it it handles only two variables (which may or
may not not equal to --argc). I think if you want to deal with only 2
argiments then (i < 3) must be the conditional check.

Nice cleaner code with array indexing though :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top