我在作业说明的PDF文件中提供了link。
[TL; DR]
问两个问题: 您是否害怕黑暗?你运动吗?
输入: 'Y'是是,'N'是否。
如果第二个问题的输入是'Y',则另一个问题:每天要执行几分钟?
输入: 整数> 0。但是,如果每天少于10 ,则不合格。>
输出:告诉用户是否可以输入忍者训练。
我遇到的困难:
我只编写了大约一个星期的代码,所以我知道这对于这项作业来说可能有些过头了。话虽如此,我在做这项作业的时候就有了一个主意,虽然我发现用言语表达我的主意是非常具有挑战性的,但是我觉得这是一张捕捉到我“可视化”的图像。
Visual posted on https://www.eskimo.com/~scs/cclass/int/sx9b.html by Steve Summit
在这个特定的作业中,我认为保留用户的答案是浪费内存。但是,如果我想编写一个程序来询问用户一系列输入,最后将它们关联起来,或者对lulz进行虚假关联,该怎么办?
Spurious Correlations http://www.tylervigen.com/spurious-correlations by Tyler Vigen
更实际的原因是MBTI个性类型测试吗?我不知道所有的可能性,但它们似乎令人兴奋。
这就是我要动态分配多维字符串数组要实现的目标
稍后会更新
随后是原始帖子……
该代码有效,但仍然允许某些输入,即,如果第一个元素为Y或N,则输入的任何字符。
代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char reference[][2] = { "Y", "N" };
char (*ptr_reference)[2] = reference;
int reference_minutes[1] = { 10 };
int *ptr_reference_minutes = reference_minutes;
char **user_input;
user_input = (char**)malloc(3 * sizeof(char*));
int i;
for (i = 0; i < 3; i++) {
user_input[i] = (char*)malloc(4 * sizeof(char));
}
if (!user_input) {
printf("Could not allocate memory!/n");
exit(1);
}
i = 0;
while (i == 0) {
printf("\nAre you afraid of the dark? Choose either [Y/N], and press enter when finished: \n");
fgets(user_input[i], 4, stdin);
user_input[i] = realloc(user_input[i], sizeof(char));
if (strncmp(user_input[i], *ptr_reference, 1) == 0) {
printf("\nPatience, Young Grasshoper! You are not ready to become a ninja.");
i = 3;
break;
} else if (strncmp(user_input[i], *(ptr_reference + 1), 1) == 0) {
i++;
break;
} else {
printf("\nPlease enter Y for yes or N for no.\n\n");
continue;
}
}
while (i == 1) {
printf("\nDo you exercise? Input [Y/N], and press enter when finished: \n");
fgets(user_input[i], 4, stdin);
if (strncmp(user_input[i], *ptr_reference, 1) == 0) {
i++;
break;
} else if (strncmp(user_input[i], *(ptr_reference + 1), 1) == 0) {
printf("\nDo you even lift, Bro?");
i = 3;
break;
} else {
printf("\nPlease enter Y for yes or N for no.\n\n");
continue;
}
}
while (i == 2) {
int sscanf_result, answer;
printf("\nHow many minutes a day do you exercise? Type an integer greater than 9 and press enter when finished.\n");
fgets(user_input[i], 4, stdin);
sscanf_result = sscanf(user_input[i], "%d", &answer);
if ((sscanf_result == 0) | (sscanf_result == EOF)) {
/* either a non-integer entered or an end-of-line */
printf ("\nYou have to enter an integer!\n");
i = 2;
continue;
} else if (answer < *ptr_reference_minutes) {
printf("\nCome on! You kids are soft! You lack discipline!\n");
i = 3;
break;
} else {
printf("\nYou are a good fit for ninja training.\n");
for (i = 0; i < 3; i++) {
free(user_input[i]);
}
free(user_input);
user_input = NULL;
break;
}
}
return 0;
}
答案 0 :(得分:2)
好的,我可以看看您的程序。问题不在于分配,而在于字符串管理。在C中,一个字符串是一个以null结尾的char数组(请复制100次...)。
当您读取带有fgets
的行时,会在缓冲区中获得换行符(\n
),因此,如果用户键入 Y Enter ,您得到{'Y', '\n', '\0', undeterminated_char }
。那么以下realloc
就是错误的:
因此,如果您坚持进行字符串比较,则应仅确保第二个字符为空:user_input[i][2] = '\0';
但是恕我直言,这里需要的只是:
if (user_input[i][0] == 'Y') {
...
那还不是全部。您尝试在输入处理中做得很好,但是只忘记了一个细节:如果一行的长度超出了声明的大小,则fgets
会填充其缓冲区,并使行的其余部分可供下次读取。>
以下只是我的建议:
您已尝试将您所知道的一切(可能还没有完全掌握的东西)用于单个简单的程序。别。保持每个程序尽可能的简单(保持愚蠢简单是一种普遍的好习惯...),并相信您的学习者会为您提供其他分配给其他模式的作业。所以在这里您应该:
\n
(可能需要几个fgets
)'Y'
或'N'
'\0'
因为这是现实世界中的普遍要求,并且只有在程序运行后,您才可以考虑:
如果合适的编码对您很重要,请提供最后的建议:程序正常运行后,您应该考虑将其发布在Code Review上以获得有趣的评论。
答案 1 :(得分:0)
@Serge Ballesta @Serga Ballesta非常感谢您的反馈。这非常有帮助。在听取了您的建议之后,我能够编写一个更好的程序,尽管我不确定在“保持简单,愚蠢”方面是否成功。
我仍然不知道如何在'Y'或'N'之后限制字符,即Nnb或Nq被接受为N并进入第二个问题。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (void) {
char *user_input = NULL;
user_input = (char*)malloc(3*sizeof(char));
int sscanf_result, answer;
int i;
while (!*user_input)
{
printf("\nAre you afraid of the dark? \n\nInput Specifications: Please type 'Y' to indicate yes, or 'N' to indicate no, and then press the 'Enter' or 'return' key when finished.\n\n");
i = 0;
fgets(user_input, sizeof(user_input), stdin);
/* trim off last character */
user_input[strlen(user_input)-1] = '\0';
if (user_input[i] == 'Y')
{
printf("\nFear of the dark? Fear those who lurk in the dark, my friend. Ninjas! You may not train as a ninja!");
free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
exit(0);
}
else if (user_input[i] == 'N')
{
free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
printf("\nDo you exercise?\n\nInput Specifications: Please type 'Y' to indicate yes, or 'N' to indicate no, and then press the 'Enter' or 'return' key when finished.\n\n");
i = 0;
fgets(user_input, sizeof(user_input), stdin);
user_input[strlen(user_input)-1] = '\0';
if (user_input[i] == 'N')
{
printf("\nDo you even lift, Bro?\n");
free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
exit(0);
}
else if (user_input[i] == 'Y')
{
free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
printf("\nHow many minutes a day do you exercise?\n\nInput Specifications: Please type a positive integer and press the 'Enter' or 'return' key when finished.\n\n");
i = 0;
fgets(user_input, sizeof(user_input), stdin);
user_input[strlen(user_input)-1] = '\0';
sscanf_result = sscanf(user_input, "%d", &answer);
if ((sscanf_result == 0) | (sscanf_result == EOF))
{
/* either a non-integer entered or an end-of-line */
printf ("\nPlease type a positive integer and then press the 'Enter' or 'return' key when finished.\n");
free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
continue;
}
if (answer < 10)
{
printf("\nCome on! You kids are soft! You lack discipline!\n");
free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
exit(0);
}
else
{
printf("\nYou may begin training as a ninja!\n");
free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
exit(0);
}
}
else
{
printf("\nInput Error: Please carefully read the input specifications that are provided after each question prompt and then try again.\n");
free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
continue;
}
}
else
{
printf("\nInput Error: Please carefully read the input specifications that are provided after each question prompt and then try again.\n");
free(user_input);
for (i = 0; i < 3; i++)
{
user_input[i] = '\0';
}
continue;
}
}
return 0;
}