我的常量在改变,我不知道为什么,甚至不知道如何
My constant is changing, and I dont know why, or even how
我正在制作一个基本上“加密”文本的程序,方法是用其他字母替换字母。所以你基本上 运行 程序并输入一个分布,然后输入你想要加密的文本,它会把密码还给你。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cs50.h>
#include <ctype.h>
string make_lower(string word);
int main (int argc, string argv[])
{
//we examine the input
if (argc < 2 || argc > 2)
{
printf("Usage: ./substitution key\n");
return (1);
}
if (strlen(argv[1]) != 26)
{
printf("Key must contain 26 characters.\n");
return (1);
}
if (strlen(argv[1]) == 26)
{
for (int i = 0; i < 26; i++)
{
if (isdigit(argv[1][i]))
{
printf("Key must onlyontain alphabetic characters.\n");
return (1);
exit(0);
}
}
for (int i = 0; i < 26; i++)
{
for (int o = i + 1; o < 26; o++)
{
if (argv[1][i] == argv[1][o])
{
printf("Key must not contain repeated characters.\n");
return (1);
exit(0);
}
}
}
//we prompt the user for the words to transcribe
const string text = get_string("plaintext: ");
//we set everithing in lower caso to compare it, and set a new variable to store the original text so we can convert the
// upper cases back later
string ntext = text;
printf("%s\n", text);
argv[1] = make_lower(argv[1]);
ntext = make_lower(ntext);
printf("%s\n", text);
string alphabet = "abcdefghijklmnopqrstuvwxyz";
//we substitute the text to the desired outcome
for (int i = 0, n = strlen(ntext); i < n; i++)
{
for (int o = 0; o < 26; o++)
{
if (ntext[i] == alphabet[o])
{
ntext[i] = argv[1][o];
}
}
}
printf("%s\n", text);
printf("ciphertext: ");
for (int i = 0, n = strlen(ntext); i < n; i++)
{
if (isupper(text[i]))
{
printf("%c", toupper(ntext[i]));
}
else
{
printf("%c", ntext[i]);
}
}
printf("%s\n", text);
printf("\n");
return(0);
exit(0);
}
}
string make_lower(string word)
{
for (int i = 0; i < strlen(word); i++)
{
word[i] = tolower(word[i]);
}
return(word);
}
所以我的问题出在代码的输出上,因为问题是如果你想要加密的文本是例如“Hello”,它应该像“Ktlly”这样的例子出现,但我的输出是“ktlly”,因此结果中不显示大写字母。
当您输入要加密的代码时,程序将其存储在一个常量字符串中,然后创建一个新变量并将其设置为等于您输入的文本,然后程序将该新变量转换为小写,因此它可以进行比较,最后当我们对文本进行加密时,我尝试通过制作一个 if 语句(第 82 行)将我想要的那些字符再次变成大写,但事实并非如此。我试着看看为什么,这就是为什么我设置在第 56、62、78 和 94 行打印常量,看看为什么它不起作用,结果发现变量在变化,即使是应该是一个常数。起初在第 56 行它仍然是原始文本;然后在第 62 行,它是相同的文本,但小写;然后在第 78 行和第 94 行,它本身被修改为文本的加密版本。
基本上就是这样,我不知道为什么会这样。至少对我来说,代码似乎是正确的,我的理论是它与函数有关,或者它与洞代码内置的大“if”语句有关。感谢您通读所有这些。
make_lower
改写了它的参数。您需要复制 string
。考虑使用 strdup()
.
我有点惊讶这没有引发编译器警告。
string make_lower(string word)
{
word = strdup(word);
//...
以下评论错误:
//we set everithing in lower caso to compare it, and set a new variable to store the original text so we can convert the
// upper cases back later
string ntext = text;
cs50.h
中定义的标识符string
只不过是数据类型char *
的typedef
。这意味着 string
类型的变量实际上并不包含字符串,而只是指向一个字符串。
在上面引用的行中,您只是复制指针,而不是实际的字符串。由于 ntext
和 text
现在都指向同一个字符串,当您修改 ntext
指向的字符串时,您也在修改 text
指向的字符串。这似乎不是你想要的。
如果要创建字符串的副本,而不仅仅是复制指针,则必须首先使用 malloc
, and then you can copy the string using strcpy
:
为新字符串分配内存
//allocate memory for copy of the string
string ntext = malloc( strlen(text) + 1 ); //add 1 for the terminating null character of the string
//copy the string
strcpy( ntext, text );
大多数编译器还支持函数 strdup
,它在单个函数调用中处理内存分配和字符串复制。如果您的编译器支持该函数,那么您可以改用它:
string ntext = strdup( text );
请注意,所有内存分配函数(例如 malloc
和 strdup
)都可能失败,例如当操作系统内存不足时。在那种情况下,函数 malloc
和 strdup
将 return 一个 NULL
指针。如果你使用这样一个 NULL
指针而不事先检查它是否是 NULL
,那么你的程序很可能会崩溃。出于这个原因,我在上面发布的代码实际上是错误的,因为它在取消引用指针之前没有检查 NULL
。
因此,下面的代码会更好,它检查 NULL
的 return 值,如果内存分配失败,则打印错误消息并退出程序:
对于malloc
/strcpy
:
//allocate memory for copy of the string
string ntext = malloc( strlen(text) + 1 );
//verify that allocation was successful
if ( ntext == NULL )
{
fprintf( stderr, "memory allocation error!\n" );
exit( EXIT_FAILURE );
}
//copy the string
strcpy( ntext, text );
对于strdup
:
string ntext = strdup( text );
if ( ntext == NULL )
{
fprintf( stderr, "memory allocation error!\n" );
exit( EXIT_FAILURE );
}
我正在制作一个基本上“加密”文本的程序,方法是用其他字母替换字母。所以你基本上 运行 程序并输入一个分布,然后输入你想要加密的文本,它会把密码还给你。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cs50.h>
#include <ctype.h>
string make_lower(string word);
int main (int argc, string argv[])
{
//we examine the input
if (argc < 2 || argc > 2)
{
printf("Usage: ./substitution key\n");
return (1);
}
if (strlen(argv[1]) != 26)
{
printf("Key must contain 26 characters.\n");
return (1);
}
if (strlen(argv[1]) == 26)
{
for (int i = 0; i < 26; i++)
{
if (isdigit(argv[1][i]))
{
printf("Key must onlyontain alphabetic characters.\n");
return (1);
exit(0);
}
}
for (int i = 0; i < 26; i++)
{
for (int o = i + 1; o < 26; o++)
{
if (argv[1][i] == argv[1][o])
{
printf("Key must not contain repeated characters.\n");
return (1);
exit(0);
}
}
}
//we prompt the user for the words to transcribe
const string text = get_string("plaintext: ");
//we set everithing in lower caso to compare it, and set a new variable to store the original text so we can convert the
// upper cases back later
string ntext = text;
printf("%s\n", text);
argv[1] = make_lower(argv[1]);
ntext = make_lower(ntext);
printf("%s\n", text);
string alphabet = "abcdefghijklmnopqrstuvwxyz";
//we substitute the text to the desired outcome
for (int i = 0, n = strlen(ntext); i < n; i++)
{
for (int o = 0; o < 26; o++)
{
if (ntext[i] == alphabet[o])
{
ntext[i] = argv[1][o];
}
}
}
printf("%s\n", text);
printf("ciphertext: ");
for (int i = 0, n = strlen(ntext); i < n; i++)
{
if (isupper(text[i]))
{
printf("%c", toupper(ntext[i]));
}
else
{
printf("%c", ntext[i]);
}
}
printf("%s\n", text);
printf("\n");
return(0);
exit(0);
}
}
string make_lower(string word)
{
for (int i = 0; i < strlen(word); i++)
{
word[i] = tolower(word[i]);
}
return(word);
}
所以我的问题出在代码的输出上,因为问题是如果你想要加密的文本是例如“Hello”,它应该像“Ktlly”这样的例子出现,但我的输出是“ktlly”,因此结果中不显示大写字母。
当您输入要加密的代码时,程序将其存储在一个常量字符串中,然后创建一个新变量并将其设置为等于您输入的文本,然后程序将该新变量转换为小写,因此它可以进行比较,最后当我们对文本进行加密时,我尝试通过制作一个 if 语句(第 82 行)将我想要的那些字符再次变成大写,但事实并非如此。我试着看看为什么,这就是为什么我设置在第 56、62、78 和 94 行打印常量,看看为什么它不起作用,结果发现变量在变化,即使是应该是一个常数。起初在第 56 行它仍然是原始文本;然后在第 62 行,它是相同的文本,但小写;然后在第 78 行和第 94 行,它本身被修改为文本的加密版本。
基本上就是这样,我不知道为什么会这样。至少对我来说,代码似乎是正确的,我的理论是它与函数有关,或者它与洞代码内置的大“if”语句有关。感谢您通读所有这些。
make_lower
改写了它的参数。您需要复制 string
。考虑使用 strdup()
.
我有点惊讶这没有引发编译器警告。
string make_lower(string word)
{
word = strdup(word);
//...
以下评论错误:
//we set everithing in lower caso to compare it, and set a new variable to store the original text so we can convert the
// upper cases back later
string ntext = text;
cs50.h
中定义的标识符string
只不过是数据类型char *
的typedef
。这意味着 string
类型的变量实际上并不包含字符串,而只是指向一个字符串。
在上面引用的行中,您只是复制指针,而不是实际的字符串。由于 ntext
和 text
现在都指向同一个字符串,当您修改 ntext
指向的字符串时,您也在修改 text
指向的字符串。这似乎不是你想要的。
如果要创建字符串的副本,而不仅仅是复制指针,则必须首先使用 malloc
, and then you can copy the string using strcpy
:
//allocate memory for copy of the string
string ntext = malloc( strlen(text) + 1 ); //add 1 for the terminating null character of the string
//copy the string
strcpy( ntext, text );
大多数编译器还支持函数 strdup
,它在单个函数调用中处理内存分配和字符串复制。如果您的编译器支持该函数,那么您可以改用它:
string ntext = strdup( text );
请注意,所有内存分配函数(例如 malloc
和 strdup
)都可能失败,例如当操作系统内存不足时。在那种情况下,函数 malloc
和 strdup
将 return 一个 NULL
指针。如果你使用这样一个 NULL
指针而不事先检查它是否是 NULL
,那么你的程序很可能会崩溃。出于这个原因,我在上面发布的代码实际上是错误的,因为它在取消引用指针之前没有检查 NULL
。
因此,下面的代码会更好,它检查 NULL
的 return 值,如果内存分配失败,则打印错误消息并退出程序:
对于malloc
/strcpy
:
//allocate memory for copy of the string
string ntext = malloc( strlen(text) + 1 );
//verify that allocation was successful
if ( ntext == NULL )
{
fprintf( stderr, "memory allocation error!\n" );
exit( EXIT_FAILURE );
}
//copy the string
strcpy( ntext, text );
对于strdup
:
string ntext = strdup( text );
if ( ntext == NULL )
{
fprintf( stderr, "memory allocation error!\n" );
exit( EXIT_FAILURE );
}