简体   繁体   English

文件到字符串数组(逐行)

[英]File to array of strings (line by line)

I have text file and I want to save each line to array of strings (global defined as fileA ). 我有文本文件,我想将每一行保存到字符串数组(全局定义为fileA )。 All I know is that all rows in file are shorter then 101 characters. 我所知道的是文件中的所有行都短于101个字符。 I made 3 functions: 我做了3个功能:

  • char * lineToString(char * filename, int line) - return value of selected line char * lineToString(char * filename, int line) - 返回所选行的值
  • int getLineCount(char * filename) - return number of lines in file (counting form 1) int getLineCount(char * filename) - 返回文件中的行数(计数形式1)
  • char * fileToArray(char * filename) - return array of strings char * fileToArray(char * filename) - 返回字符串数组

I think this functions work as they should, problem is somewhere in main() . 我认为这个函数可以正常工作,问题出在main() I had printed sizeof(...) just for debugging. 我打印sizeof(...)只是为了调试。 Also there is many warnings in my code, how can I fix them? 我的代码中还有很多警告,我该如何修复它们?

Thanks! 谢谢!

Code: 码:


#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;
}

Console: 安慰:

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)

There are routines in the standard libraries that you should consider using. 您应该考虑使用标准库中的例程。

I try to use functions in the standard libraries rather than writing my own equivalents unless absolutely necessary. 除非绝对必要,否则我尝试使用标准库中的函数而不是编写自己的等价函数。 The functions in the libraries are almost certainly better than anything I would write -- unless I was in the business of writing code for standard libraries. 库中的函数几乎肯定比我写的任何东西都要好 - 除非我是在为标准库编写代码。

I am a little rusty on C, my preferences today are C++ and C#. 我在C上有点生疏,今天我的偏好是C ++和C#。 Sorry if there are some grammatical errors in the pseudo code below. 很抱歉,如果下面的伪代码中存在一些语法错误。

Opening and closing a file for each read of a line is very inefficient. 为每次读取行打开和关闭文件效率非常低。

Here are some functions of interest 以下是一些感兴趣的功能

getline -- see How to explain the parameters of getline() in C -- is a workhorse for such tasks. getline - 请参阅如何解释C中getline()的参数 - 是这类任务的主力。 It will automagically allocate just enough storage for a line. 它将自动为线路分配足够的存储空间。

rewind -- see http://www.tutorialspoint.com/c_standard_library/c_function_rewind.htm 倒带 - 请参阅http://www.tutorialspoint.com/c_standard_library/c_function_rewind.htm

feof -- detect end of file on a stream, see http://www.tutorialspoint.com/c_standard_library/c_function_feof.htm feof - 检测流上的文件结尾,请参阅http://www.tutorialspoint.com/c_standard_library/c_function_feof.htm

Pseudo code -- not tested: 伪代码 - 未测试:

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

One problem I see is that you need to move the line 我看到的一个问题是你需要移动线

        if(currChar == '\n') currLine++;

inside the while loop. 在while循环中。

I see a few more problems that I will be able to describe when I am on a full fledged computer, not a tablet. 当我使用完整的计算机而不是平板电脑时,我会看到一些我能够描述的问题。

Update 更新

You have 你有

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;
}

Problems with this function: 这个功能有问题:

  1. The return value of char* is not compatible with the return statement return array; char*的返回值与return语句return array;不兼容return array; . array can be treated as char (*)[MAX_ROW_LENTH] , but not char* . array可以被视为char (*)[MAX_ROW_LENTH] ,但不能被视为char*

  2. Even if the return type and return statements were made to match, the main problem is that you are trying to return a pointer to an object that will be deleted when the function returns. 即使返回类型和返回语句匹配,主要问题是您正在尝试返回指向将在函数返回时将被删除的对象的指针。 The pointer will be invalid in the calling function. 指针在调用函数中无效。

  3. The line 这条线

      strcpy(array[i], lineToString(filename, i)); 

    should be 应该

      strcpy(array[i-1], lineToString(filename, i)); 

    since array indexing in C starts with 0 , not 1 . 因为C中的数组索引从0开始,而不是1

Other problems: 其他问题:

  1. You are allocating memory for string in lineToString but you are not deallocating it. 您正在为lineToString string分配内存,但您没有取消分配它。

  2. You are allocating memory for fileA in main but you are not deallocating it. 您分配内存fileAmain ,但你是不是重新分配它。

The following versions of fileToArray and main worked with my testing. 以下版本的fileToArraymain于我的测试。 I tried keep your code as much possible and modified what I thought was absolutely essential. 我尽可能地保留你的代码并修改我认为绝对必要的代码。

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 The comments made by James R Matey in his answer are very valid. PS James R Matey在答案中提出的意见非常有效。 It's expensive to open and close a file just to get one line of text. 打开和关闭文件只是为了获得一行文本是昂贵的。 I hope you find a way to incorporate his suggestions in your code. 我希望你能找到一种方法将他的建议融入你的代码中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM