Module 5: Unit 2 Strings, Structs, and I/O

Pointer Fields in C Structures
  • Structures (structs) can contain pointer fields which dynamically manage memory allocation and access large data efficiently.

  • Example structure definition: It is a common practice in C programming to use pointers for string fields to allocate memory dynamically, thereby enabling the management of various string lengths. The following is a simple structure example:

    struct personT { 
        char *name;  // Pointer to a character array for the name
        int age;     // Integer for the age
    }; 
    
  • Memory Allocation for Structs and Pointer Fields: To create instances of structs that contain pointer fields, follow these steps:

    • Define a pointer to the struct: You need a pointer to the struct to access its members within your code.
      c struct personT *p2;

    • Allocate memory for the struct: Use malloc to allocate enough memory for the struct before usage. This allocates memory effectively.
      c p2 = malloc(sizeof(struct personT));

    • Allocate memory for the string (name field): Since name is a pointer, you need to allocate memory for it separately. Here is how you do it and assign a string to it:
      c p2->name = malloc(sizeof(char) * 4); // Allocates space for 4 chars strcpy(p2->name, "Vic"); // Duplicate string "Vic" to the allocated memory p2->age = 19; // Assigning age

Manipulating C Strings
  • Important Libraries: In C, certain libraries provide essential functions for string manipulation, among others. Key libraries include:

    • string.h: Provides functions for string operations like copying, concatenation, and searching.

    • stdlib.h: Contains functions for memory allocation plus conversion utilities.

    • stdio.h: Contains standard input and output functions, essential for interaction with the user.

  • Frequently Used Functions from string.h:

    • strlen(): Determines the number of characters in a string (excluding null terminator).

    • strcpy()/strncpy(): Copies one string to another safely; strncpy prevents buffer overflows by limiting the number of characters to copy.

      • strncpy() Passes in a certain amount of characters

    • strcmp(): Compares two strings lexicographically; useful for sorting or conditional checks.

    • strcat(): Concatenates/Appends one string to another, requiring adequate memory in the receiving string.

      • Returns a string combined together

    • strstr()/strchr(): Used for searching within strings for substrings or characters, respectively.

    • strtok(): Tokenizes (breaks into smaller parts(tokens)) a string based on a given delimiter, which can be critical for parsing input.

    • Example usage:

    char str[80] = "My-name-is-Bob"; 
    char s[2] = "-";  
    char *token = strtok(str, s);  
    
  • From stdio.h, sprintf(): Formats data and stores it as a string, offering flexibility in output formatting.

  • Often used functions from stdlib.h:

    • char str[10] = “12345”; int number = atoi(str)

    • char str[10] = “20.3361 is a double”; char *ptr; 

      double number = strtod(str)

Input and Output in C
  • Standard I/O Streams: C uses standard streams to manage input/output operations effectively:

    • stdout: The standard output stream generally directed to the terminal.

    • stderr: The standard error stream used for output error messages.

    • stdin: The standard input stream used for reading keyboard input.

  • Printing to the Terminal: To output data to the terminal, use the printf() function, which supports various formatting options:

    • Example usage:

    printf("%g \t %s \t %d\n", pi, "Hello", y); // Display float, string, and integer
    
  • Reading Input: The scanf() function is used to read formatted input values from the user, and can store those values in appropriately defined variables:

    • Example usage:
      c int x; scanf("%d", &x); // Reads an integer from the input

    • Single Character Input/Output: getchar() and putchar() can be utilized for handling single characters which resembles low-level I/O operations.

    • Example usage:
      c char ch = getchar(); // Accepts a single character input

File Input and Output in C
  • Files in C: File handling enables data persistence beyond the running program and can be manipulated through input/output streams. This functionality allows for effective storage and retrieval of data.

  • Working with Files: Utilize various functions from stdio.h to handle file operations:

    • fputc(): Writes a single character to the specified file.

    • fgets(): Reads a complete line of text from a file.

    • fgetc(): Reads a single character from a file.

  • Using Text Files: Writing and reading operations can be performed in the following manner:

    • To write to a file:

  fputc(char c, *file_pointer); // Writes character
  fputs(char *str, *file_pointer); // Writes a complete string
  • To read from a file:

  fgetc(*file_pointer); // Reads one character
  fgets(char *str, int size, *file_pointer); // Reads a line into a buffer
  • Check End of File: Utilize the feof(FILE *file_pointer); function to check the status of the file pointer, indicating whether the end of the file has been reached.

  • Formatting Input from a File: To read structured formatted input (much like scanf()), apply fscanf():

    • Example usage:

    fscanf(*file_pointer, variable_formatter, variable_name);  // Input as per specified format
    
  • Opening and Closing Files: A file pointer must first be declared and then a file can be opened using fopen(), which requires the path to the file and the mode (e.g., read or write):

    • File declaration:
      c FILE *file_pointer; // Declaring a file pointer

    • Open a file:
      c file_pointer = fopen("/home/input.txt", "r"); // Open for reading
      Returns NULL if the file cannot be opened for some reason.

    • Closing a file: Always close the file when done to free resources:
      c fclose(file_pointer); // Closes the file and releases memory