我在编写代码时遇到了一些问题。程序通过将文件作为字符串读取到 char 结构变量中来读取文件,并将其传递给 trimField 函数以修剪程序。这是给我们的输入文本文件:
BROWN DANIELLA 810805748 562431322143323235411221 4213414131344422312122
DEREK SAMATHA I 002 10011313243433233344312212321342123 14212224242131121
SIMPSON BRETT 3844342323232233 33412342212342113221331132411112132
TOMATO A LUKE 811327785 15328003 4214341213331232354112432321532412124211142232213242
我在文件中读取的这个函数看起来像这样,其中数字来自结构变量(即 char Name[21];):
void readData(std::ifstream inFileStream, Scantron &inputRecord) {
std::string incomingData;
getline(inFileStream, incomingData);
if(!inputTestFile.eof) {
for(int i = 0; i < incomingData; i++) {
std::cin.get(inputRecord[i].Name, 21, ' ');
std::cin.get(inputRecord[i].Id, 11, ' ');
std::cin.get(inputRecord[i].CRN, 6, ' ');
std::cin.get(inputRecord[i].testCode, 3, ' ');
std::cin.get(inputRecord[i].specialCode, 4, ' ');
std::cin.get(inputRecord[i].score, 4, ' ');
std::cin.get(inputRecord[i].answerArray, 61, ' ');
}
}
}
我当前调用trimField函数的函数如下所示:
csvRecord transformDataToCSV(Scantron inputRecord){
csvRecord outputRecord;
trimField(inputRecord.Name, outputRecord.Name);
trimField(inputRecord.Id, outputRecord.Id);
trimField(inputRecord.score, outputRecord.score);
for(int i = 0; i < 60; ++i) {
outputRecord.answerArray[i] = inputRecord.answerArray[i];
trimField(inputRecord.answerArray, outputRecord.score);
}
return outputRecord;
}
我的修剪字段的标题必须如下所示:
// remove trailing spaces from fieldIn cstring and place in fieldOut cstring. If entire field is blank place one space followed by .
void trimField(char fieldIn[], char &fieldOut[] ) {
}
在修剪文件时,我什至不确定如何开始,并且有太多不同的方法可以在线完成,这使我很难理解如何做到这一点。
我很困惑为什么你仍然使用cstring。 更令人困惑的是,您尝试为输出传递一个引用数组;这不会编译:
error: declaration of ‘fieldOut’ as array of references
void trimField2(char fieldIn[], char &fieldOut[]) {
^
第一个非常基本的版本
尽管如此,这里有一个简单的解决方案:计算开头的空格数,计算末尾的空格数,然后只复制剩下的:
void trimField(char fieldIn[], char fieldOut[] ) {
int i=0;
// skip left spaces with i
while (fieldIn[i] && isspace(fieldIn[i]) )
i++;
// skip right spaces starting from end with j (relative to i)
int j=strlen(fieldIn+i);
while (j && isspace (fieldIn[j+i-1]) )
j--;
strncpy(fieldOut, fieldIn+i, j);
fieldOut[j]=' ';
}
请注意,此函数不安全,因为它不考虑输出的最大长度作为参数,因此存在缓冲区溢出的风险。此外,它容易出错,因为输入未定义为const
。
构建字符串的更安全版本
我向你推荐一个变体,它返回一个真正的C++字符串,并将一个常量缓冲区作为输入:
std::string trimField(const char fieldIn[]) {
const char *p, *q,*r;
for (p=fieldIn; *p && isspace(*p); p++ ) // skip left spaces
;
for (q=r=p; *q; q++) // sorry for the tripple assignment ;-)
if (!isspace (*q))
r=q; // keep trace of last non white
return std::string (p, r+1);
}
为了方便起见,我切换到指针。 为了避免在第一个非空格字符之后读取两倍的字符,我们同时搜索输入字符串 (q( 的末尾并跟踪 las 非白色字符 (r(。最后,我们基于开始和结束指针/迭代器构造一个字符串。