1 / 31

15-213 C Primer Session – 1/25/01

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 &lt;stdio.h&gt; int main( int argc, char *argv[]) { printf(“Hello World<br>”); return 0; }.

nasnan
Download Presentation

15-213 C Primer Session – 1/25/01

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 15-213 C Primer Session – 1/25/01 Outline • Hello World • Command Line Arguments • Bit-wise Operators • Dynamic Memory / Pointers • Function Parameters • Structures

  2. 1. Hello World #include <stdio.h> int main(int argc, char *argv[]) { printf(“Hello World\n”); return 0; }

  3. Hello World (Ver. 2) #include <stdio.h> #define MYSTRING “Hello World\n” int main(int argc, char *argv[]) { printf(MYSTRING); return 0; }

  4. 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; }

  5. 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)

  6. #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 */ } else printf ( "Unsupported\n" ); /* operation unsupported */ } }

  7. 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);

  8. /* * 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);

  9. /* * 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;

  10. 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()

  11. 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); }

  12. /* 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);

  13. /* 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);

  14. /* 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");

  15. /* 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; }

  16. 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); }

  17. /* 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");

  18. /* 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; }

  19. 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.

  20. 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;

  21. 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;

  22. 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.

  23. Using Libraries • What are libraries? • Using libraries • Finding library functions > man printf #include <stdio.h> ... printf(“Hello, world!\n”); ...

  24. I/O operations • Header: stdio.h • Functions: void printf(char * format, ...); int scanf(char * format, ...); ...

  25. 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); ...

  26. 6. Structures • Structures enables a programmer to group together related data • Sort of like a class, but structures only encapsulate data

  27. 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;

  28. /* 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; }

  29. /* 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;

  30. 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++; }

  31. /* 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; }

More Related