我的代码是尝试自学C.这是我学习Java时所做的游戏的修改。我的游戏的目标是采取一个巨大的5049 x 1文字文件。随机选择一个单词,混淆它并尝试猜测它。我知道如何做到这一切。所以无论如何,文本文件的每一行都包含一个单词:
5049
must
lean
better
program
now
...
所以,我在C中创建了一个字符串数组,试图读取这个字符串数组并将其放入C.我没有做任何其他事情。一旦我将文件放入C,其余的应该很容易。更奇怪的是,它符合它。当我使用./blah
命令运行它时出现问题。
我得到的错误很简单。它说:
zsh: bus error ./blah
我的代码如下。我怀疑它可能与内存或溢出缓冲区有关,但这是完全不科学和直觉。所以我的问题很简单,为什么这个C代码给我这个总线错误消息?
#include<stdio.h>
#include<stdlib.h>
//Preprocessed Functions
void jumblegame();
void readFile(char* [], int);
int main(int argc, char* argv[])
{
jumblegame();
}
void jumblegame()
{
//Load File
int x = 5049; //Rows
int y = 256; //Colums
char* words[x];
readFile(words,x);
//Define score variables
int totalScore = 0;
int currentScore = 0;
//Repeatedly pick a random work, randomly jumble it, and let the user guess what it is
}
void readFile(char* array[5049], int x)
{
char line[256]; //This is to to grab each string in the file and put it in a line.
FILE *file;
file = fopen("words.txt","r");
//Check to make sure file can open
if(file == NULL)
{
printf("Error: File does not open.");
exit(1);
}
//Otherwise, read file into array
else
{
while(!feof(file))//The file will loop until end of file
{
if((fgets(line,256,file))!= NULL)//If the line isn't empty
{
array[x] = fgets(line,256,file);//store string in line x of array
x++; //Increment to the next line
}
}
}
}
答案 0 :(得分:3)
这一行存在一些问题:
array[x] = fgets(line,256,file);//store string in line x of array
您已经在前一个if
语句的条件下阅读了该行:您要操作的当前行在缓冲区中已经已经了您使用fgets
获取下一行行。
您每次尝试分配到同一个数组插槽时:相反,您需要为数组索引保留一个单独的变量,每次循环都会增加。
最后,您尝试使用=
复制字符串。这只会复制引用,它不会创建字符串的新副本。因此,数组的每个元素都将指向同一个缓冲区:line
,它将超出范围,并在函数退出时变为无效。要使用字符串填充array
,您需要为数组创建每个字符串的副本:使用malloc
为每个新字符串分配空间,然后使用strncpy
复制每个line
x
1}}到你的新字符串。或者,如果您可以使用strdup
,则需要为您分配空间。
但我怀疑这是导致总线错误的原因:您将数组 size 作为array[x]
传入,并且在循环中,您将分配给{{ 1}}。这个问题是array[x]
不属于数组,数组只有0
到(x - 1)
的可用索引。
答案 1 :(得分:2)
您传递的值为5049。第一次该行
array[x] = ...
执行,它正在访问一个不存在的数组位置。
看起来你正在学习C.太棒了!您需要掌握的技能是基本的调试器使用。在这种情况下,如果使用
编译程序gcc -g myprogram.c -o myprogram
然后用
运行它gdb ./myprogram
(我假设Linux),您将获得一个堆栈转储,显示发生总线错误的行。这应该足以帮助您自己找出错误,从长远来看,这比询问其他错误要好得多。
调试器有许多其他方法可用,但这在列表中很高。它为您提供了一个运行程序的窗口。
答案 2 :(得分:0)
您将行存储在行缓冲区中,该行缓冲区在readFile函数内定义,并在arary中存储指向它的指针。有两个问题:每次读取新字符串并且缓冲区在堆栈中时,您将覆盖该值,并且在函数返回后无效。
答案 3 :(得分:0)
char* array[5049], int x
array[x] = fgets(line,256,file)
您分配给array [x],这是一个长度为1的内存位置,您指定一个指针(4个字节)。
另一方面,你读了256次256字节,你就失去了前256位。
但是最大的错误是你把最后的条件!feof(),它检查字符串数组的限制是否溢出。
答案 4 :(得分:0)
你至少有一些问题:
array[x] = fgets(line,256,file)
这会将line
的地址存储到每个数组元素中。当line
返回时,readFile()
不再有效,因此您将拥有一系列无用的指针。即使line
具有更长的生命周期,让所有数组元素具有相同的指针也是没有用的(它们每个只指向最后一次写入缓冲区的内容)
while(!feof(file))
这是一个用于读取文件的反模式。请参阅http://c-faq.com/stdio/feof.html和"Using feof() incorrectly"。这个反模式可能会导致您的程序循环超出读取文件时的预期。
你分配数组来保存5049个指针,但你只需读取文件中的多少 - 没有检查你是否读取了预期的数字或防止读取太多。您应该考虑在读取文件时动态分配数组,或者考虑使用一种机制来确保您读取正确数量的数据(不是太少而不是太多),并在错误时处理错误。
答案 5 :(得分:-1)
我怀疑问题出在(fgets(line,256,file))!=NULL)
。阅读文件的更好方法是使用fread()
(请参阅http://www.cplusplus.com/reference/clibrary/cstdio/fread/)。指定FILE*
(C中的文件流),缓冲区大小和缓冲区。例程返回读取的字节数。如果返回值为零,则表示已达到EOF。
char buff [256];
fread (file, sizeof(char), 256, buff);