函数内无法打印或访问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
问题根源
temp数组索引错误:直接使用lineBuffer的循环索引i给temp赋值,导致temp中字符不是从索引0开始连续存储。比如目标字段的第一个字符在lineBuffer的索引是11,就会赋值给temp[11],而temp[0]到temp[10]都是未初始化的空字符(ASCII 0),printf("%s")遇到第一个空字符就停止输出,所以看起来temp是空的。- 未添加字符串终止符:即使索引正确,也没有给
temp添加'\0',无法正确识别为C字符串。 - 字段分隔判断不健壮:仅判断双空格作为字段分隔,没有处理连续多个空格的情况,且没有跳过字段前的空白字符。
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
相关产品推荐
相关产品推荐

