从输入文件修剪空格



我在编写代码时遇到了一些问题。程序通过将文件作为字符串读取到 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(。最后,我们基于开始和结束指针/迭代器构造一个字符串。

最新更新