#include<stdio.h>
const char *encrypt(char *str);
const char *decrypt(char *str1);
int main()
{
char str[100],str1[100];
//Encryption
printf("Enter String for encryption\n");
gets(str);
encrypt(str);
printf("%s after encryption is %s\n",str,encrypt(str));
//Encryption
printf("Enter String for decryption\n");
gets(str1);
decrypt(str1);
printf("%s after decryption is %s",str1,decrypt(str1));
return 0;
}
const char *encrypt(char *str)
{
char en[100];
int i=0;
for(;i<100;i )
{
en[i]=str[i] 1;
}
en[i]='\0';
return en;
}
const char *decrypt(char *str1)
{
char de[100];
int i=0;
for(;i<100;i )
{
de[i]=str1[i]-3;
}
de[i]='\0';
return de;
}
uj5u.com熱心網友回復:
您正在回傳一個指向自動變數的指標en,de這些變數存盤在堆疊中。這反過來意味著從函式回傳后encrypt,decrypt它們在記憶體中的位置可以被任何其他變數使用。
所以為了糾正這個,你需要定義en和de作為靜態。
const char *encrypt(char *str){
static char en[100];
int i=0;
for(;i<100;i ){
en[i]=str[i] 1;
}
en[i]='\0';
return en;
}
const char *decrypt(char *str1){
static char de[100];
int i=0;
for(;i<100;i ){
de[i]=str1[i]-3;
}
de[i]='\0';
return de;
}
雖然更合適和更安全的實施方式是:
#include<stdio.h>
void encrypt(char *str, char *encStr);
void decrypt(char *str1, char* decStr);
int main()
{
char str[100], encDecStr[100];
//Encryption
printf("Enter String for encryption\n");
scanf("%s", str);
encrypt(str, encDecStr);
printf("%s after encryption is %s\n",str,encDecStr);
//Decryption
printf("Enter String for decryption\n");
scanf("%s", str);
decrypt(str, encDecStr);
printf("%s after decryption is %s",str,encDecStr);
return 0;
}
void encrypt(char *str, char *encStr)
{
for(char *c = str; *c != '\0'; c )
{
*encStr = *c 1;
}
*encStr='\0';
}
void decrypt(char *str1, char* decStr)
{
for(char *c = str1; *c != '\0'; c )
{
*decStr = *c - 1;
}
*decStr ='\0';
}
注意:代碼沒有針對不同的用例進行全面測驗。
uj5u.com熱心網友回復:
您的代碼中有很多錯誤:
- 回傳具有本地存盤持續時間
的陣列:一旦退出函式,陣列的生命周期就會結束(即它不再存在),因此回傳的指標是懸空的,從中讀取是未定義的行為 - 你寫超出你的本地陣列的邊界:
en[i] = '\0'用i為100后的回圈是有效索引從0到99的范圍內,這又是不確定的行為出來。 - 您對加密 (1) 和解密 (3) 有不同的偏移量。
- 簡單地添加一個偏移量而不進一步檢查(或模運算)將為輸入和輸出字串產生不同的字符集(可能是你最不擔心的問題......)。
- 你總是對整個陣列進行編碼/解碼,這比實際需要的多。此外,終止空字符也被編碼,導致不同長度的輸入和輸出以及編碼字串末尾的垃圾。
- 使用 of
gets是危險的,因為它允許用戶寫超出輸入陣列的內容,從而導致未定義的行為。這就是為什么它實際上已從具有 C11 標準的 C 語言中洗掉的原因——它引入了一個安全的替代方案gets_s。另一種選擇(特別是對于 C11 之前的代碼)是fgets。
對于懸空指標問題,有幾種選擇:
- 使陣列靜態化(如前所述):
這種方法的缺點是該函式不再是執行緒安全的。此外,多次呼叫該函式會覆寫以前的結果,如果您尚未評估或復制它們,它們將丟失。 - 回傳動態分配的陣列,請參閱malloc 函式。
這伴隨著呼叫者忘記再次釋放分配的記憶體的風險,這將導致記憶體泄漏 - 就地更改輸入陣列:
缺點是如果之后還需要輸入,則必須將輸入復制到備份中。 - 讓呼叫者提供緩沖區。
最后一個選項是最靈活和最慣用的選項,所以我將專注于這個選項:
void caesar(char const* input, char* output, int offset)
{
int const NumChars = 'z' - 'a';
offset = offset % NumChars NumChars;
// ^ assures valid range, can still be negative
// ^ assures positive value, possibly
// out of range, but will be fixed later
for(;*input; input, output)
{
int c = *input - 'a';
// distance from character a
c = (c offset) % NumChars;
// ^ fixes too large offset
*output = 'a' c;
}
// as now iterating *until* null character found we now *need*
// to add it (in contrast to original version with whole array!)
*output = 0;
}
這個變體包含一個有趣的想法:讓呼叫者定義要應用的偏移量!無論偏移量有多大,模運算都能確保字符的有效范圍。偉大的事情是:如果用戶使用某個數字編碼,n則可以使用完全相同的函式再次解碼-n(這就是為什么我caesar根據它實作的演算法簡單地命名它)。請注意,這是未經測驗的代碼;如果您發現錯誤,請自行修復...
但是請注意,此代碼仍有兩個弱點:
- 它假定 ASCII 編碼或兼容——至少一個字母 a 到 z 在連續范圍內,a 是第一個字符,z 是最后一個字符。但是,并非所有編碼都是如此,請考慮(in-?)著名的 EBCDIC。
- 它假設所有輸入都在拉丁小寫字母的范圍內(從 a - z),它不考慮空格、數字、大寫字母、標點符號......您可能希望對所有這些或至少包括特殊處理你可能會用到的那些。
您可以通過
- 將所有字符轉換為大寫或小寫(
toupper((unsigned char)*input)- 假設大小寫無關緊要) - 在有效字符陣列 (
"ABC...XYZ012...89") 中搜索適當的索引,如果找到,則使用NumChars陣列長度進行如上編碼,否則(空格、標點符號)保持原樣。
在任何情況下,該函式將被呼叫如下:
char input[128]; // prefer powers of 2 for array lengths...
char en[sizeof(input)];
char de[sizeof(input)];
gets_s(input, sizeof(input));
caesar(input, en, 7);
// en contains encrypted string, could e.g. be printed now
caesar(en, de, -7);
// de contains decrypted string
// you could even encode/decode in place:
caesar(input, input, 7);
// just be aware that this will fail, though, for the case if input
// and output overlap and input starts before output, as then at
// some point already encoded values will be read as input again:
// caesar(input, input 1, 7) fails!!!
uj5u.com熱心網友回復:
您的代碼中存在一些問題:
對于初學者來說不是一個很大的問題,但你應該避免
gets函式。因為它不檢查輸入,它會導致緩沖區溢位和各種安全問題,請嘗試使用fgets。在加密和解密函式中,您將回傳位于函式堆疊中的陣列地址,請看:
const char *encrypt(char *str){ char en[100]; int i=0; for(;i<100;i ){ en[i]=str[i] 1; } en[i]='\0'; return en; }
在這里,由于en陣列是在函式內部宣告的,因此在回傳后嘗試讀取它時可能會得到垃圾字串。這里的解決方案是要么malloc在函式外宣告一個靜態陣列,要么對其進行初始化。
- 您通過將字串的值加 1 進行加密,并通過檢索 3 對其進行解密。我不知道這是不是你打算做的。
這是您的代碼的新版本,請嘗試檢查它是否適合您的需要:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
static char de[100] , en[100] ;
const char *decrypt(char *str1){
memset(de , 0 , 100) ;
int i=0;
for(;i<strlen(str1);i ){
de[i]=str1[i]-1;
}
de[i]='\0';
return (const char*) de;
}
const char* encrypt(char* str){
memset(en , 0 , 100) ;
int i=0;
for(;i<strlen(str);i ){
en[i]=str[i] 1;
}
en[i]='\0';
return (const char*) en;
}
int main(){
char str[100],str1[100];
//Encryption
printf("Enter String for encryption\n");
gets(str);
encrypt(str);
printf("%s after encryption is %s\n",str,encrypt(str));
//Encryption
printf("Enter String for decryption\n");
gets(str1);
decrypt(str1);
printf("%s after decryption is %s",str1,decrypt(str1));
return 0;
}
uj5u.com熱心網友回復:
您的代碼不處理字符“z”的特殊情況。因此
en[i]=str[i] 1;
導致字符“{”被寫入陣列en。要詳細了解為什么會發生這種情況,我建議您查看ASCII 表并查看字母表的整數值。
其次,你的意思是在那里輸入 -3 嗎?
de[i]=str1[i]-3;
如果您打算使用該decrypt()函式來解密您使用的字串,這將不起作用,encrypt()因為您在加密時給字符加 1,然后在解密時減去不同的數字,因此結果會出現亂碼。
我為你重寫了你的代碼,因為這是一個初學者程式,我做了盡可能少的改動,以便你能理解它。我強烈建議不要使用gets()……請看這里。
#include<stdio.h>
const char *encrypt(char *str);
const char *decrypt(char *str1);
int main()
{
char str[100],str1[100];
//Encryption
printf("Enter String for encryption\n");
gets(str); // DON'T USE GETS!!! USE fgets(str, 100, stdin);
encrypt(str);
printf("%s after encryption is %s\n", str, encrypt(str));
//Encryption
printf("Enter String for decryption\n");
gets(str1); // DON'T USE GETS!!! USE fgets(str, 100, stdin);
decrypt(str1);
printf("%s after decryption is %s", str1, decrypt(str1));
return 0;
}
const char *encrypt(char *str)
{
char en[100];
int i=0;
for(; i<100; i )
{
if (str[i] == 'z')
{
en[i] = 'a';
continue;
}
en[i] = str[i] 1;
}
en[i] = '\0';
return en;
}
const char *decrypt(char *str1)
{
char de[100];
int i=0;
for(; i<100; i )
{
if (str[i] == 'a')
{
en[i] = 'z';
continue;
}
de[i] = str1[i] - 1;
}
de[i] = '\0';
return de;
}
一些批評
- 就像我說的那樣,
gets()真的很糟糕...請參閱此處了解更多詳細資訊。雖然它對你來說可能太復雜了......更好的選擇是fgets!
fgets(str, num, stdin)
從控制臺獲取用戶輸入,然后將其存盤在 array 中str,該array必須足夠大以存盤至少num字符。stdin如果您不知道這意味著什么,請不要擔心。但是一定要在使用時總是寫它fgets作為替代gets
- 就像其他人已經發布的一樣,盡管使用了更多技術術語,但在函式中宣告一個陣列然后回傳該陣列是一個壞主意。你知道當
return陳述句被命中時函式結束,此時函式內宣告的所有變數都將被銷毀。
這并不一定意味著您無法讀取其中的資料,但它變成了一個概率游戲,其中在函式退出后和該陣列中的資料被破壞之前,該陣列有極小的機會被破壞讀。這在技術上是未定義的行為。
我希望你知道指標。您可以直接修改作為引數傳遞的陣列,然后回傳該陣列,從而避免在其生命周期之外訪問陣列。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/341605.html
下一篇:在2個div之間連接一條線
