我搜索了所有的网络,但我还没有找到真正的解决方案(也许我还没有用正确的搜索,我不知道)。 但是我们在这里:这是我的第一个带有结构的C项目,我尝试使用gets和puts来克服printf-scanf的白色空间问题,但是这会导致很多问题(程序被跳过)直接到看跌期权,没有获得)所以我进入了这个论坛的另一位客人的话题,其中提到了
scanf("%[^\n]",str);
我将此应用于我的代码,但我遇到了同样的问题,我也尝试了
scanf("%[^\n]s",str);
scanf("%[^\n]",&str); //despite looked senseless to me
我读过关于fgets和fscanf的内容,但我还处于早期阶段
以下是代码......我使用的是在Windows 10上运行的Visual Studio 2015。
#include <stdio.h>
#include <string.h>
typedef struct s_libro {
char titolo[50];
char autore[50];
char editore[20];
int pagine;
int costo$;
}t_libro;
int main() {
t_libro libro1;
t_libro libro2;
printf("Inserire autore(max 50) ,titolo(max 50) , editore(max 20), pagine, costo$\n");
//LIBRO 1
printf("\nLIBRO 1\n");
printf("\nInserisci il nome dell'autore del libro1 : \n");
scanf("%[^\n]", libro1.autore);
printf("\nInserire titolo del libro1 : \n");
scanf("%[^\n]", libro1.titolo);
printf("\nInserire nome dell'editore del libro1:\n");
scanf("%[^\n]", libro1.editore);
printf("\nInserire numero di pagine del libro1 : \n");
scanf("%d", &libro1.pagine);
printf("\nInserire il costo (dato numerico) del libro1 : \n");
scanf("%d", &libro1.costo$);
printf("\nLIBRO1\t");
printf("\nTitolo Libro1\t %s", libro1.titolo);
printf("\nAutore Libro1\t %s", libro1.autore);
printf("\nPagine Libro1\t %d", libro1.pagine);
printf("\nEditore Libro1\t %s", libro1.editore);
printf("\nCosto Libro1\t %d $", libro1.costo$);
printf("\n\n");
//LIBRO 2
printf("\nLIBRO 2\n");
printf("\nInserisci il nome dell'autore del libro2 : ");
scanf("%[^\n]", &libro2.autore);
printf("\nInserire il titolo del libro2 : ");
scanf("%[^\n]", &libro2.titolo);
printf("\nInserire L'editore del libro2:");
scanf("%[^\n]", libro2.editore);
printf("\nInserire il numero di pagine del libro2 : ");
scanf("%d", &libro2.pagine);
printf("\nInserire il costo (dato numerico) del libro2 : ");
scanf("%d", &libro2.costo$);
printf("\nLIBRO2\t");
printf("\nTitolo Libro2\t %s", libro2.titolo);
printf("\nAutore Libro2\t %s", libro2.autore);
printf("\nPagine Libro2\t %d", libro2.pagine);
printf("\nEditore Libro2\t %s", libro2.editore);
printf("\nCosto Libro2\t %d $", libro2.costo$);
printf("\n\n");
}
答案 0 :(得分:2)
你有两个问题:
scanf()
是否成功。scanf()
leaves the newlines in the input stream。您的代码如下:
printf("\nInserisci il nome dell'autore del libro1 : \n");
scanf("%[^\n]", libro1.autore);
printf("\nInserire titolo del libro1 : \n");
scanf("%[^\n]", libro1.titolo);
首先应该有效。第二个将失败,因为第一个在输入流中留下了一个换行符,并且扫描集不会将换行符识别为有效,因此它会失败。
有几种可能的解决方案。哪个最好取决于您的详细要求。
fgets()
或POSIX getline()
来读取行,然后使用sscanf()
处理数据。" %49[^\n]"
以跳过包含换行符的空格,然后再将49个非换行符读入变量。这是最小的变化。长度限制可防止缓冲区溢出。是的,格式字符串中的大小不包括空字节。使用scanf()
读取每次输入后的行的残差。例如:
static inline void gobble(void)
{
int c;
while ((c = getchar()) != EOF && c != '\n')
;
}
然后:
printf("\nInserisci il nome dell'autore del libro1 : \n");
if (scanf("%49[^\n]", libro1.autore) != 1)
…process error or EOF…
gobble();
printf("\nInserire titolo del libro1 : \n");
if (scanf("%49[^\n]", libro1.titolo) != 1)
…process error or EOF…
gobble();
毫无疑问,还有很多其他选择;你必须决定什么最适合你。请注意,每次使用时都应检查scanf()
的状态,而 应确保您不允许溢出。
顺便提一下,scanf("%[^\n]", &str)
变种是错误的。传递的参数类型为char (*)[50]
(如果变量为char str[50];
),但扫描集转换规范需要char *
- 一种完全不同的类型。有一个怪癖意味着你逃脱它; str
和&str
的地址值相同,但类型不同,通过查看(str + 1)
和&str + 1
可以看出 - 值会有很大差异。正确的表示法是scanf("%[^\n]", str)
,因此(模数添加溢出保护)。
答案 1 :(得分:1)
如果您想保留空格,我建议您使用fgets
,然后删除任何尾随的新行字符,例如使用strcspn
(由xing建议)。阅读项目将如下所示:
printf("\nInserisci il nome dell'autore del libro1 : \n");
fgets(libro1.autore,50,stdin);
libro1.autore[strcspn(libro1.autore,"\n")] = '\0';
如果用户输入许多字符,那么优点是您可以安全地处理缓冲区溢出问题&#34;请注意,有效名称最多包含48个字符(+新行字符+字符串终止字符)。并且 - 在用户的常规输入中 - 您可以安全地处理可能影响任何后续scanf("....")
语句的新行字符。
请注意,scanf
之类的scanf(" %[^\n]", libro1.autore)
具有格式中的前导空格,不允许用户输入&#34;空&#34; name,因为格式中的空格将使用(仅)新行字符作为空格。没有前导空格的scanf
,即scanf("%[^\n]", libro1.autore)
不会消耗任何新行,从而导致您遇到的问题。
Conclusio:在这种情况下不要使用scanf
。