剥离换行非常棘手

时间:2016-04-16 05:24:41

标签: c printf scanf stdin c-strings

看起来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'在现场!!!!

1 个答案:

答案 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 Guycomment中指出的那样,重要的是要记住%c不添加空字节(它只需要一个存储字符);同样,%79c不会在结尾添加空字节。因此,s2初始化为'所有字节为零'是必要的,以防止在连接到newchar时出现未定义的行为。或者你必须使用%n(可能使用两次)的复杂技术来找出在s2中读取了多少字节,这样你就可以在事件发生后将其终止。

此变体的输出是:

s2 = [
Spot run!
]
16
8.0
See tSpot run!

因此在输入后的s2开头和结尾都有换行符。