- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
它没有显示我想要它显示的是输入文本的加密版本,而是符号,正如我猜的那样,看起来有点像“?”作为终端中的输出出现。谁能帮我找出我遗漏或做错了什么?
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(int argc, string argv[])
{
if (argc == 2)
{
string ptext = get_string("plaintext: ");
int key = (int) argv[1];
printf("ciphertext: ");
for (int i = 0, n = strlen(ptext); i < n; i++)
{
printf("%c", (( ptext[i] + key ) % 26);
}
printf("\n");
}
else
{
printf("Invalid input. \n");
}
}
我希望“hello”的输出是“ifmmp”,但事实并非如此。
最佳答案
这段代码是错误的:
int key = (int) argv[1];
argv
是string
的数组,在 CS50 中只不过是一个混淆的char *
指针。
根据5.1.2.2.1 Program startup of the C standard:
The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent; ...
因此argv[1]
是一个char *
指针值,然后您将其分配给int
值。这是获取一些内存的地址(比如argv[1]
中的值是0xFF0403220020480C
)并试图将其填充到int
变量key
的可能 4 个字节中(在这种情况下将被分配截断值0x0020480C
.)
这不是您想要做的。
(IMO,你这里的问题是一个完美的例子,说明了为什么 CS50 将char *
与string
类型混淆是一个非常糟糕的主意。如果不理解指针和NUL
终止的char
字符串通过char *
指针访问,而string
所做的混淆使得这更难。)
如果你想要convert a string to a numeric value,你可能想要something like strtol()
(never use atoi()
as it has no error checking and its use can invoke undefined behavior):
char firstCharNotConverted;
// set errno to zero as strtol()
errno = 0;
long key = strtol( argv[ 1 ], &firstCharNotConverted, 0 );
// if errno is now non-zero, the call to strtol() failed (per Linux man page)
// need to examine key and the contents of firstCharNotConverted
// to figure out why
if ( errno != 0 )
{
...
}
省略了适当的 header ,作为尝试使用此代码的任何人的练习 ;-)
请注意,我将long
用作key
,因为如果将返回值强制转换为strtol()
,则无法对int
进行完整且正确的错误检查。
错误检查strtol()
可能有点复杂,因为返回的值(并在上面的代码中分配给key
)可以是任何值,并且没有可能的值不是long
的合法值strtol()
”可以返回以指示错误,因此为了进行正确的错误检查,您需要检查errno
和firstCharNotConverted
的值,以正确确定是否确实发生了错误。 Linux man page声明:
Since strtol() can legitimately return 0, LONG_MAX, or LONG_MIN (LLONG_MAX or LLONG_MIN for strtoll()) on both success and failure, the calling program should set errno to 0 before the call, and then determine if an error occurred by checking whether errno has a nonzero value after the call.
在调用strtol()
之后,您需要检查key
是否为LONG_MIN
,或LONG_MAX
且errno
等于ERANGE
是否为下溢或上溢,或者key
是否为0
”您需要检查firstCharNotConverted
的内容以确定转换失败的原因。请注意,如果key
为零且firstCharNotConverted
不等于argv[ 1 ]
,则输入字符串已从零正确转换。
您的 Ceaser 密码实现也是错误的:
for (int i = 0, n = strlen(ptext); i < n; i++)
{
printf("%c", (( ptext[i] + key ) % 26);
}
printf("\n");
将只打印出值从0
到25
的字符——它们不是 ASCII 字符集中的字母。
这里已经发布了很多 Ceaser 密码问题,所以我不打算编写代码。一个示例问题请参见Caesar's Cipher Code。
关于CS50 Pset2-凯撒密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56272562/
我刚刚开始学习 C 语言类(class),并且遇到了命令行参数的问题。分配是这样的(还有更多,但这是开头有关命令行参数的部分): - 你的程序必须接受一个命令行参数,一个非负整数。 - 如果您的程序在
我需要检查命令行参数中是否有非数字字符。例如: ./problem 20x 应该打印出“不是数字”,因为它包含一个 x。我的代码似乎没有循环遍历命令行参数中的所有字符。 我基本上尝试了不同类型的循环,
这里我有从标准输入将字符流输入到数组中的代码。然后将该数组转换为二维数组。然后,它将该数组从行列顺序更改为列行顺序。然后它打印出创建凯撒移位加密的新数组。我遇到的问题是我的数组开始使用第二个用户输入的
我有点被这个问题困住了。当我运行程序时,由于某种原因,循环经过 z 的所有字母都不会打印。问题来自这个链接:http://docs.cs50.net/2016/x/ap/problems/caesar
我是一名优秀的程序员,十分优秀!