循环中使用数组字符串,Scanf("%[^\n]")无法工作

3

我用C语言编写了这段代码。我需要解决一个问题,需要输入5行字符串包括空格。这个程序会输出所有5行字符串,包括空格。所谓的空格是指在输入时,我可以在任何字符前面或后面加上空格。这就是我编写这段代码的原因,但我不明白为什么它不能正常工作。

#include<stdio.h>
int main() {
    char str[5][100];
    for(int i=0;i<5;i++) {
        scanf("%[^n\]",str[i]);
    }
    for(int j=0;j<5;j++) {
        printf("%s\n",str[j]);
    }
    return 0;
}

我试图只使用
scanf("%s",str[i]);

但是它忽略了输入中的所有空格并修剪了输出。此外,我尝试使用

scanf(" %[^\n]",str[i]);

这次好了一点,但它忽略了在任何字符之前的所有空格。例如输入如下:
    Robin Islam
// output showing
Robin Islam
// should show
    Robin Islam

我想让这个程序能够在任何地方允许空格,我的意思是输出应该与输入一样,而不忽略空格。有人可以帮忙吗?我尝试了很多方法,但不知道如何使它工作或如何解决......拜托了。

谢谢, 罗宾


scanf %s 会读取整个字符串,你需要用其他方式按空格进行分割。 - BitWhistler
尝试使用 scanf("%99[^\n]\n", str[i]); - ddz
scanf() 不太擅长读取行,建议使用 fgets() - chux - Reinstate Monica
实际上,这允许在任何字母字符后面添加空格,例如:Robin "这里允许空格" Islam但是在这里, "忽略空格,我是指在单词之前" Robin Islam - Robin
fgets(); :) 感谢大家 :) - Robin
显示剩余4条评论
2个回答

2
“scanf”存在许多问题,只需在此处搜索即可看到。 尽可能避免使用它。
您正在读取整行文本,有专门的函数可以完成这项任务。 “fgets”和“getline”。 我更喜欢getline,因为它会为您处理内存分配,不存在输入超出缓冲区的风险。
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>

int main() {
    char *line = NULL;
    char *lines[5];
    size_t linecap = 0;

    for( int i = 0; i < 5; i++ ) {
        /* Getline will allocate sufficient memory to line.
           It will also reuse line, so... */
        getline(&line, &linecap, stdin);

        /* ...we have to copy the line */
        lines[i] = strdup(line);
    }

    /* line must be freed after calls to getline() are finished */
    free(line);

    for( int i = 0; i < 5; i++ ) {
        printf("%s\n", lines[i]);
    }

    /* Cleaning up all memory is a good habit to get into.
       And it removes clutter from you Valgrind report. */
    for( int i = 0; i < 5; i++ ) {
        free(lines[i]);
    }

    return 0;
}

1
为了完整性,需要添加free(lines[i]) - chux - Reinstate Monica
@Michi 使用 scanf 的错误方式有很多种。除非你知道自己在做什么,否则最好避免使用它。即使如此,最好还是将 IO 分开处理并使用 sscanf - Schwern
感谢您的精彩解释,它真的帮助我理解了很多事情。然而,这个解决当前问题的过程有点长,但我相信它一定会在未来的问题中对我有所帮助。非常感谢。 - Robin
@Schwern同意,但SCANF没有错,只是像你指出的那样,如果使用不当就会有问题。太多人把SCANF当作危险函数。 - Michi
@Michi scanf是危险的,因为它鼓励你将未绑定的输入传递到固定大小的缓冲区中,这只是其中一个问题。危险函数是那些最简单使用方式最危险的函数。例如,strcpy可以安全使用,但每次使用它都需要大量额外的代码来使其安全。或者您可以使用strlcpy而不冒任何风险。scanf非常糟糕,它有自己的标签,有2000多个问题 - Schwern
@Schwern 对不起,如果让你误以为我不知道关于SCANF的“问题”。只要使用得当,SCANF是安全的。就像我说的,如果出现2000+个问题,那只是因为他们对SCANF并不了解。 - Michi

1
#include<stdio.h>
#include<stdlib.h>

int main() {

    char str[5][100];
    for(int i=0;i<5;i++) {
        fgets(str[i],100,stdin);
    }
    for(int j=0;j<5;j++) {
        printf("%s\n",str[j]);
    }

    return 0;
}

非常感谢,这几乎就是我需要解决当前问题的全部内容,但有一个问题。 当它打印结果时,我可以看到它添加了额外的换行符“\n”,您能告诉我为什么会这样吗? - Robin
非常感谢,但还有另一个问题。#include<iostream> #include<stdio.h> #include<stdlib.h>int main() { int n; scanf("%d",&n); char str[n][100]; for(int i=0;i<n;i++) { fgets(str[i],100,stdin); } for(int j=0;j<n;j++) { printf("%s",str[j]); } return 0; }只是添加了1个scanf();来获取行数,导致第一次fgets()跳过获取输入,然后它从第二次开始要求输入。您能否请检查一下... - Robin
请在聊天中继续,我会尽力为您解答。 - JCollerton
谢谢 #JCollerton,但我实际上没有足够的声望进入聊天室。但是我已经感激你的回答了。非常感谢。 - Robin
谢谢,您能否举个例子,告诉我除了scanf()之外还有哪些方法可以获取数字输入?谢谢。 - Robin
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接