Pointers to Pointers, Structures, Pointers to Structures

Pointers to pointers can be used to effectively create and manipulate dynamic two dimensional arrays. Arrays of pointers are extremely useful tools for rapid manipulation of large amounts of data.

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

#define SMALL_BUFFER 256

int readInt(char *buffer, int bounds);
int readPositiveInt(char *buffer, int bounds);
char *readString(char *buffer, int bounds);
void printResults(char **students, int **tests, int numStudents, int numTests);

int main()
{
	int **grades = NULL;
	char **students = NULL;

	int numStudents = 0;
	int numTests = 0;

	int i = 0;
	int j = 0;

	char buffer[SMALL_BUFFER];

	printf("Please enter the number of students ");
	numStudents = readPositiveInt(buffer, SMALL_BUFFER);

	printf("There are %d students.\n", numStudents);


	printf("Please enter the number of tests ");
	numTests = readPositiveInt(buffer, SMALL_BUFFER);

	printf("There were %d tests.\n", numTests);

	//malloc the space for the student names
	students = (char **)malloc(sizeof(char *) * numStudents);

	//malloc the space for the student grades
	grades = (int **)malloc(sizeof(int *) * numTests);

	for (i = 0; i < numStudents; i++) {
		//flush the output buffer of stdin
		fflush(stdin);
		printf("Please enter student #%d's name ", i+1);
		students[i] = readString(buffer, SMALL_BUFFER);

		printf("Please enter the test scores for student %s \n", students[i]);
		//malloc space for the int array
		grades[i] = (int *)malloc(sizeof(int) * numTests);
		for (j = 0; j < numTests; j++) {
			printf("Enter %s's grade for the %d test", students[i], j + 1);
			grades[i][j] = readPositiveInt(buffer, SMALL_BUFFER);
		}
	}

	printResults(students, grades, numStudents, numTests);

    return 0;
}

void printResults(char **students, int **tests, int numStudents, int numTests) {
	for (int i = 0; i < numTests; i++) {
		printf("\nResults for Test %d: \n", i + 1);
		for (int j = 0; j < numStudents; j++) {
			//*(tests + j) gets the column
			printf("%s scored %d\n", *(students + j), *(*(tests + j) + i));
		}
	}
}

int readInt(char *buffer, int bounds) {
	fgets(buffer, bounds, stdin);
	return atoi(buffer);
}

//ensure a positive number is given
int readPositiveInt(char *buffer, int bounds) {
	int rValue;
	while ((rValue = readInt(buffer, bounds)) < 1) { 		
                 printf("Value must be a positive number. Please enter again: "); 
	} 	
return rValue; 
} 

//read a string from standard input 
char *readString(char *buffer, int bounds) { 	
            fflush(stdin); 	
            fgets(buffer, bounds, stdin); 	
            int strLength = strlen(buffer) - 1; 	
            //allocate a string of the exact length needed 	
           char *rValue = (char *)malloc(sizeof(char) * strLength); 	
            //copy the string over backwards from the buffer 	
            *(rValue + strLength) = '\0'; 	
          while (--strLength >= 0) {
		*(rValue + strLength) = *(buffer + strLength);
	  }
	return rValue;
}

Interesting enough, the argv portion of the command line arguments is a pointer pointer as well.

int main(int argc, char *argv[])
{
	
	int i, j;

	char **myArgs = argv;

	//print out arguments as strings
	for (i = 0; i < argc; i++) {
		printf("argument %d = %s\n", i + 1, *(myArgs + i));
	}


    return 0;
}

Structures are aggregate data types, which means that they can store different data types in the same unit. These units, or records, can hold multiple different data types grouped together and accessed via the structure’s name. We can access these different data elements using the dot operator.

const int char_buffer_size = 128;

struct employee {
	int id;
	char name[char_buffer_size];
	int age;
};

void changeName(struct employee *emp);

int main(int argc, char *argv[])
{
	
	struct employee nd = { 411, "Nick Danger", 32 };

	struct employee *empPtr;

	printf("The starting memory address of nd is %p\n", &nd);
	empPtr = &nd;

	printf("empPtr holds %p\n", empPtr);

	printf("His name is %s, third eye.\n", nd.name);
	printf("His name is %s, third eye.\n", empPtr->name);

	changeName(&nd);

	printf("His name is now %s\n", nd.name);
	printf("His name is now %s\n", empPtr->name);

    return 0;
}

void changeName(struct employee *emp) {
	strcpy_s(emp->name, char_buffer_size, "Ivo Shandor");
}

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s