[英]scanf_s doesn't work with printf in Visual Studio C++ 2010 Express
[英]For loop doesn`t work when add [^\n] to a scanf_s
该程序应该要求您将成员(人员)添加到结构中并将它们打印到文件上,但在第一个 for 循环之后停止工作并跳过名称部分。 我刚刚发现允许您向字符串添加空格的东西,尝试过但没有成功......我试图删除它并且它可以正常工作,所以[^\n]
会出错。 怎么了 ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Staff {
char Surname[100];
char Name[100];
int age;
char spec[100];
int id;
} person;
void write();
void leggi();
void trova();
int main() {
write();
}
void write() {
int i = 0;
int n = 1;
int r;
FILE *fp;
fopen_s(&fp, "index.txt", "w+");
if (fp == NULL) {
printf("Failed to open file\n");
exit(1);
}
fprintf(fp, "%d\n", i);
for (i = 0; i < n; i++) {
printf("Surame:\n");
scanf_s("%[^\n]s", person.Surname, 100);
fprintf(fp, "%s\t\t", person.Surname);
//loop just get over the name part
printf("Name:\n"); //after the first loop
scanf_s("%s", person.Name, 100);
fprintf(fp, "%s\t", person.Name);
printf("Age:\n");
scanf_s("%d", &person.age);
fprintf(fp, "%d\t", person.age);
printf("Specialization\n");
scanf_s("%s", person.spec, 100);
fprintf(fp, "%s\n", person.spec);
printf("Want to enter another? 1=yes 0=no...\n");
scanf_s("%d", &r);
if (r == 1)
n = n + 1;
}
rewind(fp);
fprintf(fp, "%d\n", i);
fclose(fp);
}
您的代码中有多个问题:
您使用所谓的安全函数fopen_s
、 scanf_s
等,但您不检查返回值以检测无效输入。 您应该改用标准函数,传递适当的参数并检查返回值。
使用scanf_s
实际上是不可移植的:C 标准附件 K 中定义的scanf_s
函数要求指针后面的长度参数具有size_t
类型,而 Microsoft 库中的同名函数使用类型UINT
,其表示形式不同在他们的 Windows 操作系统的 64 位版本上。 拥抱、增强和消灭策略的经典案例。 在标准 C 中,应该写: scanf_s("%s", person.Name, (size_t)100)
或更好:
scanf_s("%s", person.Name, sizeof person.Name)
无需使用"w+"
打开输出文件进行更新,只需使用"w"
即可。
您将流指针倒回到文件的开头并覆盖文件开头的条目数。 只要您的条目少于 10 个,此方法就有效,但除此之外,该数字有更多位数,因此文件中的某些字符将被损坏。 您可以使用带有填充的格式,例如"%6d\n"
,这将允许最多 100 万条记录而没有风险。
"%[^\n]s"
不是正确的scanf
格式:您应该只写"%[^\n]"
或更好的" %99[^\n]"
以跳过初始空白并将输入限制为 99人物。
这是修改后的版本:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Staff {
char Surname[100];
char Name[100];
int age;
char spec[100];
int id;
};
void write(void);
void leggi(void);
void trova(void);
int main() {
write();
}
int flush_input(void) {
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
return c;
}
void write(void) {
int n = 0;
int r;
FILE *fp = fopen("index.txt", "w");
if (fp == NULL) {
fprintf("Failed to open file index.txt: %s\n",
strerror(errno));
exit(1);
}
fprintf(fp, "%6d\n", n);
for (;;) {
struct Staff person = { 0 };
printf("Surname:\n");
if (scanf(" %99[^\n]", person.Surname) != 1)
break;
flush_input();
fprintf(fp, "%s\t\t", person.Surname);
//loop just get over the name part
printf("Name:\n"); //after the first loop
scanf(" %99[^\n]", person.Name);
flush_input();
fprintf(fp, "%s\t", person.Name);
printf("Age:\n");
scanf("%d", &person.age);
flush_input();
fprintf(fp, "%d\t", person.age);
printf("Specialization\n");
scanf(" %99[^\n]", person.spec, 100);
flush_input();
fprintf(fp, "%s\n", person.spec);
n++;
printf("Want to enter another? 1=yes 0=no...\n");
if (scanf("%d", &r) != 1 || r != 1) {
flush_input();
break;
}
flush_input();
}
rewind(fp);
// update the entry count on 6 characters
fprintf(fp, "%6d\n", n);
fclose(fp);
}
通过在格式字符串的开头插入空格来更改下面的 scanf 调用以输入字符串。 例如,而不是这个电话
scanf_s("%[^\n]s", person.Surname, 100);
(其中字母s
必须从格式字符串中删除)写
scanf_s(" %[^\n]", person.Surname, ( rsize_t )100);
^^^^^^^^
这允许跳过输入缓冲区中的前导空白字符。
注意改变条件或 for 循环就像你正在做的那样
for (i = 0; i < n; i++) {
//...
if (r == 1)
n = n + 1;
}
使代码不清楚。 代替 for 循环,您可以使用 do-while 循环。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.