fscanf运行初期正常,后续停止工作的技术问题求助
fscanf Stopping Issue Let's walk through the key problems in your code that are causing fscanf to stop working after a few lines, along with actionable fixes:
Key Root Causes
1. Misuse of while(!feof(fp))
This is one of the most common C file I/O pitfalls. The feof() function only returns true after you've attempted to read past the end of the file. That means your loop will run one extra time when the file is already exhausted, leading to invalid reads and unexpected behavior (like your program hanging or stopping).
2. Mixed File I/O Functions Causing Pointer Chaos
You're mixing fgetc() (character-level reading) with fscanf() (formatted reading), plus manual fseek() calls. These functions interact with the same file pointer and input buffer, but their behavior doesn't always play nicely together:
fscanf()skips leading whitespace by default, which can clash with your manualfgetc()checks for newlines/spaces.- Your
fseek(fp, -1, SEEK_CUR)after reading a character might not account for line ending differences (e.g.,\r\non Windows vs\non Unix), leaving the pointer in an unexpected position for subsequentfscanfcalls.
3. Potential Memory/Type Issues with fscanf Calls
Looking at fscanf(fp,"%s",&mne):
- If
mneis a character array (likechar mne[20];), you should passmnedirectly (not&mne) since array names decay to pointers. Using&mnepasses a pointer to the array itself, which is a type mismatch and can cause memory corruption. - If
mneis an uninitialized pointer, this line will write to random memory, leading to crashes or unpredictable behavior.
4. No Error Checking for fscanf
You never check the return value of fscanf(). This function returns the number of items successfully read. If it returns less than expected (e.g., 0 or EOF), it means the read failed—but your code keeps executing as if nothing went wrong, leading to invalid data and program halts.
Fixes & Actionable Steps
1. Replace the feof Loop Condition
Instead of relying on feof, base your loop on the success of your read operations. For example:
int cc; while ((cc = fgetc(fp)) != EOF) { fputc(cc, o); putchar(cc); if (cc == '\n') { // Your newline handling code here } }
This ensures the loop stops as soon as we hit the end of the file.
2. Avoid Mixing I/O Functions (or Sync Properly)
Stick to one style of reading if possible. If you need to mix them:
- Use
fflush(fp)before switching between functions (note:fflushon input streams is undefined in standard C, so this works best on systems like Linux that support it, or switch to binary mode withfopen(..., "rb")). - Alternatively, rewrite your newline/space checks using
fscanfinstead offgetc. For example, to check for a space after a newline:
// Skip any leading whitespace (including newlines) fscanf(fp, " "); // Then check if the next character is a space int next_char = fgetc(fp); if (next_char == ' ') { fseek(fp, -1, SEEK_CUR); // Put it back for fscanf to read // Proceed with your mne read } else if (next_char != EOF) { fseek(fp, -1, SEEK_CUR); }
3. Fix fscanf Argument Types
Ensure mne and var are properly sized character arrays, and pass them correctly to fscanf:
char mne[32]; // Size appropriately for your mnemonics char var[64]; // Size for variables // Correct call: pass the array name (pointer to first element) if (fscanf(fp, "%s", mne) != 1) { // Handle read failure: break loop, log error, etc. break; }
4. Add Error Checking for All I/O Operations
Always validate the return values of fgetc, fscanf, fseek, etc.:
int aa = fgetc(fp); if (aa == EOF) { break; // End of file, exit loop } if (fseek(fp, -1, SEEK_CUR) != 0) { // Handle seek error (e.g., invalid position) perror("fseek failed"); break; } // Check fscanf success if (fscanf(fp, "%s", mne) != 1) { perror("Failed to read mnemonic"); break; }
5. Handle Line Endings Consistently
If you're working on Windows, line endings are \r\n (two characters). When you read \n with fgetc, the previous character is \r, so your fseek back 1 will point to \r, which fscanf will treat as whitespace. To avoid this, consider reading lines with fgets first, then processing each line with sscanf—this isolates line handling and avoids pointer confusion.
内容的提问来源于stack exchange,提问作者Ramyanee Kashyap

