[英]For loop doesn`t work when add [^\n] to a scanf_s
This program should ask you to add member (people) to a struct and print them on a file but after the first for loop just stop working and jump over the name part.该程序应该要求您将成员(人员)添加到结构中并将它们打印到文件上,但在第一个 for 循环之后停止工作并跳过名称部分。 I just found that thing that allow you to add space to a string, tried it but no success... I tried to remove it and it work without any problem so the
[^\n]
make something go wrong.我刚刚发现允许您向字符串添加空格的东西,尝试过但没有成功......我试图删除它并且它可以正常工作,所以
[^\n]
会出错。 What is wrong ?怎么了 ?
#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);
}
There are multiple problems in your code:您的代码中有多个问题:
you use the so called secure functions fopen_s
, scanf_s
etc, but you do not check the return values to detect invalid input.您使用所谓的安全函数
fopen_s
、 scanf_s
等,但您不检查返回值以检测无效输入。 You should instead use standard functions, pass the appropriate arguments and check the return values.您应该改用标准函数,传递适当的参数并检查返回值。
using scanf_s
is actually non portable: the scanf_s
function defined in Annex K of the C Standard requires the length argument after the pointer to have size_t
type, whereas the function with the same name in the Microsoft library uses type UINT
, which has a different representation on 64-bit versions of their Windows OS.使用
scanf_s
实际上是不可移植的:C 标准附件 K 中定义的scanf_s
函数要求指针后面的长度参数具有size_t
类型,而 Microsoft 库中的同名函数使用类型UINT
,其表示形式不同在他们的 Windows 操作系统的 64 位版本上。 A classical case of the Embrace, enhance and extinguish strategy.拥抱、增强和消灭策略的经典案例。 In Standard C, one should write:
scanf_s("%s", person.Name, (size_t)100)
or better:在标准 C 中,应该写:
scanf_s("%s", person.Name, (size_t)100)
或更好:
scanf_s("%s", person.Name, sizeof person.Name)
there is no need to open the output file for update with "w+"
, just use "w"
.无需使用
"w+"
打开输出文件进行更新,只需使用"w"
即可。
you rewind the stream pointer back to the beginning of file and overwrite the number of entries at the start of the file.您将流指针倒回到文件的开头并覆盖文件开头的条目数。 This works as long as you have less than 10 entries, but beyond that, the number has more digits so some characters in the file will be corrupted.
只要您的条目少于 10 个,此方法就有效,但除此之外,该数字有更多位数,因此文件中的某些字符将被损坏。 You could use a format with padding such as
"%6d\n"
which would allow for up to 1 million records without risks.您可以使用带有填充的格式,例如
"%6d\n"
,这将允许最多 100 万条记录而没有风险。
"%[^\n]s"
is not a correct scanf
format: you should just write "%[^\n]"
or better " %99[^\n]"
to skip initial white space and limit the input to 99 characters. "%[^\n]s"
不是正确的scanf
格式:您应该只写"%[^\n]"
或更好的" %99[^\n]"
以跳过初始空白并将输入限制为 99人物。
Here is a modified version:这是修改后的版本:
#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);
}
Change the call of scanf below for entering strings by inserting a space in the beginning of the format string.通过在格式字符串的开头插入空格来更改下面的 scanf 调用以输入字符串。 For example instead of this call
例如,而不是这个电话
scanf_s("%[^\n]s", person.Surname, 100);
(where the letter s
must be removed from the format string) write (其中字母
s
必须从格式字符串中删除)写
scanf_s(" %[^\n]", person.Surname, ( rsize_t )100);
^^^^^^^^
This allows to skip leading white space characters in the input buffer.这允许跳过输入缓冲区中的前导空白字符。
Pay attention to that changing the condition or the for loop the was as you are doing注意改变条件或 for 循环就像你正在做的那样
for (i = 0; i < n; i++) {
//...
if (r == 1)
n = n + 1;
}
makes the code unclear.使代码不清楚。 Instead of the for loop you could use do-while loop.
代替 for 循环,您可以使用 do-while 循环。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.