我以前是一名java程序员,但我现在正在大学(计算机科学专业)修读C课程。
我需要用户能够输入3个字符,前2个是数字,最后1个是'v'或'h'。 例如“1 2 v”。
我需要用户能够输入每个字符之间的空格。
这是我目前的代码:
// Compact lambda
lst.Find(a => a.Name.Equals("Alex"))
// Explicitly typed parameter
lst.Find((FindPerson a) => a.Name.Equals("Alex"))
// Explicit delegate type
lst.Find(new Predicate<FindPerson>(a => a.Name.Equals("Alex")))
// Combination of the two above
lst.Find(new Predicate<FindPerson>((FindPerson a) => a.Name.Equals("Alex")))
// Explicit delegate type through casting
lst.Find((Predicate<FindPerson>)(a => a.Name.Equals("Alex")))
// Lambda block
lst.Find(a => { return a.Name.Equals("Alex"); })
// Delegate block
lst.Find((Predicate<FindPerson>)(delegate(FindPerson a) { return a.Name.Equals("Alex"); }))
// ... etc
}
但是如果我运行它,当我输入带有“12v”之类的空格的字符时它可以正常工作,但是如果我输入“1 2 v”,它将打印出“1”,调用printBox,然后打印出来“ 2“,然后再打印出来,等等。
如果有人能解释我在这里做错了什么,我会很感激。
答案 0 :(得分:3)
如果有人能解释我在这里做错了什么,我会很感激。
短篇小说是:您的代码无法满足您的要求。它根本不能做你想做的事。
您的要求是:
实际上,您的代码通过访问move
数组超出范围来调用未定义的行为。请考虑由于上述某种情况i
可能会变成某些情况值高于3.此代码中可能会发生什么:move[i] = input[i];
?
您的代码也太复杂了。您的所有功能都可以由scanf
单独执行。当你知道如何正确使用它时,它是一个非常强大的功能......当你有机会时,我建议多次阅读和理解the manual。你会学习很多!
我注意到你在你提出的逻辑中忽略了一些东西:预计第一个字段也可能是'x'
,它对应于 exit 用例。这是一个糟糕的设计;来电者没有机会清理......但我会用它来运行。您确实应该使用return
(并返回int
值或其他内容(对应于错误/成功)。
让我们把最后一段放在一边,因为我们可以简单地认为'x'
是无效输入(并因此退出),我不想改变你的功能合同;我会留给你的。到目前为止所描述的表达似乎是int x = scanf("%1[0123456789]%*1[ ]%1[0123456789]%*1[ ]%1[vh]", a, b, c);
。
请注意,a
,b
和c
应该有足够的空间来存储长度为一个字节的字符串。也就是说,他们的声明应该是:char a[2], b[2], c[2];
。
请务必检查返回值(示例中为x
)!如果x
为3,则可以安全地假设三个变量{{1} },a
和b
可以安全使用。如果c
为2,则可以安全地假设x
和a
可以安全使用,依此类推......如果b
为x
或{ {1}},它们都不能安全使用。
通过检查返回值,您可以拒绝与该精确模式不匹配的输入,即:
你忽略了提到的其他东西,它也存在于你的代码中:Chux提到你可能期望输入以EOF
(换行符)字符终止。这也可以使用0
:
'\n'
会尝试准确读取和丢弃一个scanf
字符,但无法确保成功。 scanf("%1*[\n]");
更适合此目的; '\n'
的某些内容可能是有意义的,如果你希望确保输入线完美形成并且当它们不是......时展开...... {/ 1}} getchar
更有意义;如果你有兴趣每行阅读一个项目,那么丢弃该行上剩下的所有内容,然后是新行字符本身是有意义的。请注意,您的程序应始终告诉用户何时丢弃或截断输入。您也可以使用if (getchar() != '\n') { exit(EXIT_FAILURE); }
。#define BOMB_OUT
答案 1 :(得分:1)
%s
用scanf读取以空格分隔的字符串,所以如果这不是你想要的,那就不是用的了。 %c
读取单个字符,但不跳过whitespce,因此您可能还希望格式中的(空格)跳过空格:
char input[3];
scanf(" %c %c %c", intput, input+1, input+2);
将读取3个非空格字符并跳过它们之前或之间的任何空格。您还应检查scanf
的返回值以确保它为3 - 如果不是,则在到达文件结尾之前输入中的字符少于3个。
答案 2 :(得分:0)
由于潜在的缓冲区溢出,通过scanf
读取字符串通常是一个坏主意。考虑使用{/ 1}}或更好fscanf
,如
fgets
请注意&#39; \ 0&#39;。
的额外字节此外,您在此处将char与字符串进行比较:fgets(input, 15, stdin);
。它应该是input[i] != "\n"
。
顺便说一句,你可以使用像
这样的东西input[i] != '\n'
答案 3 :(得分:0)
这看起来像两个简单的错误。
您需要为move []和input []
使用单独的索引 int i = 0;
while(input[i] != 0){
if(input[i] != ' ' && input[i] != "\n"){
move[i] = input[i];
}
i++;
}
想象一下输入1 2 v
输入[0]!= 0,所以我们进入循环
它不是&#39; &#39;或者&#39; \ n&#39;或者,所以我们将input [0]复制到move [0]
到目前为止一切顺利
你增加i,发现输入[1] ==&#39; &#39;
但是你再次增加我
你发现你对输入[2](2)感兴趣 - 所以你把它复制到移动[2],而不是移动[1]。糟糕!
然后更糟糕的是,你永远不会在move []的最后一个有效字符后面放一个字符串结尾的字符。