我在Ubuntu中使用GCC在ANSI C中创建一个小应用程序。应用程序应该通过在数组中交换两个字母来解密消息。
我的主要课程:
#include "CipherCode.h"
char cipherText[] = "PUCXHTULUL, XW AELW, JUAJ TXJ FOCTXWU EH XW OCCQLPOWCU RXAT ATU DUZ GXJA. RTUW ATU FUJJOBU XJ LUCUXIUP, TU JUAJ ATU DUZ RTUUGJ AQ ATU";
int main(void) {
char ch = 0;
char chLetter, chReplacement;
char *pLetter = chLetter;
char *pReplacement = chReplacement;
int cipherStats[ALPHABET_SIZE] = { 0 };
char chAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int *pCipherStats = cipherStats;
char *pCipherText = cipherText;
char *pAlphabet = chAlphabet;
do {
DisplayCipherText(pCipherText);
GetFrequency(pCipherText, pCipherStats);
DisplayCipherStats(pCipherStats, pAlphabet, 26);
chLetter = GetLetter("Enter character to substitute:");
chReplacement = GetLetter("Swap this with character:");
Decipher(pCipherText, pReplacement);
printf("%s", "\nPress 'n' to exit or any other key to continue...\n"); /* prompt to continue looping */
} while ((ch = getchar()) != 'n'); /* loop unless user enters char 'n' */
return EXIT_SUCCESS;
}
我的CipherCode.c文件:
#include "CipherCode.h"
char GetLetter(const char* prompt) {
char ch = '\0';
do {
printf( "%s", prompt );
fflush(stdout);
ch = toupper(getchar());
printf( "%c\n", ch );
} while (!isalpha(ch));
return ch;
}
int GetFrequency(const char *pCipherText, int *pCipherStats) {
printf("Frequency analysis:\n");
for (; *pCipherText != '\0'; pCipherText++) {
if (isalpha(*pCipherText)) {
int index = toupper(*pCipherText) - 'A';
if ( index >= 0 && index < 26 ) {
pCipherStats[index]++;
}
else {
fprintf(stderr, "%c gives invalid index: %d\n", *pCipherText, index);
}
}
}
return EXIT_SUCCESS;
}
void DisplayCipherText(char *pCipherText) {
for (; *pCipherText != '\0'; pCipherText++) {
printf("%c", *pCipherText);
}
printf("\n\n");
}
void DisplayCipherStats(int *pCipherStats, char *pAlphabet, int size) {
int i;
for (i = 0; i < size; i++) { /*for each letter in the alphabet*/
printf("%1c:%-4d", *pAlphabet++, *pCipherStats++); /*print frequency information*/
}
printf("\n\n");
}
void Decipher(char *pCipherText, char *pReplacement) {
for (; *pCipherText != '\0'; pCipherText++) {
if (*pCipherText == *pReplacement) {
SortChar(pCipherText, pReplacement);
}
}
}
void BubbleSort(int *pInt, char *pCh) {
int i, j;
for (i = ALPHABET_SIZE-1; i >= 0; i--) {
for (j = 0; j < i; j++) {
if (*(pInt+j) < *(pInt+j+1)) {
SortChar(pCh+j, pCh+j+1);
SortInt(pInt+j, pInt+j+1);
}
}
}
}
void SortInt(int *pIntA, int *pIntB) {
int tempInt; /*temp variable*/
tempInt = *pIntA; /*store old value before it is overwritten*/
*pIntA = *pIntB; /*overwrite old value*/
*pIntB = tempInt; /*complete the swap*/
}
void SortChar(char *pChA, char *pChB) {
char tempCh; /*temp variable*/
tempCh = *pChA; /*store old value before it is overwritten*/
*pChA = *pChB; /*overwrite old value*/
*pChB = tempCh; /*complete the swap*/
}
我的标题文件:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define ALPHABET_SIZE 26
/*
* global variables
*/
extern char cipherText[];
/*
* function prototypes
*/
char GetLetter(const char*);
int GetFrequency(const char*, int*);
void DisplayCipherText(char*);
void DisplayCipherStats(int*, char*, int);
void Decipher(char*, char*);
void BubbleSort(int*, char*);
void SortInt(int*, int*);
void SortChar(char*, char*);
我希望程序采用chLetter并用chReplacement替换cipherText中出现的所有chLetter。对于do循环的每次迭代,我想显示cipherText,然后分析cipherText中字母的频率,然后显示频率,然后请求chLetter,然后请求chReplacement,最后用chReplacement交换chLetter。
程序必须使用指针来引用数组的内容。我还必须使用我的排序功能来破译文本。
非常感谢任何帮助。感谢。
答案 0 :(得分:1)
char GetLetter(char chLetter) {
char *pLetter = scanf("Enter character to substitute: %c", &chLetter);
return *pLetter;
}
^指定scanf格式字符串的错误方式,格式字符串用于 匹配来自缓冲区的输入而不是用于显示提示。 scanf返回数字 它从缓冲区找到的参数不是char *
而是做这样的事情:
char GetLetter()
{
printf( "%s", "Enter character to substitute:");
fflush(stdout);
return getchar();
}
或为了使其更灵活,请在参数中指定提示符:
char GetLetter(const char* prompt)
{
printf( "%s", prompt );
fflush(stdout);
return getchar();
}
然后你可以用
来调用它char chReplace = GetLetter("Enter character to substitute:");
char chWith = GetLetter("Swap this with character:");
使用此功能
int GetFrequency(char *pCipherText, int *pCipherStats) {
printf("Frequency analysis:\n");
for (; *pCipherText != '\0'; pCipherText++) { /*check if at the end of the array*/
char ch = *pCipherText; /*store current letter as a char*/
if (isalpha(ch)) pCipherStats[ch - 'A']++; /*if character is a letter, store ascii value in array and increment array*/
}
^你似乎假设所有输入字母都是大写字母,也许你应该通过首先将字符转换为大写来确保它。在编程时总是很好,更安全而不是遗憾。通常,通过将参数用作临时变量来修改参数是不好的方式,当函数更复杂时,它会使代码混乱。而是使用本地var例如
int GetFrequency(const char *pCipherText, int *pCipherStats)
{
char* p = pCiperText;
printf("Frequency analysis:\n");
for (; *p != '\0'; ++p)
{
if (isalpha(*p))
{
int index = toupper(*p) - 'A';
if ( index >= 0 && index < 26 )
{
pCipherStats[index]++;
}
else
{
fprintf(stderr, "%c gives invalid index: %d\n", *p, index );
}
}
}
...
说,你可以使GetLetter功能更加强大:
char GetLetter(const char* prompt)
{
char ch = '\0';
do
{
printf( "%s", prompt );
fflush(stdout);
ch = toupper(getchar());
printf( "%c\n", ch );
}
while ( !isalpha(ch) );
return ch;
}
答案 1 :(得分:0)
GetLetter()
和GetReplacement()
有多个问题。
第一行将其定义为采用char
并返回char
的函数。
这实际上没问题,但是因为你没有使用传递的值
chLetter
,您根本不需要传递它。
char GetLetter(char chLetter) {
此行不执行您认为的操作。它将不使用该文本
"Enter the character ..."
作为提示,但尝试匹配输入。这个
意味着scanf
不会失败的唯一方法是用户键入
整个字符串,这显然不是你想要的。
scanf
也不返回char *
,但是int
,表示有多少
输入项已成功匹配,或EOF
以防输入结束
在匹配第一个项目之前达到或发生错误。分配int
指针的值通常没有意义
char *pLetter = scanf("Enter character to substitute: %c", &chLetter);
在这里,您尝试取消引用未指向有效的指针 记忆位置。
return *pLetter;
}
一个简单的实现可能是:
/** Prompt for inputting a single character
*
* Reads the first character and then discards the rest of the line.
* The `text` parameter is the prompt string.
* Returns an int so we can indicate EOF, which isn't representable by char
*/
int prompt_char(const char *text) {
int c, tmp;
printf("%s: ", text);
c = getchar();
do {
tmp = getchar();
} while (tmp != '\n' && tmp != EOF);
return c;
}
您可以在main()
中使用这样的内容:
do {
...
chLetter = prompt_char("Enter character to substitute");
chReplacement = prompt_char("Swap this with character");
if (chLetter == EOF || chReplacement == EOF) {
// do something, e.g. break from the loop or exit the program
}
...
} while (...)