Upload
nasnan
View
33
Download
0
Embed Size (px)
DESCRIPTION
15-213 C Primer Session – 1/25/01. Outline Hello World Command Line Arguments Bit-wise Operators Dynamic Memory / Pointers Function Parameters Structures. 1. Hello World. #include int main( int argc, char *argv[]) { printf(“Hello World\n”); return 0; }. - PowerPoint PPT Presentation
Citation preview
15-213 C Primer Session – 1/25/01
Outline• Hello World• Command Line Arguments• Bit-wise Operators• Dynamic Memory / Pointers• Function Parameters• Structures
1. Hello World
#include <stdio.h>
int main(int argc, char *argv[]){ printf(“Hello World\n”); return 0;}
Hello World (Ver. 2)
#include <stdio.h>
#define MYSTRING “Hello World\n”
int main(int argc, char *argv[]){ printf(MYSTRING); return 0;}
Hello World (Ver. 3)
#include <stdio.h>
#ifdef HELLO#define MYSTRING “Hello World\n”#else#define MYSTRING “Goodbye World\n”#endif
int main(int argc, char *argv[]){ printf(MYSTRING); return 0;}
2. Command Line Arguments
• ls –l *.txt– How does a program obtain the ‘-l’
and ‘*.txt’?– Use the argc and argv parameters to
main()• argc – Number of arguments (including
program name)• argv – Array of strings of all arguments
(including program name)
#include <stdio.h>
main(int argc, char *argv[]){ int j, sum; char *pchar;
printf ("Program called : %s\n", *argv ); /* print 0th arg, program called */
if ( argc < 4 ) printf ( "Not enough arguments\n" ); /* see if enough args to perform op */ else { pchar = *(argv + 1); /* get pointer to 1st arg */ if ( *pchar == '+' ) /* if +, continue */
{ sum = 0; printf ( "Numbers : " ); for ( j = 2; j < argc; j++ ) { sum += atoi ( *(argv + j) ); /* each arg -> int, add to sum */ printf ( "%s ", *(argv + j) ); /* print argument */ } printf ( "\nSum : %i\n", sum ); /* print sum */}
elseprintf ( "Unsupported\n" ); /* operation unsupported */
}}
3. Bit-wise OperatorsExample Problems
/* * bitNor - ~(x|y) using only ~ and & * Example: bitNor(0x6, 0x5) = 0xFFFFFFF8 * Legal ops: ~ & * Max ops: 8 * Rating: 1 */int bitNor(int x, int y) {
}
return (~x & ~y);
/* * logicalShift - shift x to the right by n, * using a logical shift * Can assume that 1 <= n <= 31 * Examples: logicalShift(0x87654321,4) = 0x08765432 * Legal ops: ~ & ^ | + << >> * Max ops: 16 * Rating: 3 */int logicalShift(int x, int n) {
}
/* Shift normally, using XOR to clear any bits * on the left of the result that should always * be 0 instead of the sign */
return (x >> n) ^ (((x & (1 << 31)) >> n) << 1);
/* * bang - Compute !x without using ! * Examples: bang(3) = 0, bang(0) = 1 * Legal ops: ~ & ^ | + << >> * Max ops: 12 * Rating: 4 */int bang(int x) {
}
int minus_x = ~x+1;
/* Cute trick: 0 is the only value of x * for which neither x nor -x are negative */
int bits = (minus_x | x) >> 31; /* -1 or 0 */return bits + 1;
4. Dynamic Memory & Pointers
• Java manages memory for you, C does not– C requires the programmer to allocate and
unallocate memory• For instance, int x tells C to allocate 4 bytes for
an integer
– Unknown amounts of memory can be allocated dynamically during run-time with malloc() and unallocated using free()
Code!#include <stdio.h> #include <string.h>
#define HELLO_MIXED "Hello world!"#define HELLO_CAPS "HELLO WORLD!"
int main (int argc, char *argv){ char *original_string; char *copied_string; int index;
/* Allocate space for the string. * Strings are terminated with a NULL. * Don't forget to include space for this terminator. */ original_string = (char *) malloc (strlen (HELLO_MIXED) + 1); if (!original_string) { printf ("malloc() has failed\n"); exit (-1); }
/* Initialize the string */strncpy (original_string, HELLO_MIXED, strlen (HELLO_MIXED));
/* 1st attempt to copy the string */copied_string = original_string;
/* It looks like it worked */printf ("Original String: %s\nCopied String: %s\n\n", original_string, copied_string);
/* Now, let's change the original string to be all uppercase */strncpy (original_string, HELLO_CAPS, strlen (HELLO_CAPS));
/* Let's take a look at those two strings again */printf ("Original String: %s\nCopied String: %s\n", original_string, copied_string);
/* What happened? We copied the address, not the content. * We made an alias */printf ("Original String address: 0x%p\nCopied String Address: 0x%p\n\n", original_string, copied_string);
/* To fix this, we could allocate space * for a new string using malloc() * and then use strncpy() to copy the contents, as before. But, we * can actually do this in one step with strdup() */copied_string = strdup(original_string);
/* Now, let's test things again */
/* They look the same, but are they actually different? */printf ("Original String: %s\nCopied String: %s\n\n", original_string, copied_string);
/* Let's see */strncpy (original_string, HELLO_MIXED, strlen (HELLO_CAPS));
/* Perfect. This time it works */printf ("Original String: %s\nCopied String: %s\n", original_string, copied_string);printf ("Original String address: 0x%p\nCopied String Address: 0x%p\n\n", original_string, copied_string);
/* Strings are actually arrays of characters. We can access the * characters, including the NULL, one at a time by using their * address. Notice the use of the * operator to dereference a * character pointer. Also notice that the pointer moves by * one byte each time -- what one would expect from "++". */
/* Notice strlen() + 1. strlen() doesn't count the NULL, * but we want to see it */for (index=0; index < (strlen (original_string) + 1); index++){ printf ("0x%p: %c (%d)\n", original_string + index, *(original_string + index), (int)*(original_string + index));}printf ("\n");
/* We can also use a shortcut notation: original_string[index]. * The preprocessor will convert this to *(original_string + index) * for us */
for (index=0; index < (strlen (original_string) + 1); index++){ printf ("0x%p: %c (%d)\n", original_string + index, original_string[index], (int)original_string[index]);}
/* Lastly, let's give back the space that we allocated * I like to set the pointers to NULL to indicate that * they are not allocated. */free (original_string);original_string = NULL;
free (copied_string);copied_string = NULL;
return 0;}
Integer Arrays#include <stdio.h>
#define ARRAY_COUNT 5
int main (int argc, char *argv){ int *int_array; int index;
/* Allocate space for the ints * Only strings are null terminated -- int arrays are not. * * Here, the use of sizeof() is critical * -- ints are more than 1 byte */ int_array = (int *) malloc (ARRAY_COUNT * sizeof(int)); if (!int_array) { printf ("malloc() has failed\n"); exit (-1); }
/* Initialize the array */for (index=0; index < ARRAY_COUNT; index++){ *(int_array + index) = index;}
/* Make sure it worked * Notice the use of the & operator. This returns the address of * an object in memory. */for (index=0; index < ARRAY_COUNT; index++){ printf ("int_array[%d]=%d at address 0x%p (decimal %d)\n", index, int_array[index], &(int_array[index]), &(int_array[index]));}printf ("\n");
/* But wait! Why did that work? We only added one, * and integers are larger than one byte. * * The joys of "Pointer Arithmetic". When adding or * incrementing pointers, C automatically adds or * increments multiples of the size of the data type. * * Take a second look at the output of the loop and the * addresses. * * Now, take a look at the size of int printed below */printf ("sizeof(int) = %d bytes", sizeof(int));printf ("\n");
/* Clean-up */free (int_array);int_array = NULL;
return 1;}
5. Function Parameters
• Function arguments are passed “by value”.
• What is “pass by value”?– The called function is given a copy of the
arguments.
• What does this imply?– The called function can’t alter a variable in
the caller function, but its private copy.
Example 1
Example 1:
void swap_1(int a, int b){
int temp;
temp = a;a = b;b = temp;
}
Q: Let x=3, y=4,
after swap_1(x,y);
x =? y=?
A1: x=4; y=3;
A2: x=3; y=4;
Example 2: swap_2
Example 2:
void swap_2(int *a, int *b){
int temp;
temp = *a;*a = *b;*b = temp;
}
Q: Let x=3, y=4, after
swap_2(&x,&y); x =? y=?
A1: x=3; y=4;
A2: x=4; y=3;
Example 3: scanf
Example 3:
#include <stdio.h>
int main(){
int x;scanf(“%d\n”, &x);printf(“%d\n”, x);
}
Q: Why using pointers in scanf?
A: We need to assign the value to x.
Using Libraries
• What are libraries?• Using libraries
• Finding library functions> man printf
#include <stdio.h>...printf(“Hello, world!\n”);...
I/O operations
• Header: stdio.h• Functions:
void printf(char * format, ...);int scanf(char * format, ...);...
String operations
• Header: string.h• Functions:
int strlen(char * str);int strcmp(char * str1, char * str2);char * strcpy(char * dest, char * orig);char * strchr(char * str, char ch);...
6. Structures
• Structures enables a programmer to group together related data– Sort of like a class, but structures only
encapsulate data
More Code!#include <stdio.h>#include <string.h>#include <malloc.h>
#define MAX_STRING 20#define MAX_STUDENTS 6
/* A C struct is a data type that groups of objects of * possibly different types into a single object. */struct student { char first[MAX_STRING]; char last[MAX_STRING]; char id[MAX_STRING]; int age;}; int main(int argc, char **argv){ int n, index;
/* Allocate memory for an array of students. * Make sure to use sizeof when allocating memory for a struct. * Because of memory alignment issues, * struct may require more memory * than you think, so shouldn't hand calculate size. */ struct student *roster = (struct student *) malloc(MAX_STUDENTS * sizeof(struct student));
struct student tmpStudent;
/* Open text file with all of the student information * for reading. */ FILE *fid = fopen("students.txt", "r"); if(!fid) { printf("Error opening file for reading.\n"); return 1; }
/* FILL IN STRUCT ARRAY */ index = 0; while(fid && (index < MAX_STUDENTS)) { /* fscanf reads from the supplied stream 'fid‘ * under a controlled format * and assigns the converted values to the args provided. * Note: Each argument must be a pointer. * fscanf returns 0 when the format is exhausted * returns EOF if end of file or an error occurs * else returns number of items converted. */ n = fscanf(fid, "%s %s %s %d\n", tmpStudent.first, tmpStudent.last, tmpStudent.id, &(tmpStudent.age));
if (n == 0) { printf("Error scanning file.\n"); return 1; } if (n == EOF) break;
strncpy((*(roster + index)).first, tmpStudent.first, strlen(tmpStudent.first)); strncpy((*(roster + index)).last, tmpStudent.last, strlen(tmpStudent.last)); strncpy((*(roster + index)).id, tmpStudent.id, strlen(tmpStudent.id)); (*(roster + index)).age = tmpStudent.age;
/* Much easier way to do this copying */ memcpy((void *) (roster + index), (const void *) &tmpStudent, sizeof(struct student));
index++; }
/* PRINT OUT STRUCT ARRAY */ for(index = 0; index < MAX_STUDENTS; index++) { /* Notice here simpler way of accessing fields in struct. * '->' is a pre-processor shortcut for (*sptr).field */
printf("Student #%d: %s\t%s\t%s\t%d\n", index + 1, roster->last, roster->first, roster->id, roster->age); roster++; };
/* Clean-up */ free(roster); roster = NULL; fclose(fid); return 0;}