剥离换行符非常棘手

Stripping newline is being very tricky

看起来 scanf() 正在读取前一个 '\n'。我正在尝试将连接的字符串放在一行中。如何去掉第二个字符串开头的“\n”。

这是一个c程序。

我猜我必须在读入下一行之前以某种方式刷新缓冲区。但我不知道如何做到这一点而不会出错。

顺便说一句,我不能在这里使用 cin.get() 或其他标准 cin/cout 操作。我也不能使用标准字符串操作,因为我只使用 c 字符串和 strings.h,而不是字符串。

来自标准输入的输入是:

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")]='[=10=]';
    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! //<--注意 Spot 前面的 't'!!!

根据要求。

关于 scanf() 及其相关函数的行为有很多问题,它们是标准 C 库中一些最微妙和最复杂的函数。当下一个字符不是数字的一部分时,诸如 %lf 之类的转换规范将停止读取 - 让该字符由下一个转换规范处理。请注意 %c(连同 %[…] 扫描集和 %n)不要跳过前导白色 space;所有其他转换规范都会跳过前导白色 space。如果您不希望数字输入留下换行符,请使用 " %79c" 跳过任何白色 space。格式字符串中的空格会跳过零个或多个白色 space 字符,包括空格、制表符和换行符。

就目前而言,"%79c"4.0 之后读取换行符,'Spot run!' 中的字符包括其后的换行符,并停止读取假设然后输入到达 EOF。

你不应该在 See 之后换行。 s2[strcspn(s2,"\n")] = 't';写的t覆盖了s2的第一个字节,是4.0以后的换行。

你有没有意识到这一行:

newchar[strcspn(newchar, "\n")] = '[=10=]';

用空字节覆盖 See 之后的 space 之后的空字节,这是一个无操作。

我经常使用的一项技术是打印包含在一组合适的括号中的输入日期,有时 <<…>> 有时 […],具体取决于心血来潮或可能的内容。例如:

#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")]='[=11=]';
    s2[strcspn(s2, "\n")] = 't';
    strcat(newchar, s2);
    printf("%s", newchar);

    return 0;
}

正如Cool Guy in his 所指出的,重要的是要记住%c不添加空字节(它只需要存储一个字符);同样,%79c 不会在末尾添加空字节。因此,将 s2 初始化为 'all bytes zero' 是必要的,以防止在连接到 newchar 时出现未定义的行为。或者你必须使用 %n 的精细技术(可能使用两次)来找出有多少字节被读入 s2 以便你可以在事件发生后 null 终止它。

这个变体的输出是:

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

所以输入后s2的开头和结尾各有一个换行符