咨询:如何实现C语言中的字符串提取与插入函数
Alright, let's tackle this problem step by step. I'll walk you through implementing the two functions you need, following the exact rules you laid out for reading strings from a file stream into your My_string type.
First, let's define a common My_string structure to work with (since you didn't provide one, this is a standard implementation that aligns with your requirements):
#include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <string.h> // Core My_string structure typedef struct { char* data; // Buffer holding the string (null-terminated) size_t length; // Current number of characters (excluding null terminator) size_t capacity; // Total allocated space (includes room for null terminator) } My_string; // Handle type for My_string objects typedef My_string* My_string_handle;
Now we'll build two functions: a helper to manage dynamic capacity growth, and the main function to handle the stream reading logic with your specified rules.
1. Helper Function: my_string_reserve (Capacity Growth)
This function ensures your My_string has enough space to add new characters, growing the buffer as needed. It's critical for fulfilling the "capacity grows on demand" requirement.
// Precondition: hMy_string is a valid My_string handle // Postcondition: hMy_string's capacity is at least new_capacity; existing data is preserved int my_string_reserve(My_string_handle hMy_string, size_t new_capacity) { if (!hMy_string) return -1; // Fail if handle is invalid // No need to resize if we already have enough space if (new_capacity <= hMy_string->capacity) { return 0; } // Reallocate buffer (add 1 extra byte for the null terminator) char* new_data = realloc(hMy_string->data, new_capacity + 1); if (!new_data) { perror("Failed to expand string buffer"); return -1; } hMy_string->data = new_data; hMy_string->capacity = new_capacity; return 0; }
2. Main Function: my_string_read_next_from_stream
This function implements the core logic: skipping leading whitespace, reading characters until a stop condition, and ensuring the string grows as needed.
// Precondition: hMy_string is a valid My_string handle; fp is a valid open file stream // Postcondition: hMy_string contains the next string from fp (per rules), or is empty if EOF is reached int my_string_read_next_from_stream(My_string_handle hMy_string, FILE* fp) { if (!hMy_string || !fp) return -1; // Reset the string to empty before starting a new read hMy_string->length = 0; if (hMy_string->data) { hMy_string->data[0] = '\0'; } // Step 1: Skip all leading whitespace characters int c; while ((c = fgetc(fp)) != EOF && isspace(c)) { // Just consume whitespace—do nothing else } // If we hit EOF after skipping whitespace, return early if (c == EOF) { return 0; } // Initialize capacity if the string was empty if (hMy_string->capacity == 0) { if (my_string_reserve(hMy_string, 16) != 0) { // Start with 16-char buffer (adjustable) return -1; } } // Step 2: Read characters until stop condition (whitespace or EOF) do { // Expand capacity if we're running out of space (double capacity each time for efficiency) if (hMy_string->length >= hMy_string->capacity) { if (my_string_reserve(hMy_string, hMy_string->capacity * 2) != 0) { return -1; } } // Add the current character to the string hMy_string->data[hMy_string->length++] = (char)c; hMy_string->data[hMy_string->length] = '\0'; // Maintain null termination // Read the next character c = fgetc(fp); } while (c != EOF && !isspace(c)); // Put the stop character back into the stream (optional, useful for sequential reads) if (c != EOF) { ungetc(c, fp); } return 0; }
Key Details to Note:
- Leading Whitespace: Uses
isspace()from<ctype.h>to skip all standard whitespace (spaces, tabs, newlines, etc.) before reading the actual string content. - Capacity Growth: We double the buffer size each time we need more space—this gives amortized constant time complexity for each character added, making the function efficient even for large strings.
- Stop Condition: Currently stops at whitespace or EOF. If you need a different stop condition (like a specific delimiter, e.g., comma or semicolon), just modify the
whileloop condition (e.g.,while (c != EOF && c != ',')). - Null Termination: The string is always kept null-terminated, so it works seamlessly with standard C string functions like
printf()orstrlen().
Example Usage:
int main() { My_string str = {NULL, 0, 0}; My_string_handle hStr = &str; FILE* fp = fopen("input.txt", "r"); if (!fp) { perror("Failed to open input file"); return 1; } // Read strings from the file until EOF while (my_string_read_next_from_stream(hStr, fp) == 0 && hStr->length > 0) { printf("Read string: '%s'\n", hStr->data); } // Cleanup resources free(str.data); fclose(fp); return 0; }
内容的提问来源于stack exchange,提问作者Billy

