C 由于使用fgets()将文件中的行读取到结构数组中而导致的分段错误
我目前正在学习C语言,需要一些代码方面的帮助 假设有一个名为“books.txt”的文件,它在文件的新行中包含多本书的名称。我正试图抓取每本书的名字,以便在我的程序的其余部分使用 为此,我创建了以下内容:C 由于使用fgets()将文件中的行读取到结构数组中而导致的分段错误,c,arrays,struct,segmentation-fault,C,Arrays,Struct,Segmentation Fault,我目前正在学习C语言,需要一些代码方面的帮助 假设有一个名为“books.txt”的文件,它在文件的新行中包含多本书的名称。我正试图抓取每本书的名字,以便在我的程序的其余部分使用 为此,我创建了以下内容: struct bookData { // This is my struct to encapsulate book information char name[50]; // Name of book // Other struct variable // Ot
struct bookData { // This is my struct to encapsulate book information
char name[50]; // Name of book
// Other struct variable
// Other struct variable
};
现在我需要获得每本书的名称,并将它们放入结构数组中。下面是我如何做到这一点的
struct bookData booksList[numBooks]; // numBooks is the number of books in "books.txt"
int i;
for(i = 0; i < numBooks; i++) {
fgets(booksList[i].name, 50, books);
// Books is the "books.txt" file that was opened for reading
}
如果没有for循环,就不会发生错误,代码可以正常运行并打印书籍的名称
我试图理解为什么我的代码中会出现错误。如果有人能给我一些关于如何修正错误的建议,我将不胜感激。提前感谢您抽出时间阅读/回答我的问题
编辑:numBooks本质上是“books.txt”文件中的行数。这就转化为这个问题的书的数量。numBooks是使用以下代码计算的:
char c;
int numBooks;
while((c = fgetc(books)) != EOF) {
if(c == '\n') {
numBooks++;
}
}
编辑#2:谢谢大家的帮助 以下代码是错误的,可以合理预期会导致问题:
char c;
int numBooks;
while((c = fgetc(books)) != EOF) {
if(c == '\n') {
numBooks++;
}
}
首先,numBooks
是未初始化的,以后使用它可能会调用未定义的行为
其次,尽管在大多数系统上引起问题的可能性要小得多,fgetc
返回int
,它通常具有更宽的域(可以表示比无符号字符更多的值)。这样做是有原因的。fgetc
返回的任何实际字符值将作为无符号字符
(即仅为正数)值。故障将导致EOF
(仅为负值)。这意味着fgetc
通常可以返回257个值中的一个,通过直接转换为char
您将丢弃其中一个值:错误处理值。换句话说,您无法再判断fgetc
是否成功。当您达到EOF
时会发生什么情况?将其转换为字符
,将其视为字符值(如果不是),然后重试。。?回答错了
总之,fgetc
返回int
,因此将返回值存储在int
中
当numBooks
达到INT_MAX
和numBooks++时,会出现另一个问题代码>将导致溢出。从技术上讲,这是未定义的行为,理论上可能导致分段错误。。。但我从未亲眼见过。尽管如此,您可能应该使用无符号
类型,因为文件中的条目数为负数是没有意义的,不是吗
仔细想想,如果structbookdatabookslist[numBooks]中的numBooks
如果代码>为负数(或足够大),当您访问更高的元素时,您可能会开始看到分段冲突
总之:当您只希望看到正数时,请使用无符号类型;对于大型数组,请使用动态分配(例如malloc
)
请注意,这并没有涵盖所有的可能性,因为您没有提供详细的说明,因此不可能/不实际地这样做;您的segfault很可能是由您未提供的其他代码引起的。如果你更新了这个问题,请告诉我,这样我就可以更新这个答案,让世界继续旋转:)什么是numBooks
?如何检索它的值?为什么不使用调试器并找出哪行代码产生了错误?如果booklist在堆栈上并且numbooks很大,那么您可能会在某个地方耗尽堆栈空间。或者,在返回后,堆栈上的数据将消失,但您返回了指向它的指针。我将打印出numbooks
的值。我也会在你们读的时候把每一行都打印出来,看看你们在撞车前能走多远。你们都很好!这是麻木书的问题。正如保罗·奥格尔维先生所说,书单最终太大了,因为麻木书是不正确的。非常感谢大家!非常感谢您的详细解释!这真的帮助我了解了发生了什么。我打印了numBooks,发现它返回了一个非常荒谬的数字。(当时是4195735。)我现在将努力修复代码的这一部分。确实是个奇怪的数字<代码>整数最大值
或者整数最大值
<代码>整数最小值
可能被转换成一个无符号整数
?嗯……您忘记了主要问题:numBooks
未初始化且具有自动存储,这就是segfault背后的原因。@LPs:您可能应该将其作为一个答案发布。这一条解决了许多不太可能导致cae问题的次要质量问题,并省略了这一关键错误,而这一错误肯定是导致cae问题的原因。@LPs感谢您提供的额外细节。我错过了!哦!
char c;
int numBooks;
while((c = fgetc(books)) != EOF) {
if(c == '\n') {
numBooks++;
}
}