C 防止超过30个字符的输入
嗨,我的代码有问题。我需要它运行,这样,如果用户为“fileName”变量输入超过30个字符,它将“return”;但是下面的代码不起作用。有什么想法吗C 防止超过30个字符的输入,c,C,嗨,我的代码有问题。我需要它运行,这样,如果用户为“fileName”变量输入超过30个字符,它将“return”;但是下面的代码不起作用。有什么想法吗 FILE *packetFile; //initialize file handle char fileName[30]; //initialize int i; int length = 0; length = strlen(fileName); getchar(); printf("Please enter a file name (M
FILE *packetFile; //initialize file handle
char fileName[30]; //initialize
int i;
int length = 0;
length = strlen(fileName);
getchar();
printf("Please enter a file name (Maxium 30 characters): ");
fgets(fileName, 30, stdin);
sscanf(fileName, "%s", fileName);
if(fileName[0] == '\n'){
return;
}
if(strlen(fileName) > 30)
return;
if((packetFile = fopen(fileName,"w"))==NULL) {
printf("Unable to open the file: %s\n",fileName);
} else {
printf("%d packets have been saved to file named %s", pCount, &fileName);
for(i=0;i<pCount;i++) {
fprintf(packetFile,"%04i:%04i:%04i:%04i:%s\r\n",pRecords[i].source,pRecords[i].destination,pRecords[i].type,pRecords[i].port,pRecords[i].data);
}
fclose(packetFile);
}
文件*packetFile//初始化文件句柄
字符文件名[30]//初始化
int i;
整数长度=0;
长度=strlen(文件名);
getchar();
printf(“请输入文件名(最多30个字符):”;
fgets(文件名,30,标准输入法);
sscanf(文件名,“%s”,文件名);
如果(文件名[0]='\n'){
返回;
}
如果(strlen(文件名)>30)
返回;
if((packetFile=fopen(文件名,“w”))==NULL){
printf(“无法打开文件:%s\n”,文件名);
}否则{
printf(“%d个数据包已保存到名为“%s”、pCount和fileName”的文件中);
因为(i=0;i多个原因。您只分配了30个字符的空间,因此在您的情况下,strlen
将永远不会返回结果>30
。您在fgets
调用中最多只能读取30个字符
一个可能的解决方案是分配更多的空间开始使用strlen
。另一个解决方案是保持有限的分配,并使用循环从stdin
读取单个字符-如果您没有及时到达换行符,您只需中断并返回即可
在POSIX系统上,getline
提供了一个简洁的解决方案。它读取整行,并返回长度。唯一需要记住的是getline
在堆上分配内存,因此在完成后需要释放内存
大致如下:
char *filename = NULL;
size_t linecap = 0; // These initial values tells getline to allocate as much space as needed
ssize_t linelen = getline(&filename, &linecap, stdin);
if (linelen < 0)
...
if (linelen > 30)
// Treat as error or whatever
free(filename);
char*filename=NULL;
size\u t linecap=0;//这些初始值告诉getline根据需要分配尽可能多的空间
ssize_t linelen=getline(&filename,&linecap,stdin);
if(linelen<0)
...
如果(linelen>30)
//视为错误或任何东西
免费(文件名);
(无耻地从手册页借用)多个原因。您只分配了30个字符的空间,因此在您的情况下,strlen
将永远不会返回结果>30
。您的fgets
调用中最多只能读取30个字符
一个可能的解决方案是分配更多的空间开始使用strlen
。另一个解决方案是保持有限的分配,并使用循环从stdin
读取单个字符-如果您没有及时到达换行符,您只需中断并返回即可
在POSIX系统上,getline
提供了一个简洁的解决方案。它读取整行,并返回长度。唯一需要记住的是getline
在堆上分配内存,因此在完成后需要释放内存
大致如下:
char *filename = NULL;
size_t linecap = 0; // These initial values tells getline to allocate as much space as needed
ssize_t linelen = getline(&filename, &linecap, stdin);
if (linelen < 0)
...
if (linelen > 30)
// Treat as error or whatever
free(filename);
char*filename=NULL;
size\u t linecap=0;//这些初始值告诉getline根据需要分配尽可能多的空间
ssize_t linelen=getline(&filename,&linecap,stdin);
if(linelen<0)
...
如果(linelen>30)
//视为错误或任何东西
免费(文件名);
(无耻地从手册页上借来)太棒了。我该怎么做呢?我需要包括任何专门的图书馆吗@Henrik@Henrik注:getline()
在C语言中不是一个标准函数,但我认为它在POSIX.Brilliant中。我该怎么做呢?我需要为此包含任何特殊的库吗@Henrik@Henrik注:getline()
在C语言中不是一个标准函数,但我认为它在POSIX中。您应该更清楚地说明哪些函数不能按预期/喜欢的方式工作。您应该更清楚地说明哪些函数不能按预期/喜欢的方式工作。鉴于存在长度
为0的异常情况,如果(length&&fileName[length-1]!='\n'){
如果在fgets中输入的长度变为0,则阻止UB?@chux。输入的EOF?如果strlen在fgets中接收EOF,则不要满足,因为它是垃圾。因此,我想保护strlen(length)的值没有意义。同意fgets()
返回NULL表示文件名中的垃圾文件名[0]
可以是\0
带管道的标准输入或键盘,允许输入\0
fgets()
在\n
上停止,但在\0
上不停止。如果大小(文件名)
was 1-但不在您的情况下。@您这样做的目的是输入文件名吗?为什么?鉴于存在length
为0的异常情况,如果(length&&fileName[length-1]!='\n',您认为这样做有用吗{
如果在fgets中输入的长度变为0,则防止UB?@chux。输入的EOF?如果strlen在fgets中接收EOF,则不要满足,因为它是垃圾。因此,我想保护strlen(长度)的值没有意义。同意fgets()
返回NULL表示文件名中的垃圾
可以使用管道\0
标准DIN
或允许输入\0
fgets()
的键盘\n
停止,但不在\0
上。此外,如果大小(文件名)
为1,则不在您的情况下。@chux您这样做是为了输入文件名吗?为什么?