从C中的STDIN解析后输出的垃圾字符

时间:2012-01-09 10:45:47

标签: c io stdin

我在一些文本的最后输出了一个垃圾字符:

hum 1345342342 ~Users/Documents ecabd459 //line that was read in from stdin
event action: hum_?
event timestamp: 1345342342
event path: ~Users/Documents
event hash: ecabd459

在事件操作值结束时有一个'_?'输出的垃圾字符。这可以通过将变量的最后位置设置为空终止符(event.action[3] = '\0')来纠正,这一切都很好,但是我很困惑的另一个char数组event.hash没有表现出这种类型行为我以相同的方式创建/打印它们,但哈希行为不一样。

注意:我正在考虑这可能是因为哈希值严格遵循换行符(我顺便说一句),所以我测试了我的程序并重新排序输入无效(也就是说,在哈希值在线上的位置后添加了一个额外的空格和单词)。

相关代码如下:

struct Event{
    char action[4];
    long timestamp;
    char* path;
    char hash[9];
};   

// parse line and return an Event struct
struct Event parseLineIntoEvent(char* line) {
    struct Event event;
    char* lineSegment;

    int i = 0;
    lineSegment = strtok(line, " ");
    while (lineSegment != NULL) {
        if (i > 3) {
            printf("WARNING: input format error!\n");
            break;
        }
        if (i == 0)
            strncpy(event.action, lineSegment, sizeof(event.action)-1);
        else if(i == 1)
            event.timestamp = atoi(lineSegment);
        else if(i == 2) {
            event.path = malloc(sizeof(lineSegment));
            strcpy(event.path, lineSegment);
        } else if(i == 3)
            strncpy(event.hash, lineSegment, sizeof(event.hash)-1);
        lineSegment = strtok(NULL, " ");
        i++;
    } // while
    return event;
} // parseLineIntoEvent()

int main (int argc, const char * argv[]) {
//...
    printf("%s\n",line); //prints original line that was read in from stdin
    struct Event event = parseLineIntoEvent(line);
    printf("event action: %s\n", event.action);
    printf("event timestamp: %lu\n", event.timestamp);
    printf("event path: %s\n", event.path);
    printf("event hash: %s\n", event.hash);
    free(event.path);
    free(line);
//...
    return 0;
}

修改 我用这个函数读了一行,它删除了换行符:

// read in line from stdin, eliminating newline character if present
char* getLineFromStdin() {
    char *text;
    int textSize = 50*sizeof(char);
    text = malloc(textSize);

    if ( fgets(text, textSize, stdin) != NULL ) {
        char *newline = strchr(text, '\n'); // search for newline character
        if ( newline != NULL ) {
            *newline = '\0'; // overwrite trailing newline
        }
    }
    return text;
}

提前致谢!

4 个答案:

答案 0 :(得分:3)

这是一个错误:

event.path = malloc(sizeof(lineSegment));

将返回sizeof(char*),当您需要长度加1来终止NULL字符时:

event.path = malloc(sizeof(char) * (strlen(lineSegment) + 1));

为避免必须将空字符串终止符插入actionhash,您可以初始化event

struct Event event = { 0 };

答案 1 :(得分:2)

来自Linux manual page

The strncpy() function is similar, except that at most n bytes of src are copied.
Warning: If there is no null byte among the first n bytes of src, the string
placed in dest will not be null-terminated.

执行strncpy时,您必须确保目标字符串已正确终止。

更改event.action字段的设置:

if (i == 0)
{
    strncpy(event.action, lineSegment, sizeof(event.action)-1);
    event.action[sizeof(event.action)-1] = '\0';
}

答案 2 :(得分:1)

  

但是我对另一个char数组event.hash没有表现出这种行为的事实感到困惑

你不走运。 hash [8]可能通过纯粹的(坏)运气获得了'\ 0'。

尝试在strtok循环之前将其设置为“随机”

    int i = 0;
    event.hash[8] = '_';             /* forcing good-luck */
    lineSegment = strtok(line, " ");
    while (lineSegment != NULL) {

答案 3 :(得分:0)

这是因为,字符串“num”只接受来自4个元素字符数组Event.action的三个元素,第四个元素将保持未设置状态。因为没有为Event.action数组元素设置任何内容,所以它将指向存储了一些随机值的随机内存位置。当你打印这个字符数组时,它将打印所有元素而不是那些指向有效数据的元素。这会导致垃圾字符出现。