Обрезка пробелов из входного файла - PullRequest
0 голосов
/ 16 сентября 2018

У меня возникли проблемы с кодом, который я пишу. Программа считывает данные из файла, считывая его как строку в переменные структуры 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;
}

И заголовок для моего trimField должен выглядеть так:

// remove trailing spaces from fieldIn cstring and place in fieldOut cstring. If entire field is blank place one space followed by \0.
void trimField(char fieldIn[], char &fieldOut[] )   {

}

Я не уверен, с чего начать, когда дело доходит до обрезки файла, и есть слишком много разных способов сделать это онлайн, и мне трудно понять, как это сделать.

1 Ответ

0 голосов
/ 16 сентября 2018

Я озадачен, почему ты все еще работаешь с 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]='\0'; 
}

Обратите внимание, что эта функция небезопасна, поскольку она не учитывает максимальную длину вывода в качестве параметра, что может привести к переполнению буфера. Кроме того, он подвержен ошибкам, потому что ввод не определен как 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 non white char (r). Наконец, мы строим строку на основе начального и конечного указателя / итератора.

...