You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

函数内无法打印或访问char *变量的技术求助

矩阵列提取函数问题排查与修复

需求是实现getField函数,从矩阵格式文本文件中提取指定列(由field参数指定)的内容。当前代码用-Wall -pedantic编译无报错,但无法正确打印和返回temp变量,无法获取目标字段。

输入文件内容

4
spQ77377.1  0.000000  0.776030  0.781073  0.804880
spO91086.1  0.776030  0.000000  0.564157  0.559756
spP04578.2  0.781073  0.564157  0.000000  0.302724
spO12164.1  0.804880  0.559756  0.302724  0.000000

完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

char * const getField( char lineBuffer[255], int field ) {
    printf( "\n " );
    static char temp[30];

    int f = 0;
    for( int i = 0; lineBuffer[i]!='\n' ; i++ ) {
    
        if( f == field && lineBuffer[i] != ' ' ) {
            temp[i] = lineBuffer[i];
            printf( "%c", temp[i] );
        }
        if( lineBuffer[i] == ' ' && lineBuffer[i+1] == ' ' ) {
            printf( "||" );
            f++;
        }
        if( f > field ) {
            printf( " break " );
            printf( "*%s*", temp );
            fflush(stdout);
            return temp;
        }
    }
    return "!";
}

int main() {

    FILE *matrixStream;
    matrixStream = fopen( "outfile", "r" );
    if ( matrixStream == NULL ) {
        printf( "\n\tERROR FILE NOT FOUND!\n" );
        exit( 1 );
    }

    char lineBuffer[255];  
    fseek( matrixStream, 0, SEEK_SET );
    int line = 0;

    char ** field1 = malloc( 4 * sizeof( char *) );
    while( fgets( lineBuffer, 255, matrixStream ) ) {
        if( line != 0 ) {
            printf( "\n line = %d ", line-1 );
            if( line == 1 ) {
                field1[line-1] = malloc( 30 * sizeof( char ) );
                strcpy( field1[line-1], getField( lineBuffer, 1 ) );
            }
        }
        line++;
    }
    printf( "\n" );

    fclose( matrixStream );
    
    return 0;
}

实际输出

line = 0 
 ||0.000000|| break **
 line = 1 
 line = 2 
 line = 3 

问题根源

  1. temp数组索引错误:直接使用lineBuffer的循环索引i给temp赋值,导致temp中字符不是从索引0开始连续存储。比如目标字段的第一个字符在lineBuffer的索引是11,就会赋值给temp[11],而temp[0]到temp[10]都是未初始化的空字符(ASCII 0),printf("%s")遇到第一个空字符就停止输出,所以看起来temp是空的。
  2. 未添加字符串终止符:即使索引正确,也没有给temp添加'\0',无法正确识别为C字符串。
  3. 字段分隔判断不健壮:仅判断双空格作为字段分隔,没有处理连续多个空格的情况,且没有跳过字段前的空白字符。
  4. temp未重置:temp是静态变量,多次调用时会残留上次的内容,可能导致结果混乱。

修复后的getField函数

char * const getField( char lineBuffer[255], int field ) {
    printf( "\n " );
    static char temp[30];
    int temp_idx = 0;
    int f = 0;
    int in_field = 0; // 标记是否进入当前字段

    // 清空temp,避免残留
    memset(temp, 0, sizeof(temp));

    for( int i = 0; lineBuffer[i] != '\n' && lineBuffer[i] != '\0'; i++ ) {
        // 跳过连续空白字符,同时判断字段切换
        if (isspace((unsigned char)lineBuffer[i])) {
            // 如果之前在字段内,说明当前字段结束
            if (in_field) {
                in_field = 0;
                f++;
                printf( "||" );
            }
            continue;
        }

        in_field = 1;
        // 如果是目标字段,复制字符到temp
        if( f == field ) {
            if (temp_idx < sizeof(temp) - 1) { // 避免缓冲区溢出
                temp[temp_idx++] = lineBuffer[i];
                printf( "%c", temp[temp_idx-1] );
            }
        }
        // 已经过目标字段,提前退出
        if( f > field ) {
            printf( " break " );
            temp[temp_idx] = '\0'; // 添加字符串终止符
            printf( "*%s*", temp );
            fflush(stdout);
            return temp;
        }
    }
    // 处理行尾的情况
    if (f == field) {
        temp[temp_idx] = '\0';
        printf( "*%s*", temp );
        return temp;
    }
    return "!";
}

修复说明

  • 新增temp_idx变量,专门用于temp数组的索引,确保字符从0开始连续存储。
  • 使用memset清空temp,避免静态变量的残留数据干扰。
  • 用isspace判断空白字符,同时通过in_field标记处理字段结束,分隔判断更健壮,支持任意数量的空白分隔。
  • 添加'\0'作为字符串终止符,确保temp是合法的C字符串。
  • 增加缓冲区溢出检查,避免写入超过temp数组的范围。

内容的提问来源于stack exchange,提问作者Goëtay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 03:18:24