我有文本文件,我想将每一行保存到字符串数组(全局定义为fileA
)。我所知道的是文件中的所有行都短于101个字符。我做了3个功能:
char * lineToString(char * filename, int line)
- 返回所选行的值int getLineCount(char * filename)
- 返回文件中的行数(计数形式1)char * fileToArray(char * filename)
- 返回字符串数组我认为这些功能可以正常工作,问题出现在main()
中。我打印sizeof(...)
只是为了调试。我的代码中还有很多警告,我该如何修复它们?
谢谢!
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int MAX_LINES = 1000; //0 <= x && x < 1000
int MAX_ROW_LENGTH = 101; //100 + 1 ('\0')
char * fileA = NULL;
char * lineToString(char * filename, int line){
FILE * file = fopen(filename, "r");
int currLine = 1;
int currCol = 0;
char currChar;
char * string = (char *) malloc(sizeof(char)*MAX_ROW_LENGTH);
string[0] = '\0';
if(file != NULL && line >= 1){
while((currChar = getc(file)) != EOF){
if(currLine == line){
if(currChar == '\n'){
string[currCol] = '\0';
break;
}else{
string[currCol] = currChar;
currCol++;
}
}
if(currChar == '\n') currLine++;
}
fclose(file);
}
return string;
}
int getLineCount(char * filename){
FILE * file = fopen(filename, "r");
int count = 0;
char c;
if(file != NULL){
while((c = getc(file)) != EOF)
if(c == '\n') count++;
fclose(file);
}
return count;
}
char * fileToArray(char * filename){
int i;
int lineCount = getLineCount(filename);
char array[lineCount][MAX_ROW_LENGTH];
for(i = 1; i <= lineCount; i++){
strcpy(array[i], lineToString(filename, i));
//printf("%s\n", array[i]);
}
printf("%d\n",sizeof(array));
return array;
}
int main(int argc, char **argv){
fileA = (char *) malloc(sizeof(fileToArray(argv[1])));
strcpy(fileA, fileToArray(argv[1]));
printf("%d\n", (int) sizeof(fileA));
int i;
for(i = 0; i < (int) sizeof(fileA); i++){
printf("%s\n", fileA[i]);
}
return 0;
}
控制台:
matjazmav:~/FRI13_14/SE02/P2/DN/DN08$ gcc 63130148-08.c -o 63130148-08
63130148-08.c: In function ‘fileToArray’:
63130148-08.c:58:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat]
63130148-08.c:59:2: warning: return from incompatible pointer type [enabled by default]
63130148-08.c:59:2: warning: function returns address of local variable [enabled by default]
63130148-08.c: In function ‘main’:
63130148-08.c:69:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]
matjazmav:~/FRI13_14/SE02/P2/DN/DN08$ ./63130148-08 input-1a input-1b
808
8
Segmentation fault (core dumped)
答案 0 :(得分:2)
您应该考虑使用标准库中的例程。
我尝试使用标准库中的函数,而不是编写我自己的等价物,除非绝对必要。库中的函数几乎肯定比我写的任何东西都要好 - 除非我从事为标准库编写代码的工作。
我对C有点生疏,今天我的偏好是C ++和C#。很抱歉,如果下面的伪代码中存在一些语法错误。
为每次读取一行打开和关闭文件的效率非常低。
以下是一些感兴趣的功能
getline - 请参阅How to explain the parameters of getline() in C - 是此类任务的主力军。它将自动为线路分配足够的存储空间。
快退 - 请参阅http://www.tutorialspoint.com/c_standard_library/c_function_rewind.htm
feof - 检测流上的文件结尾,请参阅http://www.tutorialspoint.com/c_standard_library/c_function_feof.htm
伪代码 - 未经测试:
FILE fileHandle;
fileHandle = fopen(filename, "r");
if (! fileHandle) yourErrorExit();
// Count the lines -- there may be a system call that will do this more efficiently
int fileLengthInLines = 0;
char *lineBuffer = (char*)malloc(sizeOf(char) * maximumSizeOfLine]);
int bytesRead;
while (! feof(fileHandle)) {
int err;
err = getline(&lineBuffer, &bytesRead, filehandle) // ignore the string returned
if (!err) ; // process error appropriately
fileLengthInLines ++; // this gives you your length of file in lines
}
free(lineBuffer); // we won't use it again
// allocate your array
char **stringArray;
stringArray = (char**) malloc(sizeof(char*)*fileLengthInLines);
rewind(fileHandle); // get back to start of file
// Read lines and store
int lineNumber = 0;
char *getlineBuffer = NULL; // to force getline to allocate
int lineLength;
while (! feof(fileHandle)) {
if (! (lineLength = getline(&getLineBuffer, 0, fileHandle))) ; // process error
stringArray[lineNumber] = getLineBuffer;
getLineBuffer = NULL; // to force getline to allocate on next iteration
lineNumber++;
}
fclose(fileHandle);
// Check that all lines are processed -- compare fileLengthInLines with lineNumber
// Be sure to deallocate stringArray and its strings when you are done
答案 1 :(得分:1)
我看到的一个问题是你需要移动线
if(currChar == '\n') currLine++;
在while循环中。
当我使用成熟的电脑而不是平板电脑时,我会看到一些我能够描述的问题。
<强>更新强>
你有
char * fileToArray(char * filename){
int i;
int lineCount = getLineCount(filename);
char array[lineCount][MAX_ROW_LENGTH];
for(i = 1; i <= lineCount; i++){
strcpy(array[i], lineToString(filename, i));
//printf("%s\n", array[i]);
}
printf("%zu\n",sizeof(array));
return array;
}
此功能存在问题:
char*
的返回值与return语句return array;
不兼容。 array
可以视为char (*)[MAX_ROW_LENTH]
,但不能视为char*
。
即使返回类型和返回语句匹配,主要问题是您尝试返回指向将在函数返回时删除的对象的指针。指针在调用函数中无效。
该行
strcpy(array[i], lineToString(filename, i));
应该是
strcpy(array[i-1], lineToString(filename, i));
因为C中的数组索引以0
开头,而不是1
。
其他问题:
您正在为string
中的lineToString
分配内存,但您尚未取消分配。
您正在为fileA
中的main
分配内存,但您尚未取消分配。
以下版本的fileToArray
和main
适用于我的测试。我尽可能地保留你的代码并修改我认为绝对必要的代码。
void fileToArray(char * filename, int lineCount, char (*array)[MAX_ROW_LENGTH])
{
int i;
char* string;
for(i = 1; i <= lineCount; i++){
string = lineToString(filename, i);
strcpy(array[i-1], string);
free(string);
}
}
int main(int argc, char **argv)
{
int i;
int lineCount = getLineCount(argv[1]);
char array[lineCount][MAX_ROW_LENGTH];
fileToArray(argv[1], lineCount, array);
for(i = 0; i < lineCount; i++){
printf("%s\n", array[i]);
}
return 0;
}
PS James R Matey在回答中的评论非常有效。打开和关闭文件只是为了获得一行文本是昂贵的。我希望你能找到一种方法将他的建议纳入你的代码中。