C - 逐行读取文本文件到指针数组,得到 BAD_ACCESS
C - Reading text file line by line to pointer array, getting BAD_ACCESS
我写在Xcode。我的代码应该将文本文件逐行读取到指针数组 *ar[] 中。我使用了一个简单的循环,通过 getc() 将每个字符读取到 c,并将 c 读取到 *ar[i]。如果 c!= '\n' *ar[i] 递增。否则,*ar[i] 和 i 都会递增。为了便于牵引,我在每一步后添加了 'printf'。 问题: 程序将第一行读取到 *ar[0],但是一旦 i 递增到 1,我得到 EXC_BAD_ACCESS (code=2,address=0x10000000000) . MAC 的 VIM 给出总线 error:10。在增量中发生了一些我无法理解的事情。
#include <stdio.h>
#define MAXLINE 10
int main()
{
FILE *file;
int i = 0;
char *ar[MAXLINE];
char c;
file = fopen("/Users/ykeshet/Desktop/lab/alice30.txt", "read");
while ((i < MAXLINE) && ((*ar[i]) = c = getc(file)) != EOF){
if (c != '\n'){
printf("%c",c);
(*ar[i])++;
}
else{
printf("%c",c);
(*ar[i])++;
i++;
}
}
printf("\n");
}
This is the output I get (first line)
That's the variable's state in the debugger:
此处说明错误:
char *ar[MAXLINE];
这声明了一个数组 MAXLINE
指向 char
的指针。这些指针保持未初始化状态,它们不指向有效位置,取消引用它们是 未定义的行为。实际上,它们可能指向某个或多或少的 "random" 位置,并且您的操作系统将阻止您写入某些您的进程不允许的地址。
while ((i < MAXLINE) && ((*ar[i]) = c = getc(file)) != EOF){
// ^ undefined behavior
if (c != '\n'){
printf("%c",c);
(*ar[i])++;
为什么要增加 a[i]
指向的字符?您可能想在不存在的 "string" a[i]
应该指向的地方前进一个。您需要 that 的另一个指针,否则您的程序将 "forget" 字符串开始的位置。
遵循基于您的原始结构的工作程序,但使用 fgets
和静态缓冲区。如果您需要动态分配内存,或者如果您出于某种原因坚持逐个字符地读取,这将留作练习。
#include <stdio.h>
#define MAXLINE 10
#define LINEBUFSIZE 1024
int main()
{
FILE *file;
int i = 0;
char ar[MAXLINE][LINEBUFSIZE];
file = fopen("/Users/ykeshet/Desktop/lab/alice30.txt", "r");
if (!file) return 1;
while ((i < MAXLINE)
{
// read in next "line" by giving a pointer to the
// first element as buffer for fgets():
if (!fgets(&(arr[i++][0]), LINEBUFSIZE, file)) break;
}
fclose(file);
// i now holds the number of lines actually read.
return 0;
}
Felix Palmen 说了什么但也注意到这一行:
file = fopen("/Users/ykeshet/Desktop/lab/alice30.txt", "read");
在 fopen() 的规范中没有 "read" 模式。有 "r"、"r+",但没有 "read"。
http://www.cplusplus.com/reference/cstdio/fopen/
我正在使用 GCC 5.3.0 并尝试使用 "read" 打开文件会破坏程序,因此您可能需要小心。
这一行:
char *ar[MAXLINE];
声明一个包含 10 个指向 char 的指针的数组。
但是,这些指针从未设置为指向某些内存
但这与代码将输入读入该指针数组的问题无关紧要。
它应该将输入读入指针指向的位置,但是这要求指针实际指向应用程序拥有的内存。
以下:
- 干净地编译
- 正确检查错误(但并不总是正确处理它们,因为代码应该在 any/every 退出点
处清理
- 记录包含每个头文件的原因
- 缩进代码以提高我们人类的可读性
- 为了便于阅读,应用适当的水平间距
- 为了可读性,通过单个空行分隔代码块
- 仅在使用变量时(或之前)声明变量。
- 使用源代码文件
untitled1.c
作为输入。
- 使用
#define
语句为任何 'magic' 数字赋予有意义的名称。
- 如果行太长或行太多或遇到 EOF,'while()' 循环将退出
- 使用有效的第二个参数调用
fopen()
。
以下代码是实现功能的一种方法::
#include <stdio.h> // fopen(), fclose(), perror(), printf(), putc()
#include <stdlib.h> // exit(), EXIT_FAILURE, malloc(), free()
// prototypes
void cleanup( FILE *fp, char **ar );
#define MAXLINE 100
#define MAX_LEN 100
int main( void )
{
char **ar = calloc( MAXLINE, sizeof( char* ) );
for( size_t i=0; i<MAXLINE; i++)
{
ar[i] = malloc( MAX_LEN );
if( !ar[i] )
{ // then malloc failed
perror( "malloc failed" );
cleanup( NULL, ar );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
}
FILE *fp = fopen("untitled1.c", "r");
if( !fp )
{ // then fopen failed
perror( "fopen failed" );
cleanup( fp, ar );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
size_t col = 0; // 'size_t' because value will never be <0
size_t row = 0; // "
int c;
while ( (row < MAXLINE)
&& (col < MAX_LEN )
&& ( (c = getc(fp)) != EOF) )
{
if (c != '\n')
{ // normal char read
ar[row][col] = (char)c;
col++;
}
else
{ // newline read
// terminate the row
ar[row][col] = '[=11=]';
row++; // step to next row
col = 0; // reset to first column of new row
}
// echo byte read from file to terminal
printf("%c",c);
}
putc('\n', stdout);
cleanup( fp, ar );
} // end function: main
void cleanup( FILE *fp, char **ar )
{
if( NULL != fp )
{
fclose( fp );
}
for( size_t i = 0; i < MAXLINE; i++ )
{
free( ar[i] );
}
} // end function: cleanup
我写在Xcode。我的代码应该将文本文件逐行读取到指针数组 *ar[] 中。我使用了一个简单的循环,通过 getc() 将每个字符读取到 c,并将 c 读取到 *ar[i]。如果 c!= '\n' *ar[i] 递增。否则,*ar[i] 和 i 都会递增。为了便于牵引,我在每一步后添加了 'printf'。 问题: 程序将第一行读取到 *ar[0],但是一旦 i 递增到 1,我得到 EXC_BAD_ACCESS (code=2,address=0x10000000000) . MAC 的 VIM 给出总线 error:10。在增量中发生了一些我无法理解的事情。
#include <stdio.h>
#define MAXLINE 10
int main()
{
FILE *file;
int i = 0;
char *ar[MAXLINE];
char c;
file = fopen("/Users/ykeshet/Desktop/lab/alice30.txt", "read");
while ((i < MAXLINE) && ((*ar[i]) = c = getc(file)) != EOF){
if (c != '\n'){
printf("%c",c);
(*ar[i])++;
}
else{
printf("%c",c);
(*ar[i])++;
i++;
}
}
printf("\n");
}
This is the output I get (first line)
That's the variable's state in the debugger:
此处说明错误:
char *ar[MAXLINE];
这声明了一个数组 MAXLINE
指向 char
的指针。这些指针保持未初始化状态,它们不指向有效位置,取消引用它们是 未定义的行为。实际上,它们可能指向某个或多或少的 "random" 位置,并且您的操作系统将阻止您写入某些您的进程不允许的地址。
while ((i < MAXLINE) && ((*ar[i]) = c = getc(file)) != EOF){
// ^ undefined behavior
if (c != '\n'){
printf("%c",c);
(*ar[i])++;
为什么要增加 a[i]
指向的字符?您可能想在不存在的 "string" a[i]
应该指向的地方前进一个。您需要 that 的另一个指针,否则您的程序将 "forget" 字符串开始的位置。
遵循基于您的原始结构的工作程序,但使用 fgets
和静态缓冲区。如果您需要动态分配内存,或者如果您出于某种原因坚持逐个字符地读取,这将留作练习。
#include <stdio.h>
#define MAXLINE 10
#define LINEBUFSIZE 1024
int main()
{
FILE *file;
int i = 0;
char ar[MAXLINE][LINEBUFSIZE];
file = fopen("/Users/ykeshet/Desktop/lab/alice30.txt", "r");
if (!file) return 1;
while ((i < MAXLINE)
{
// read in next "line" by giving a pointer to the
// first element as buffer for fgets():
if (!fgets(&(arr[i++][0]), LINEBUFSIZE, file)) break;
}
fclose(file);
// i now holds the number of lines actually read.
return 0;
}
Felix Palmen 说了什么但也注意到这一行:
file = fopen("/Users/ykeshet/Desktop/lab/alice30.txt", "read");
在 fopen() 的规范中没有 "read" 模式。有 "r"、"r+",但没有 "read"。
http://www.cplusplus.com/reference/cstdio/fopen/
我正在使用 GCC 5.3.0 并尝试使用 "read" 打开文件会破坏程序,因此您可能需要小心。
这一行:
char *ar[MAXLINE];
声明一个包含 10 个指向 char 的指针的数组。
但是,这些指针从未设置为指向某些内存
但这与代码将输入读入该指针数组的问题无关紧要。 它应该将输入读入指针指向的位置,但是这要求指针实际指向应用程序拥有的内存。
以下:
- 干净地编译
- 正确检查错误(但并不总是正确处理它们,因为代码应该在 any/every 退出点 处清理
- 记录包含每个头文件的原因
- 缩进代码以提高我们人类的可读性
- 为了便于阅读,应用适当的水平间距
- 为了可读性,通过单个空行分隔代码块
- 仅在使用变量时(或之前)声明变量。
- 使用源代码文件
untitled1.c
作为输入。 - 使用
#define
语句为任何 'magic' 数字赋予有意义的名称。 - 如果行太长或行太多或遇到 EOF,'while()' 循环将退出
- 使用有效的第二个参数调用
fopen()
。
以下代码是实现功能的一种方法::
#include <stdio.h> // fopen(), fclose(), perror(), printf(), putc()
#include <stdlib.h> // exit(), EXIT_FAILURE, malloc(), free()
// prototypes
void cleanup( FILE *fp, char **ar );
#define MAXLINE 100
#define MAX_LEN 100
int main( void )
{
char **ar = calloc( MAXLINE, sizeof( char* ) );
for( size_t i=0; i<MAXLINE; i++)
{
ar[i] = malloc( MAX_LEN );
if( !ar[i] )
{ // then malloc failed
perror( "malloc failed" );
cleanup( NULL, ar );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
}
FILE *fp = fopen("untitled1.c", "r");
if( !fp )
{ // then fopen failed
perror( "fopen failed" );
cleanup( fp, ar );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
size_t col = 0; // 'size_t' because value will never be <0
size_t row = 0; // "
int c;
while ( (row < MAXLINE)
&& (col < MAX_LEN )
&& ( (c = getc(fp)) != EOF) )
{
if (c != '\n')
{ // normal char read
ar[row][col] = (char)c;
col++;
}
else
{ // newline read
// terminate the row
ar[row][col] = '[=11=]';
row++; // step to next row
col = 0; // reset to first column of new row
}
// echo byte read from file to terminal
printf("%c",c);
}
putc('\n', stdout);
cleanup( fp, ar );
} // end function: main
void cleanup( FILE *fp, char **ar )
{
if( NULL != fp )
{
fclose( fp );
}
for( size_t i = 0; i < MAXLINE; i++ )
{
free( ar[i] );
}
} // end function: cleanup