一个代码阅读题求指导

RT 被要求说出一段代码的功能以及找出其中三个错误 说是不懂C语言也能看出来 我读了一段时间,感觉出两问题不知道对不对(对C的语法什么都不太熟悉) 之前只会写一点jQuery的DOM操作 所以来求证

一个是32行的strncmp(src_str + i, sub_str, sub_str_len) -直接把src_str和int型 i相加 在JS里面 这样做会 把两个拼成一个字符串 不知道c里面这样做的结果会如何
一个是sort_txt_line里面的for循环有可能第一个元素 永远没有和最后一个元素进行比较...

功能 凭感觉 就是把字符串转成数组排序 然后输出出来 求指正

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned int BOOL;
#define TRUE    1
#define FALSE    0
#define MAX_FILE_NAME_LEN 255
#define MAX_PRO_TXT_LINES_NUM 1024
#define MAX_CHAR_NUM_IN_ONE_LINE 1024
char src_txt_line_arr[MAX_PRO_TXT_LINES_NUM][MAX_CHAR_NUM_IN_ONE_LINE];
void swap(long long *a, long long *b)
{
    long long tmp = *a;
    *a = *b;
    *b = tmp;
}
BOOL contain_str(const char *src_str, const char *sub_str)
{
    unsigned int src_str_len;
    unsigned int sub_str_len;
    int i;
    
    src_str_len = strlen(src_str);
    sub_str_len = strlen(sub_str);

    if(src_str_len < sub_str_len)
    {
        return FALSE;
    }
    for(i = 0; i <= src_str_len - sub_str_len; ++i)
    {
        if(0 == strncmp(src_str + i, sub_str, sub_str_len) )
        {
            return TRUE;
        }
    }
    
    return FALSE;
}

void init_txt_index_arr(long long *arr, long long num)
{
    int i;
    for(i = 0; i < num; ++i)
    {
        *(arr + i) = i;
    }
}
void sort_txt_line(long long *txt_index_arr, long long arr_num)
{
    int i;
    int j;
    int index;
    int index_next;
    for(i = 0; i < arr_num; ++i)
    {
        for(j = 0; j < arr_num - i; ++j)
        {
            index = *(txt_index_arr + j);
            index_next = *(txt_index_arr + j + 1);
            if(strcmp(src_txt_line_arr[index], src_txt_line_arr[index_next]) > 0)
            {
                swap(&txt_index_arr[index], &txt_index_arr[index_next]);        
            }
        }
    }
}
void get_in_txt_line_arr(const char *file_name, long long *p_arr_num)
{
    FILE *fp;
    char *line = NULL;
    size_t len = 0;
    ssize_t read;
    long long step = 0;

    fp = fopen(file_name, "r");
    if(NULL == fp)
    {
        exit(EXIT_FAILURE);
    }
    while((read = getline(&line, &len, fp)) != -1)
    {
                if(TRUE == contain_str(line, "abc") )
                {
                        strcpy(src_txt_line_arr[step++], line);
                }
                if(step >= MAX_PRO_TXT_LINES_NUM)
                {
                        printf("sorry. we can only process %d lines\n", MAX_PRO_TXT_LINES_NUM);
                        break;
                }
        }
    free(line);
    *p_arr_num = step;
}
void out_put_str_arr(long long *index_arr, long long arr_num)
{
    long long i;
    for( i = 0; i < arr_num; ++i)
    {
        printf("Line %03lld: %s", i, src_txt_line_arr[*(index_arr + i)]); 
    }
}
int main(int argc, char *argv[])
{
    long long dst_txt_index[MAX_PRO_TXT_LINES_NUM];
    long long arr_num = 0;

    if(argc != 2)
    {
        printf("Usage: xxx fileName\n");
        exit(0);
    }

    get_in_txt_line_arr(argv[1], &arr_num);
    
    init_txt_index_arr(dst_txt_index, arr_num);

    sort_txt_line(dst_txt_index, arr_num);

    out_put_str_arr(dst_txt_index, arr_num);

    return 0;
}
阅读 3.1k
2 个回答

没学过C语言,用js的语法思维来看C语法,根本无法想象。

代码的功能就是从一个文件读入包括abc字符串的行,并对这些行进行排序,按排序后的顺序打印这些行,为了减少排序时字符串的复制,用一个下标数组保存排序的结果。

代码中的错误:
1、fopen了文件后,用完没有调用fclose
2、getline函数每次调用成功会给line分配空间,用完每次都要free,而代码只free了一次
3、排序时,我猜测代码想要使用冒泡排序算法,但那种写法不是冒泡排序的正确写法

太细的错误我也不会去看,因为人家都说了“不懂C语言也能看出来的错误”

拿到标准答案于是来填一下坑

功能:

读取一个文件,将文件中含有"abc"的行按升序排序,并输出排序后的结果

  大家都答对了!

重大问题:
1.资源没有释放,内存泄漏 fopen()打开文件,但没有调用fclose() 关闭文件句柄。

2.strcpy(srctxtlinearr[step++], line); 没有考虑line的长度比strtxtlinearr[]数组元素 MAXCHARNUMINONE_LINE长,存在内存溢出风险。
这是最致命的!

3.函数getintxtlinearr()中打开文件出错,直接调用exit()函数退出,会导致程序随意终止。这样写根本不敢用于库调用!

4.排序算法错误,根本不能排序!C语言排序有标准库函数qsort(),可支持对任何数据类型的排序,高效简洁!

5.在free(line)之前,应该进行判断if (NULL != line) free(line), 因为getline()有可能失败,line会为NULL,产生段错误!

小问题:
1.定义固定长度的字符串数组,没有考虑文件中可能存在很多行的情况,程序可扩展性差;

2.判断一行内容是否包含"abc"字符串的函数 contain_str() 丑陋低效,重复造轮子;C语言标准库函数 strstr()/memmem() 等都比它强!

3.定义bool真假宏标识没有考虑与系统定义相冲突的可能情况
如果非要定义,建议如下写法

#ifndef TRUE
#define TRUE    1
#endif

#ifndef FALSE
#define FALSE    0
#endif

4.swap()函数用于对保存行内容字符串的数组地址进行交换,隐式转换char* 为long long 类型,丑陋的类型转换

建议:
1.增加必要的注释;注意编程规范;

2.将所有的printf()调试行用宏替换;

3.在getintxtlinearr()中打开文件失败后直接退出,没有必要的错误输出,极不利于程序错误诊断。
对关键资源访问出现的错误因尽量输出调试日志!比如:open(),listen()等等

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进