以下是CS50课程练习的一部分。完整的问题在这里描述:https://cs50.harvard.edu/x/2021/psets/2/substitution/
简而言之:在命令行上,您提供了一个26个长的字母数组作为参数,这些字母将用于“加密”一个字符串,该字符串在运行时被提示为明文。
然后将明文数组循环,并将其ascii整数值(略为简化)用于索引到作为命令行参数提供的26个字母密钥中,从而加密初始明文字符串(ptxt)并将其存储在新的密文字符串(ctxt)中。
我遇到的问题是,对于纯文本小于6的输入,我用来在'n'中存储ptxt长度的strlen()函数似乎返回6。因此,如果我在明文提示下只键入字母“a”,n似乎被设置为6。
以下例子:
$ ./替换YTNSHVEFXRBAUQZCLWDMIPGJO
明文:a
密文:y.G[
密文有6长
预期的输出应该是'y',但显然有些东西超出了范围——长度不应该是6,而应该是1。让我发疯的是——如果你在初始化'n'后取消对printf语句的注释,那么代码会突然起作用,你会得到以下结果:
$ ./替换YTNSHVEFXRBAUQZCLWDMIPGJO
明文:a
明文长度为1
密文:y
密文的长度是1
我错过了什么?printf调用是如何解决这个问题的?
快把我逼疯了:)
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
bool is_letter(string array);
char encrypt(string key, char c);
//Command Line input a key to 'encrypt' some plaintext inputted at runtime
int main(int argc, string argv[])
{
// if there are NOT 2 arguments OR the first argument is NOT just letters OR is not 26 letters
if (argc != 2 || !is_letter(argv[1]) || strlen(argv[1]) != 26)
{
printf("Usage: ./caesar key (where key must be 26 letters)\n");
return 1;
}
// prompt user for a plaintext string, store the length in n and initialize a ciphertext string with same length
string ptxt = get_string("plaintext: ");
int n = strlen(ptxt);
//printf("plaintext is %i long\n", n); //this is here to correct n (try commenting out this line and see what happens for ptxt < 6)
char ctxt[n];
for (int i = 0; i < n; i++)
{
ctxt[i] = encrypt(argv[1], ptxt[i]);
}
printf("ciphertext: %s\n", ctxt);
printf("ciphertext is %i long\n", (int) strlen(ctxt));
return 0;
}
// function that checks whether command line argument is all letters
bool is_letter(string array)
{
int n = strlen(array);
for (int i = 0; i < n; i++)
{
if (!isalpha(array[i])) //loop over string - if any char is not a letter - return false
{
return false;
}
}
return true; //reaching this means all chars in the string are a letter - return true
}
//function that takes a key and a char and returns the "encrypted" char
char encrypt(string key, char c)
{
if (isalpha(c))
{
int n = 0;
char letter = 0;
if (isupper(c))
{
n = c - 65;
letter = key[n];
return toupper(letter);
}
else
{
n = c - 97;
letter = key[n];
return tolower(letter);
}
}
else
{
return c;
}
}
C中没有“字符串”这个词。C中的“字符串”实际上是字节数组,char*
。C中的数组不知道它们有多长,没有内置的边界检查。你要么需要知道它们的大小,要么就有一个终结者。“字符串”以0结尾,称为“空字节”,通常表示为\0
。
strlen
读取字节,直到看到空字节。如果没有空字节,strlen
将愉快地从数组末尾进入垃圾内存,直到它碰巧看到空字节,或者操作系统阻止程序超出其内存边界,这是一个分段错误。
// A basic strlen() implementation.
size_t my_strlen(const char *string) {
size_t len;
// no body, just counting until it sees a null byte.
for( len = 0; string[len] != '\0'; len++ );
return len;
}
(IMO CS50在学习C时试图隐藏这一点是有害的。有一个悠久的传统,就是试图把C当作不是C来对待。C的裸机、热棒、没有护栏的特性不能零碎地隐藏起来。你要么会得到一个混乱的结果,要么会得到一种新的语言。如果你想要字符串,请使用C或像GLib这样完全实现的库。)
当逐字节创建新字符串时,必须终止它。它必须有一个额外的字节来存储0。
// Allocate an extra byte for the terminating null.
// At this point ctxt contains garbage.
char ctxt[n+1];
for (int i = 0; i < n; i++)
{
ctxt[i] = encrypt(argv[1], ptxt[i]);
}
// Terminate the string.
ctxt[n] = '\0';
printf调用是如何解决这个问题的?
当您像char ctxt[n 1]
这样分配内存时,它是未初始化的。它不会自动归零。它包含了记忆中的所有垃圾。你可以走运,得到全零。它可能包含其他字符串。它可能包含看起来像随机垃圾的东西。
在分配ctxt
之前添加printf
会稍微改变分配给ctxt
的内存块printf
还必须分配内存,因此ctxt
可能会得到一个恰好以零开头的稍有不同的内存块ctxt
可能会得到printf分配、归零和释放的内存块。由于内存是一种全局资源,程序某个部分的更改可能会暴露或隐藏程序另一部分的内存错误。
valgrind和AddressSanitizer等工具可以帮助发现这些微妙的错误。
我正在尝试运行一个in查询(springboot jpa mysql)。我已经启用了调试日志,查询似乎很好,但是SpringJPA没有返回任何结果。 以下是配置: 这是我的存储库: //或 这里需要注意的是,“in”查询中的列不是主键。 生成的查询:
本章目录 1. 一个特殊的参数:return_value 2. 引用与函数的执行结果 3. 小结 PHP语言中函数的返回值是通过return来完成的,就像下面的程序: <?php function sample_long() { return 42; } $bar = sample_long(); C语言也一样使用return关键字 int sample_long(void) { r
问题内容: 我想我已经找到了错误所在: 我进行调试,得到以下结果(我输入了555和欧元): 因此看来,用于解码JSON对象的PHP函数在某处做错了。有什么帮助吗? 问题答案: Google给您的响应不是有效的JSON,因为未引用标签。您必须自己解析。 输出:
我们想写一个函数,它将二叉树的根作为输入,并使用类PairAns返回该树的最大值和最小值。 我在这个问题的基础案例中遇到了一些问题 我希望答案是正确的,但在所有测试用例中都出现了运行时错误。
我正在处理LeetCode问题111。二叉树的最小深度: 给定一棵二叉树,求其最小深度。 最小深度是从根节点到最近的叶节点的最短路径上的节点数。 注意:叶是没有子节点的节点。 我使用了广度优先的算法,并试图改变它以使其与问题保持一致。但是函数返回的是。 有人能解释为什么会这样吗?
本文向大家介绍返回JavaScript中数组的最小值和最大值的函数,包括了返回JavaScript中数组的最小值和最大值的函数的使用技巧和注意事项,需要的朋友参考一下 问题 我们需要编写一个接受一个数组并返回另一个数组的JavaScript函数,该数组的第一个元素应该是输入数组的最小元素,第二个应该是输入数组的最大元素。 示例 以下是代码- 输出结果