循环 ASCII 字符并解密消息
Looping ASCII characters and decrypting the message
老师给我布置了作业:-
You are given a string (of at most 100 characters) consisting of
lowercase characters, terminated with a # symbol. The string is the
"encrypted" form of an original string as follows - each character in
the original string has been shifted by a fixed integer n (where 1<= n
<= 25).
Assuming that a is the 0th character in the alphabet, ..., and z is
the 25th character of the alphabet, in the encrypted version, we have:
'a' becomes the nth character in the alphabet, 'b' becomes the (n+1)%26th
character in the alphabet, ...
and so on.
n is not known to you. You only know that the first character
represents 't'. From this information, you have to output the original
string.
这是我的代码:-
#include <stdio.h>
#include <stdlib.h>
int main()
{
char array[100]; //string will be stored here.
char a;
int i = 0; //initializer
scanf("%c", &a);
int counter = 0; // to count the size of the string
while(a != '#')
{
array[i] = a;
i++;
counter++;
scanf("%c", &a);
}
a = 't';
int temp = a - array[0]; //To get the offset of the encrypted message.
for(i = 0; i < counter; i++)
{
if((array[i] + temp) >= 'a' && (array[i] + temp) <= 'z')
{
array[i] = array[i] + temp; //Applying the offset to the encrypted message to get the true message.
}
else if((array[i] + temp) < 'a')
{
array[i] = 'z' - (temp - (array[i] - 'a')); //If offset is large and it falls below ASCII charater number 'a' then loop back to 'z'.
}
else
{
array[i] = 'a' + (temp - ('z' - array[i])); //If offset is large and it falls above ASCII charater number 'z' then loop back to 'a'.
}
}
puts(array);
return 0;
}
现在我所应用的逻辑肯定是错误的。我所有的测试用例都失败了。我怀疑问题出在以下代码片段中:-
for(i = 0; i < counter; i++)
{
if((array[i] + temp) >= 'a' && (array[i] + temp) <= 'z')
{
array[i] = array[i] + temp; //Applying the offset to the encrypted message to get the true message.
}
else if((array[i] + temp) < 'a')
{
array[i] = 'z' - (temp - (array[i] - 'a')); //If offset is large and it falls below ASCII charater number 'a' then loop back to 'z'.
}
else
{
array[i] = 'a' + (temp - ('z' - array[i])); //If offset is large and it falls above ASCII charater number 'z' then loop back to 'a'.
}
}
这个简单的问题我做不出来。请帮忙。
部分测试用例如下:-
#include <stdio.h>
#include <stdlib.h>
int main()
{
char array[100]; //string will be stored here.
int counter = 0; // to count the size of the string
scanf("%s", array);
while(array[counter] != '#')
counter++;
int offset = 't' - array[0]; //To get the offset of the encrypted message.
if (offset < 0)
offset = 26 + offset;
for(int i = 0; i < counter; i++)
array[i] = ((array[i] - 'a' + offset) % 26) + 'a';
array[counter] = '[=10=]'; // Removing the # at the end
puts(array);
return 0;
}
第一,您不是以 null 终止您的字符串,因此有时会在末尾出现额外的字符。我通过要求一个字符串而不是连续的几个字符来修复它,我个人觉得这更简单。然后它会自动在您的数组末尾添加一个 [=11=]
,但它不会逐个字符地添加。话虽这么说,你的也可以工作,但前提是你在末尾添加一个 array[counter] = '[=12=]'
以 null 终止它。
'a' becomes the nth character in the alphabet, 'b' becomes the (n+1)%26th character in the alphabet, ...
您的实施过于复杂。这里只需要一行 array[i] = ((array[i] - 'a' + offset) % 26) + 'a';
。
为了分解它,我们通过 array[i] - 'a'
得到字母在字母表中的索引;我们添加偏移量,我们 运行 模 26(字母表中的字符数)以获得新字母的索引并说明我们可以获得高于 26 的结果(在这种情况下我们想换行:29 表示字母表中的第三个字母,因为 29 - 26 = 3)。我们加回 'a'
以获得实际字符而不是索引,我们得到了正确的字母。
此外,您的代码目前容易受到缓冲区溢出的影响!您不应该太在意学校项目,但这是一个巨大的安全漏洞,您可能有兴趣了解更多信息。如果您的输入字符串中没有 #,您也很容易出现分段错误。
我有意没有对您的代码进行太多改进,因为它是一个学校项目,但我知道变量 counter
完全没有必要,您可以重新设计代码以避免使用它。您可能需要考虑如何解决这个问题。
以下是按所需偏移量简单地内联替换字符。我没有优化替换语句,因为我觉得这样更易读。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char buf[101]; // one character extra for max input case
char *p; // iteration pointer
int d; // for "delta"
scanf("%s", buf);
d = *buf - 't'; // record the "rot13" encryption offset
for (p = buf; *p != '#'; p++)
*p = (((*p - 'a') + 26 - d) % 26) + 'a';
*p = '[=10=]';
printf("%s\n", buf);
return 0;
}
记住:这是 C,始终注意无效输入。
通过一些基本的错误检查:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char buf[101]; // one character extra for max input case
char *p; // iteration pointer
int d; // for "delta"
switch (scanf("%100[a-z#]", buf)) {
case EOF:
fprintf(stderr, "empty file\n");
return 1;
case 0:
fprintf(stderr, "invalid input\n");
return 1;
}
d = *buf - 't'; // record the "rot13" encryption offset
for (p = buf; *p != '#' && *p != '[=11=]'; p++) {
*p = (((*p - 'a') + 26 - d) % 26) + 'a';
}
if (*p != '#') {
fprintf(stderr, "missing termination character\n");
return 1; // omit this line if you want best-effort output anyway
}
*p = '[=11=]';
printf("%s\n", buf);
return 0;
}
这应该处理太短或太长的输入、包含无效字符、缺少 # 字符或只是一个空文件。
老师给我布置了作业:-
You are given a string (of at most 100 characters) consisting of lowercase characters, terminated with a # symbol. The string is the "encrypted" form of an original string as follows - each character in the original string has been shifted by a fixed integer n (where 1<= n <= 25).
Assuming that a is the 0th character in the alphabet, ..., and z is the 25th character of the alphabet, in the encrypted version, we have:
'a' becomes the nth character in the alphabet, 'b' becomes the (n+1)%26th character in the alphabet, ...
and so on.
n is not known to you. You only know that the first character represents 't'. From this information, you have to output the original string.
这是我的代码:-
#include <stdio.h>
#include <stdlib.h>
int main()
{
char array[100]; //string will be stored here.
char a;
int i = 0; //initializer
scanf("%c", &a);
int counter = 0; // to count the size of the string
while(a != '#')
{
array[i] = a;
i++;
counter++;
scanf("%c", &a);
}
a = 't';
int temp = a - array[0]; //To get the offset of the encrypted message.
for(i = 0; i < counter; i++)
{
if((array[i] + temp) >= 'a' && (array[i] + temp) <= 'z')
{
array[i] = array[i] + temp; //Applying the offset to the encrypted message to get the true message.
}
else if((array[i] + temp) < 'a')
{
array[i] = 'z' - (temp - (array[i] - 'a')); //If offset is large and it falls below ASCII charater number 'a' then loop back to 'z'.
}
else
{
array[i] = 'a' + (temp - ('z' - array[i])); //If offset is large and it falls above ASCII charater number 'z' then loop back to 'a'.
}
}
puts(array);
return 0;
}
现在我所应用的逻辑肯定是错误的。我所有的测试用例都失败了。我怀疑问题出在以下代码片段中:-
for(i = 0; i < counter; i++)
{
if((array[i] + temp) >= 'a' && (array[i] + temp) <= 'z')
{
array[i] = array[i] + temp; //Applying the offset to the encrypted message to get the true message.
}
else if((array[i] + temp) < 'a')
{
array[i] = 'z' - (temp - (array[i] - 'a')); //If offset is large and it falls below ASCII charater number 'a' then loop back to 'z'.
}
else
{
array[i] = 'a' + (temp - ('z' - array[i])); //If offset is large and it falls above ASCII charater number 'z' then loop back to 'a'.
}
}
这个简单的问题我做不出来。请帮忙。
部分测试用例如下:-
#include <stdio.h>
#include <stdlib.h>
int main()
{
char array[100]; //string will be stored here.
int counter = 0; // to count the size of the string
scanf("%s", array);
while(array[counter] != '#')
counter++;
int offset = 't' - array[0]; //To get the offset of the encrypted message.
if (offset < 0)
offset = 26 + offset;
for(int i = 0; i < counter; i++)
array[i] = ((array[i] - 'a' + offset) % 26) + 'a';
array[counter] = '[=10=]'; // Removing the # at the end
puts(array);
return 0;
}
第一,您不是以 null 终止您的字符串,因此有时会在末尾出现额外的字符。我通过要求一个字符串而不是连续的几个字符来修复它,我个人觉得这更简单。然后它会自动在您的数组末尾添加一个 [=11=]
,但它不会逐个字符地添加。话虽这么说,你的也可以工作,但前提是你在末尾添加一个 array[counter] = '[=12=]'
以 null 终止它。
'a' becomes the nth character in the alphabet, 'b' becomes the (n+1)%26th character in the alphabet, ...
您的实施过于复杂。这里只需要一行 array[i] = ((array[i] - 'a' + offset) % 26) + 'a';
。
为了分解它,我们通过 array[i] - 'a'
得到字母在字母表中的索引;我们添加偏移量,我们 运行 模 26(字母表中的字符数)以获得新字母的索引并说明我们可以获得高于 26 的结果(在这种情况下我们想换行:29 表示字母表中的第三个字母,因为 29 - 26 = 3)。我们加回 'a'
以获得实际字符而不是索引,我们得到了正确的字母。
此外,您的代码目前容易受到缓冲区溢出的影响!您不应该太在意学校项目,但这是一个巨大的安全漏洞,您可能有兴趣了解更多信息。如果您的输入字符串中没有 #,您也很容易出现分段错误。
我有意没有对您的代码进行太多改进,因为它是一个学校项目,但我知道变量 counter
完全没有必要,您可以重新设计代码以避免使用它。您可能需要考虑如何解决这个问题。
以下是按所需偏移量简单地内联替换字符。我没有优化替换语句,因为我觉得这样更易读。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char buf[101]; // one character extra for max input case
char *p; // iteration pointer
int d; // for "delta"
scanf("%s", buf);
d = *buf - 't'; // record the "rot13" encryption offset
for (p = buf; *p != '#'; p++)
*p = (((*p - 'a') + 26 - d) % 26) + 'a';
*p = '[=10=]';
printf("%s\n", buf);
return 0;
}
记住:这是 C,始终注意无效输入。 通过一些基本的错误检查:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char buf[101]; // one character extra for max input case
char *p; // iteration pointer
int d; // for "delta"
switch (scanf("%100[a-z#]", buf)) {
case EOF:
fprintf(stderr, "empty file\n");
return 1;
case 0:
fprintf(stderr, "invalid input\n");
return 1;
}
d = *buf - 't'; // record the "rot13" encryption offset
for (p = buf; *p != '#' && *p != '[=11=]'; p++) {
*p = (((*p - 'a') + 26 - d) % 26) + 'a';
}
if (*p != '#') {
fprintf(stderr, "missing termination character\n");
return 1; // omit this line if you want best-effort output anyway
}
*p = '[=11=]';
printf("%s\n", buf);
return 0;
}
这应该处理太短或太长的输入、包含无效字符、缺少 # 字符或只是一个空文件。