首页 > 解决方案 > 从文件未定义行为打印的 C 行

问题描述

我制作了一个 ac 程序,它解析一种称为 rapid 的语言的源代码文件,以提取我在工作中需要记录的某些数据。提取的数据保存到 csv 文件,然后格式化为 Excel 工作表。

除了我在下面放置的这个功能之外,一切都在工作。在某些情况下,我想从从文件读取的行中删除所有空格和制表符,以便我可以将语句作为字符串存储在结构属性中。

程序没有崩溃,但是当我 printf() 删除了空格的新行时,其他一些字符会被打印出来。

示例“cmd.exe”、“PowerShell\v1.0\Modules”、“igh\AppData\LocaloYSφo¡”

如果我这样做Printf("%s\n", currentLine);它打印得很好

当我使用时,printf("%s\n", removeWhiteSpace(currentLine));我得到未定义的行为。

这是功能

/******************************************************************
*   Takes a string as input, returns it without tabs or spaces
*   Used to put whole line into the additional commands
*   Attribute
******************************************************************/
static char* removeWhiteSpace(char* string)
{
    int i;
    int j;
    int len = strlen(string);
    char ch;
    char* result = malloc(sizeof(char)*len+1);

    memset(result, 0, sizeof(*result));

    j=0;
    for (i=0; i<len; i++)
    {
        ch = string[i];
        if ((ch != ' ') && (ch != '\t'))
            {
                result[j] = ch;
                j++;
            }
    }

    result[strlen(result)] = '\0';

    return result;
}

另外,我使用 fgets() 从文件中获取行,缓冲区的大小为 1000。

文本文件中不存在不需要的字符,至少不可见。

感谢您抽出宝贵时间,如果您需要文本文件或程序的其余部分,我可以提供,但它很长。

另外,我正在使用 GCC 编译器使用 codeblocks IDE,我在编译时没有错误或警告。

标签: cstringfile

解决方案


memset(result, 0, sizeof(*result));

那是错的。*result是东西result指向。resultchar *,所以它指向 a char,并且 a 的大小char是 1。所以该语句将 1 设置char为 0。它不会将整个分配的内存块设置为零。

正如我们将看到的,它是不需要的,所以只需删除该语句。

result[strlen(result)] = '\0';

这种说法是没有用的。strlen通过查找数组中的第一个空(零)字符来工作。所以strlen(result)会报告第一个空字符在哪里。然后result[strlen(result)] = '\0';将该字符设置为零。但它已经为零。所以这个语句永远无法完成任何事情。不仅如此,它还不起作用,因为memset上面没有将内存设置为零,所以分配的内存中可能没有空字符可以找到。在这种情况下,行为不是由 C 标准定义的。

但是,没有必要使用strlen来查找字符串的结尾。我们知道字符串的结尾应该在哪里。对象j一直在计算写入的字符数result。所以只需删除这一行并使用:

result[j] = '\0';

当我使用时,printf("%s\n", removeWhiteSpace(currentLine));我得到未定义的行为。

这没有任何意义。“未定义的行为”不是一回事。这是缺少的东西。说某事具有“未定义的行为”意味着 C 标准没有定义行为是什么。具有未定义行为的程序可能不打印任何内容,可能会打印期望的结果,可能会打印不期望的结果,可能会打印垃圾字符,可能会崩溃,并且可能会挂起。

说程序产生了未定义的行为并不能告诉任何人发生了什么。相反,您应该编写程序行为的具体描述,例如“程序打印了预期的文本,后跟意外的字符”。精确输入和精确输出的复制和粘贴会很好。


推荐阅读