看起来scanf()正在阅读之前的' \ n'。我试图将我的串联字符串放在一行上。如何摆脱' \ n'在我的第二个字符串的开头。
这是一个c程序。
我猜测我必须在读取下一行之前以某种方式刷新缓冲区。但我不知道如何在没有错误的情况下执行此操作。
顺便说一下,我不能在这里使用cin.get()或其他标准的cin / cout操作。我也不能使用标准的字符串操作,因为我只使用c-strings和strings.h,而不是字符串。
stdin的输入是:
12
4.0
Spot run!
int main() {
int i = 4;
double d = 4.0;
char s[] = "See ";
int isum;
int MAX_SIZE = 256;
double dsum;
char s2[MAX_SIZE];
scanf("%i",&isum);
scanf("%lf",&dsum); // Hope to clear out the newline from reading
// in the double value. Or any other newline
// before the next scarf(), but haven't figured
// how.
scanf("%79c", s2);
isum += i;
printf("%d \n",isum);
dsum += d;
printf("%.1f \n",dsum);
char newchar[MAX_SIZE];
strcpy(newchar,s);
newchar[strcspn(newchar,"\n")]='\0';
s2[strcspn(s2,"\n")] = 't'; //To test where newline is in second string.
strcat(newchar,s2);
printf("%s",newchar);
return 0;
我的输出是:
16
8.0
See
tSpot run!
//< - 注意' t'在现场!!!!
答案 0 :(得分:2)
根据要求。
关于scanf()
及其亲属的行为有很多问题,它们是标准C库中最微妙和最复杂的函数。转换规范(例如%lf
)在下一个字符不是数字的一部分时停止读取 - 使该字符由下一个转换规范处理。请注意,%c
(以及%[…]
扫描集和%n
)不会跳过前导空格;所有其他转换规范都会跳过前导空格。如果您不希望数字输入遗留换行符,请使用" %79c"
跳过任何空格。格式字符串中的空白会跳过零个或多个空格字符,包括空格,制表符和换行符。
目前,"%79c"
从4.0
后面读取换行符,“Spot run!
”中的字符包含后面的换行符,并在假定输入后停止读取达到EOF。
See
之后你不应该换行。 t
写的s2[strcspn(s2,"\n")] = 't';
会覆盖s2
的第一个字节,这是4.0之后的换行符。
你有没有意识到这一行:
newchar[strcspn(newchar, "\n")] = '\0';
使用空字节覆盖See
之后的空格之后的空字节,这是一个无操作。
我经常使用的一种技术是将输入日期打印在一组合适的括号中,有时候<<…>>
,有时候[…]
,这取决于奇思妙想或可能的内容。例如:
#include <stdio.h>
#include <string.h>
int main(void)
{
int i = 4;
double d = 4.0;
char s[] = "See ";
int isum;
int MAX_SIZE = 256;
double dsum;
char s2[MAX_SIZE] = ""; // See comments.
scanf("%i", &isum);
scanf("%lf", &dsum);
scanf("%79c", s2);
printf("s2 = [%s]\n", s2);
isum += i;
printf("%d\n", isum);
dsum += d;
printf("%.1f\n", dsum);
char newchar[MAX_SIZE];
strcpy(newchar, s);
newchar[strcspn(newchar, "\n")]='\0';
s2[strcspn(s2, "\n")] = 't';
strcat(newchar, s2);
printf("%s", newchar);
return 0;
}
正如Cool Guy在comment中指出的那样,重要的是要记住%c
不添加空字节(它只需要一个存储字符);同样,%79c
不会在结尾添加空字节。因此,s2
初始化为'所有字节为零'是必要的,以防止在连接到newchar
时出现未定义的行为。或者你必须使用%n
(可能使用两次)的复杂技术来找出在s2
中读取了多少字节,这样你就可以在事件发生后将其终止。
此变体的输出是:
s2 = [
Spot run!
]
16
8.0
See tSpot run!
因此在输入后的s2
开头和结尾都有换行符。