由C中的fgets()引起的分段错误
这是一个我不理解的问题-我主要使用的是由C中的fgets()引起的分段错误,c,segmentation-fault,fgets,C,Segmentation Fault,Fgets,这是一个我不理解的问题-我主要使用的是fgets(),它可以工作。我(我认为)在函数中使用它的方式完全相同,我得到一个错误[分段错误核心转储--退出代码139] 这段代码是基于Ivor Horton的《开始C》(这是一个老版本,但我只是想从中学习基础知识)一书中的一个示例程序编写的 我的程序如下所示。我正在使用Geany处理*nix(基本上是用GCC编译)。您可以看到,fgets在main中工作(输出是您输入的字符串)。但它在函数stru in()中不工作。它一直到第二个printf()语句输入
fgets()
,它可以工作。我(我认为)在函数中使用它的方式完全相同,我得到一个错误[分段错误核心转储--退出代码139]
这段代码是基于Ivor Horton的《开始C》(这是一个老版本,但我只是想从中学习基础知识)一书中的一个示例程序编写的
我的程序如下所示。我正在使用Geany处理*nix(基本上是用GCC编译)。您可以看到,fgets
在main中工作(输出是您输入的字符串)。但它在函数stru in()
中不工作。它一直到第二个printf()
语句输入字符串,无需进一步。请注意,在本书中,Horton使用了get()
。我试图在这里实现一个更安全的字符串输入函数,但没有乐趣
顺便说一下,程序应该对存储在字符串指针数组中的字符串进行排序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define MAX_NUM_STRINGS 50
int str_in(char **); /*Pointer to a string pointer*/
void str_sort(char *[], int n); /*Array of pointers to strings, number of strings in array*/
void str_out (char *[], int n); /*Array of pointers to strings, number of strings in array*/
int main(){
char *pS[MAX_NUM_STRINGS] = { NULL }; /*Array of pointers to strings stored in str_space*/
int numStrings = 0; /*Count of strings*/
char buffer[BUFSIZ];
printf("Enter a string\n");
fgets(buffer, BUFSIZ, stdin);
printf("%s", buffer);
printf("fgets works here\n\n");
/* get string input from user - a pointer to each string is saved in pS */
while ( str_in(&pS[numStrings]) && numStrings < MAX_NUM_STRINGS)
numStrings++;
if ( numStrings > 0 ){
str_sort(pS, numStrings);
str_out(pS, numStrings);
}
return 0;
}
int str_in(char** pString){
char buffer[BUFSIZ];
char *p;
printf ("Enter string:\n");
fgets(buffer, 60, stdin);
printf("fgets doesn't work here!!\n");
if( buffer != NULL ){
printf("here");
if ((p = strchr(buffer, '\n')) != NULL)
*p = '\0'; /*replace newline with null character*/
else
return FALSE;
if ( strlen(buffer) > 0 ){
strcpy(*pString, buffer);
return TRUE;
}
else
return FALSE; /*blank line - end of input*/
}
else
return FALSE;
}
void str_sort(char* pStrings[], int n){
/*sort strings by manipulating array of string pointers*/
char *temp;
int sorted = FALSE;
int i = 0;
while (!sorted){
sorted = TRUE;
for(i = 0; i < n - 1; i++){
temp = pStrings[i];
if ( strcmp(temp, pStrings[i+1]) > 1 ){
pStrings[i] = pStrings[i+1];
pStrings[i+1] = temp;
sorted = FALSE;
break;
}
}
}
}
void str_out(char* pStrings[], int n){
/*print strings to standard output. Free memory as each string is printed */
int i = 0;
printf("Sorted strings:\n");
for(i = 0; i < n; i++){
printf("%s", pStrings[i]);
free(pStrings[i]);
}
}
#包括
#包括
#包括
#定义真1
#定义FALSE 0
#定义最大数量字符串50
int str_in(char**);/*指向字符串指针的指针*/
void str_sort(char*[],int n);/*指向字符串的指针数组,数组中的字符串数*/
void str_out(char*[],int n);/*指向字符串的指针数组,数组中的字符串数*/
int main(){
char*pS[MAX_NUM_STRINGS]={NULL};/*指向存储在str_空间中的字符串的指针数组*/
int numStrings=0;/*字符串计数*/
字符缓冲区[BUFSIZ];
printf(“输入字符串”);
fgets(缓冲区、BUFSIZ、标准输入);
printf(“%s”,缓冲区);
printf(“fgets在此工作\n\n”);
/*从用户获取字符串输入-指向每个字符串的指针保存在pS中*/
while(str_in(&pS[numStrings])&&numStrings0){
str_排序(pS,numstring);
stru_out(pS,numStrings);
}
返回0;
}
int str_in(字符**pString){
字符缓冲区[BUFSIZ];
char*p;
printf(“输入字符串:\n”);
fgets(缓冲器,60,标准输入);
printf(“fgets在这里不起作用!!\n”);
if(缓冲区!=NULL){
printf(“此处”);
if((p=strchr(缓冲区,'\n'))!=NULL)
*p='\0';/*用空字符替换换行符*/
其他的
返回FALSE;
如果(strlen(缓冲区)>0){
strcpy(*pString,buffer);
返回TRUE;
}
其他的
返回FALSE;/*空行-输入结束*/
}
其他的
返回FALSE;
}
void str_排序(char*pStrings[],int n){
/*通过操纵字符串指针数组对字符串进行排序*/
字符*温度;
int=FALSE;
int i=0;
而(!排序){
排序=真;
对于(i=0;i1){
pStrings[i]=pStrings[i+1];
pStrings[i+1]=温度;
排序=假;
打破
}
}
}
}
void stru_out(char*pStrings[],int n){
/*将字符串打印到标准输出。打印每个字符串时释放内存*/
int i=0;
printf(“排序字符串:\n”);
对于(i=0;i
您必须检查fgets的返回值,以查看是否已成功接收到某些内容,如果未成功接收,则不应将缓冲区作为字符串使用,因为您不会NUL终止缓冲区
/* Checking for buffer != NULL is of no use */
/* as buffer will always be not NULL since */
/* since you have allocated it as char buffer[BUFSIZ] */
if (fgets(buffer, BUFSIZ, stdin) == NULL) {
/* buffer may not be a valid string */
}
因此,您可以在输入函数时(在声明完成后)立即将缓冲区初始化为NUL字符串
buffer[0] = 0; /* initialize to NUL string */
现在,您可以在任何地方将缓冲区用作字符串
还要注意的是,如果BUFSIZ太大,大于几KB,则可能由于堆栈溢出而导致seg错误。如果它们太大,则可以将缓冲区设置为“静态字符”而不是“字符”。分段错误不是由
fgets()
引起的,而是由strcpy()
引起的:
您试图写入*pString
,但从未为其分配内存。main()
中的pS
只是一个空指针数组
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define MAX_NUM_STRINGS 50
int str_in(char **); /*Pointer to a string pointer*/
void str_sort(char *[], int n); /*Array of pointers to strings, number of strings in array*/
void str_out (char *[], int n); /*Array of pointers to strings, number of strings in array*/
int main(){
char *pS[MAX_NUM_STRINGS] = { NULL }; /*Array of pointers to strings stored in str_space*/
int numStrings = 0; /*Count of strings*/
char buffer[BUFSIZ];
printf("Enter a string\n");
fgets(buffer, BUFSIZ, stdin);
printf("%s", buffer);
printf("fgets works here\n\n");
/* get string input from user - a pointer to each string is saved in pS */
while ( str_in(&pS[numStrings]) && numStrings < MAX_NUM_STRINGS)
numStrings++;
if ( numStrings > 0 ){
str_sort(pS, numStrings);
str_out(pS, numStrings);
}
return 0;
}
int str_in(char** pString){
char buffer[BUFSIZ];
char *p;
printf ("Enter string:\n");
fgets(buffer, 60, stdin);
printf("fgets doesn't work here!!\n");
if( buffer != NULL ){
printf("here");
if ((p = strchr(buffer, '\n')) != NULL)
*p = '\0'; /*replace newline with null character*/
else
return FALSE;
if ( strlen(buffer) > 0 ){
strcpy(*pString, buffer);
return TRUE;
}
else
return FALSE; /*blank line - end of input*/
}
else
return FALSE;
}
void str_sort(char* pStrings[], int n){
/*sort strings by manipulating array of string pointers*/
char *temp;
int sorted = FALSE;
int i = 0;
while (!sorted){
sorted = TRUE;
for(i = 0; i < n - 1; i++){
temp = pStrings[i];
if ( strcmp(temp, pStrings[i+1]) > 1 ){
pStrings[i] = pStrings[i+1];
pStrings[i+1] = temp;
sorted = FALSE;
break;
}
}
}
}
void str_out(char* pStrings[], int n){
/*print strings to standard output. Free memory as each string is printed */
int i = 0;
printf("Sorted strings:\n");
for(i = 0; i < n; i++){
printf("%s", pStrings[i]);
free(pStrings[i]);
}
}
另一件事是使用
if(buffer!=NULL)进行测试
,这永远不会是真的,因为缓冲区是一个数组,而不是指针。我遗漏了什么吗?我没有看到任何字符串的空间被分配。另外:在中,stru in
缓冲区不可能是空的…我认为只有在发生某种非常不寻常的输入错误的情况下,它才会是空的-下面的例子是lowing在这里:@topsail:buffer
是一个数组对象,而不是指针;它衰减为指向其第一个元素的指针,该元素永远不能为null。好的。现在这不是必需的,但看看Sundar下面的注释,如果fgets()返回null,那么null指针不会存储在我的变量缓冲区中吗(即使它没有改变数组中的任何内容)。谢谢。就是这样。事实上,在霍顿的例子中,我漏掉了一行:*pString=(char*)malloc(strlen(buffer)+1);
我有点明白你的意思,但是fgets()在输入中附加一个空字符?因此,只要它没有完全无法从用户处获取输入,它至少应该是一个空字符(可能是一个换行符,后跟一个空字符。根据C标准(第7.19.7.2节)“如果遇到文件结尾,且数组中未读取任何字符,则数组的内容保持不变,并返回空指针”。当返回值为空时,FGET无需追加NUL。