C 使用fgets()从文件中读取多行并存储到指针数组
我正在尝试在“批处理文件模式”上实现一个自定义shell。假设我有一个名为“batchfile”的文件,其中包含:C 使用fgets()从文件中读取多行并存储到指针数组,c,bash,shell,pointers,fgets,C,Bash,Shell,Pointers,Fgets,我正在尝试在“批处理文件模式”上实现一个自定义shell。假设我有一个名为“batchfile”的文件,其中包含: ls –l pwd ps touch hello ls -l ; cat file ; grep foo file2 ls -l && cat file quit 调用/myShell batchfile,我想分别执行这些命令。但是,当我尝试使用fgets()读取文件中的行,然后将它们存储到数组(char*batch\u cmds[512])时,我得到: 分段故障
ls –l
pwd
ps
touch hello
ls -l ; cat file ; grep foo file2
ls -l && cat file
quit
调用/myShell batchfile
,我想分别执行这些命令。但是,当我尝试使用fgets()
读取文件中的行,然后将它们存储到数组(char*batch\u cmds[512]
)时,我得到:
分段故障(堆芯转储)
这是我目前的代码:
int main(int argc, char *argv[]){
if (argc >=2){
char str[512];
char *batch_cmds[512];
int i=0;
FILE *fp;
fp = fopen(argv[1], "r");
while(fgets(str,512, fp)!=NULL){
strcpy(batch_cmds[i], str);
i++;
}
fclose(fp);
我无法理解为什么会弹出此错误。您为指针本身保留了空间,但不是为每个指针指向的每个字符串保留空间。每个
batch\u cmds[i]
都指向“某处”,至少不指向您分配的对象;然后调用strcpy(批处理cmds[i],str)
,您将str
的内容写入“某处”,并产生未定义的行为(例如,崩溃;实际上语句batch\u cmds[i]
访问未初始化的数组,并且本身已经是未定义的行为;但仅此一项就很少导致崩溃)
而不是
strcpy(batch_cmds[i], str);
写
命令strdup
执行两项操作:(1)保留足够大的内存以容纳str
的内容;(2)然后复制str
的内容。这相当于batch_cmds[i]=malloc(strlen(str)+1);strcpy(批处理cmds[i],str))代码>
此外,检查i
是否为行:
char *batch_cmds[512];
声明一个包含512个指向char
的指针的数组,但这些指针未初始化(野生、悬空、随意选择)
您的选择:
在堆栈上声明二维数组:
char batch_cmds[512][512];
使用动态内存管理在堆上分配字符串:
char *batch_cmds[512];
int i;
for(i = 0; i < 512; i++)
{
batch_cmds[i] = malloc(string_length);
if(batch_cmds[i] == NULL)
{
// handle alloc error
}
}
// Code that uses batch_cmds...
for(i = 0; i < 512; i++)
{
free(batch_cmds[i]);
batch_cmds[i] = NULL;
}
char*batch_cmds[512];
int i;
对于(i=0;i<512;i++)
{
批处理cmds[i]=malloc(字符串长度);
if(批处理cmds[i]==NULL)
{
//句柄分配错误
}
}
//使用batch_cmds的代码。。。
对于(i=0;i<512;i++)
{
免费(批处理单元cmds[i]);
batch_cmds[i]=NULL;
}
使用strdup
为batch_cmds
中的char
指针赋值(如Stephan Lechner的回答所示)。请注意,strdup
也在后台使用堆内存,因此在使用完返回的指针后,还必须将其传递给free
,以避免内存泄漏
您没有为batch\u cmds
分配任何内存,因此(例如)batch\u cmds[0]
没有指向内存中存储字符串的有效位置。C使用旧式堆栈/堆内存管理,因此您需要了解指针和malloc的工作方式。@ChrisTurner是正确的,batch\u cmds是一个不指向任何内容的指针,您需要管理内存或静态分配内存,我建议您在成功读取一行时使用链表并分配每个节点。非常感谢。无法更好地解释它。它工作得很好。
char *batch_cmds[512];
int i;
for(i = 0; i < 512; i++)
{
batch_cmds[i] = malloc(string_length);
if(batch_cmds[i] == NULL)
{
// handle alloc error
}
}
// Code that uses batch_cmds...
for(i = 0; i < 512; i++)
{
free(batch_cmds[i]);
batch_cmds[i] = NULL;
}