使用strtok与fgets时触发Segmentation Fault问题求助
Let's break down why your process_stream function is hitting a segmentation fault and fix the logic errors to get your word counter working correctly.
Critical Bugs in Your Original Code
You discard the first token immediately
You callstrtok(buffer, " \n")to grab the first token, but then immediately overwrite it withtoken = strtok(NULL, " \n")before processing it. When a line only has one word, this setstokentoNULL, and passing aNULLpointer tostrcmp(which expects valid C strings) triggers a segmentation fault.Array index out-of-bounds
Your loop condition for checking entries isi < entry_count+1, but yourentriesarray only hasentry_countelements (indices 0 toentry_count-1). Accessingentries[entry_count]reads memory outside the array, leading to undefined behavior (often a segfault).Unsafe newline removal
You directly setbuffer[strlen(buffer)-1]='\0'without verifying that character is actually a newline. Iffgetsreturns an empty line or hits EOF right away,strlen(buffer)could be 0, makingbuffer[-1]an invalid memory access.No handling for the termination character '.'
Your requirement states input ends with., but your code keeps reading untilfgetsfails (EOF), so it won't stop when the user enters the termination character.
Fixed Version of process_stream
#include <string.h> #include <stdio.h> // Assuming your WordCountEntry structure looks like this: typedef struct { char* word; int counter; } WordCountEntry; int process_stream(WordCountEntry entries[], int entry_count) { short line_count = 0; char buffer[30]; while (fgets(buffer, sizeof(buffer), stdin)) { line_count++; // Safely remove trailing newline if present size_t buf_len = strlen(buffer); if (buf_len > 0 && buffer[buf_len - 1] == '\n') { buffer[buf_len - 1] = '\0'; } // Stop processing when termination character is entered if (strcmp(buffer, ".") == 0) { break; } char* token = strtok(buffer, " \n"); while (token != NULL) { // Check if current token matches any target word for (int i = 0; i < entry_count; i++) { if (strcmp(entries[i].word, token) == 0) { entries[i].counter++; break; // Exit early once match is found } } // Get the next token token = strtok(NULL, " \n"); } } return line_count; }
Key Fixes Explained
- Process the first token correctly: We now capture the initial token, process it, then fetch the next one in the loop—no more skipping words or passing invalid pointers to
strcmp. - Valid array bounds: The entry loop uses
i < entry_count, ensuring we only access valid indices in theentriesarray. - Safe newline handling: We check if the last character is a newline before modifying it, avoiding invalid memory access for empty lines.
- Termination check: We compare the input line to
.and break the loop immediately, stopping input as required. - Early exit in entry loop: Once a matching word is found, we stop checking other entries to save unnecessary iterations.
Testing this with your example input (cat cat nap .) will return the expected result: cat: 2 nap: 1 dog: 0.
内容的提问来源于stack exchange,提问作者flutterbug98

