未知密钥的移位密码(Shift Cipher)解密程序问题排查与优化咨询
Hey there! Let's work through your shift cipher program issues—first fixing that bug in the top-5 selection module, then making your code cleaner without all those messy if statements. I'll keep things clear and beginner-friendly.
First: Fixing the Top-5 Selection Bug
Your current code has two critical issues causing wrong results (especially with inputs like "VDDDDDDDDC"):
1. You're Not Resetting Your Count Variables
In the second for(x=1;x<=25;x++) loop, your e,a,r,i,o counters aren't reset to 0 before each new shift. This means counts from previous shifts are added to the current one, leading to inflated, incorrect numbers.
2. Your Selection Logic Is Misaligned
Right now, you're tracking which shift has the most E, which has the most A, etc.—but this often leads to duplicate shifts (one shift might top multiple character counts) and ignores the total number of all high-frequency characters combined. We need to score each shift by the sum of E+A+R+I+O, then pick the top 5 highest scores.
Fixed Code for the Selection Module
Add this code after generating all 25 decrypted results:
// First, calculate total score for each shift int total_score[26] = {0}; // Index 0 unused, 1-25 map to shifts char target_chars[] = {'E', 'A', 'R', 'I', 'O'}; for(int x=1;x<=25;x++){ int score = 0; for(int f=0;store[x][f]!='\0';f++){ char c = store[x][f]; // Check if current character is one of our high-frequency targets for(int k=0;k<5;k++){ if(c == target_chars[k]){ score++; break; } } } total_score[x] = score; } // Now find the top 5 shifts by score int top_shifts[5]; int top_scores[5] = {-1, -1, -1, -1, -1}; // Initialize to low values for(int x=1;x<=25;x++){ for(int k=0;k<5;k++){ if(total_score[x] > top_scores[k]){ // Shift existing top entries down to make space for(int m=4;m>k;m--){ top_scores[m] = top_scores[m-1]; top_shifts[m] = top_shifts[m-1]; } top_scores[k] = total_score[x]; top_shifts[k] = x; break; } } } // Output the top 5 results printf("The program thinks the possible solutions are:\n"); for(int k=0;k<5;k++){ printf("%s\n", store[top_shifts[k]]); }
Second: Code Optimization (Ditch the Spaghetti ifs!)
Here are practical, beginner-friendly optimizations to clean up your code:
1. Use Arrays Instead of Individual Variables
Instead of separate e,a,r,i,o variables, use an array paired with a list of target characters. This makes it easy to add/remove high-frequency characters later without rewriting code:
// Define your target characters once char target_chars[] = {'E', 'A', 'R', 'I', 'O'}; int char_counts[5] = {0}; // Indexes match target_chars // Inside your counting loop: for(int f=0;store[x][f]!='\0';f++){ char c = store[x][f]; for(int k=0;k<5;k++){ if(c == target_chars[k]){ char_counts[k]++; break; } } } int total = char_counts[0] + char_counts[1] + char_counts[2] + char_counts[3] + char_counts[4];
2. Simplify Shift Logic with Modulo Arithmetic
Your current decryption code uses multiple if statements to handle wrap-around. Use modulo (%) to simplify this to one line (no more nested ifs!):
// For uppercase letters (your input is all caps) // Adjust the formula based on your shift direction (you said your first part works, so tweak if needed) if(isupper(code[f])){ store[x][f] = ((code[f] - 'A') + x) % 26 + 'A'; } // If decryption requires shifting backward (more standard for shift ciphers), use: // store[x][f] = ((code[f] - 'A') - x + 26) % 26 + 'A';
You'll need to include <ctype.h> for the isupper() function, which checks if a character is uppercase (way more readable than comparing ASCII values directly).
3. Use Structs for Organized Data
For more professional code, use a struct to store all data related to a single shift (shift number, decrypted text, score). Then use the standard library's qsort() function to sort shifts by score:
// Add this at the top of your file #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h> // Define a struct to hold all shift-related data typedef struct { int shift_num; int score; char decrypted_text[400]; } ShiftResult; // Comparison function for qsort (sorts from highest to lowest score) int compare_shifts(const void *a, const void *b){ ShiftResult *sa = (ShiftResult*)a; ShiftResult *sb = (ShiftResult*)b; return sb->score - sa->score; } // In main(), replace your store array with this: ShiftResult results[25]; // When generating decrypted text: for(int x=0;x<25;x++){ results[x].shift_num = x+1; // Keep shift numbering 1-25 // Generate decrypted text into results[x].decrypted_text // Calculate score and assign to results[x].score } // Sort all results by score qsort(results, 25, sizeof(ShiftResult), compare_shifts); // Output top 5 printf("Top 5 possible solutions:\n"); for(int k=0;k<5;k++){ printf("Shift %d: %s\n", results[k].shift_num, results[k].decrypted_text); }
4. Fix Input Handling
Your scanf("%[^'\n']s", code); has a format error—remove the trailing s so it's scanf("%[^\n]", code);. Also, add a getchar() after reading the ciphertext to clear the newline from the input buffer (prevents issues with subsequent scanf calls):
printf("Enter your code here:\n"); scanf("%[^\n]", code); getchar(); // Eat the leftover newline character
内容的提问来源于stack exchange,提问作者SirJames Longbottom

