如何从fgets读取的行中获取长度并循环遍历它

3

我正在尝试在fgets中循环每个字符的行,但我遇到了错误,如下所述。

int main(int argc, char* argv[]) {
   char arr[200]
   int currS = sizeof(arr) / sizeof(char);
   // call readIt function

}

void readIt(char* argv[], char arr[], int currS) {
  FILE* file;
  file = NULL;
  file = fopen(argv[1], "r");
  while(fgets(arr, currS, file) != NULL) 
    for (int i = 0; i < sizeof(arr); i++) 
       print each char of current line
}

当我在每一行上使用for循环时,每一行的输出都将是文件中第一行的长度。for循环迭代的次数永远不会改变。我该如何更新它?我查看了其他SO问题,但它们并不是很有帮助。

1
注意:sizeof(char)始终为1。可以简化为int currS = sizeof(arr); - chux - Reinstate Monica
3
考虑使用 POSIX 函数 getline() 替代 fgets(),因为它的一个优点是可以返回行的长度。 - Jonathan Leffler
2个回答

3
readIt()函数中,你需要使用strlen(arr)而不是sizeof arr。后者将会给你一个char *的大小,而这个大小总是相同的,无论它所指向的字符串的长度是多少。
你还应该检查fopen()的返回值是否为NULL,因为fopen()可能因为许多原因而失败。
void readIt(char* argv[], char arr[], int currS) {
    FILE * file = fopen(argv[1], "r");
    if ( file ) {
        while( fgets(arr, currS, file) ) {
            const int len = strlen(arr); 
            for ( int i = 0; i < len; ++i ) {
                // print each char of current line
            }
        }
    }
}

请注意,在这里使用变量 len 意味着你只计算字符串的长度一次,即在开始循环之前,而不是每次通过循环计算它,如果你这样做 for ( int i = 0; i < strlen(arr); ++i )。 如果你只是打印每个字符,那么字符串的长度在调用 fgets() 之间不会改变,因此多次计算它是低效的。
另外,除非出于某种原因你希望在 readIt() 返回后将文件中读取的最后一行包含在 main() 中的数组中,否则你可以更容易地在 readIt() 内部定义 arr,以避免完全传递它到该函数中,例如:
void readIt(char* argv[]) {
    FILE * file = fopen(argv[1], "r");
    if ( file ) {
        char arr[200];
        while( fgets(arr, sizeof arr, file) ) {
            const int len = strlen(arr); 
            for ( int i = 0; i < len; ++i ) {
                // print each char of current line
            }
        }
    }
}

由于arr现在是readIt()函数中的一个实际数组,而不是指向char的指针(你无法将数组传递给函数,只能传递其中一个地址),所以sizeof arr将给出数组的实际大小,而不是char *的大小,因此可以将其传递给fgets()


1
你真是救星啊。我已经调试了三个小时了。感谢你的答案和清晰的解释! - Anthony J

0

这个函数:

void readIt(char* argv[], char arr[], int currS) {
  FILE* file;
  file = NULL;
  file = fopen(argv[1], "r");
  while(fgets(arr, currS, file) != NULL)
    for (int i = 0; i < sizeof(arr); i++)
       print each char of current line
}

最好使用arr[]中实际字符数进行编写
建议使用大括号,以避免未来维护困难
建议使用垂直间距以提高可读性
建议使用注释以避免未来维护困难

void readIt(char* argv[], char arr[], int currS)
{
    FILE* file = NULL;

    if( NULL == (file = fopen(argv[1], "r") ) )
    { // then fopen failed
        perror( "fopen failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    // read line from file and echo to user
    // note: file lines are considered to be terminated by either a NUL char or newline or EOF
    //       fgets() assures the line in arr[] has a NUL char termination
    while( fgets(arr, currS, file) )
    {
        int len = strlen(arr);  // returns offset to NUL char

        // use following if do not want to echo a newline read from the file
        if( '\n' == arr[strlen(arr)-1])
        {
            arr[strlen(arr)-1] = '\0';
            len--;
        } // end if

        printf( "\nNumber of characters in line: %d\n", len );
        printf( "%s\n", arr );

    } // end while

    fclose(file); // cleanup
} // end function: readIt

“file lines are considered to be terminated by either a NUL char or newline or EOF” 这种说法是不正确的。文件行以 '\n'EOF 结束。如果 fgets() 遇到 '\0',它并不会停止读取文件。 - chux - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接