предупреждение: структура user_data_s объявлена ​​внутри списка параметров

Вот готовая к использованию функция, если вам нужно всего лишь загрузить файл данных с удвоением (целые числа, текст).

#include <sstream>
#include <fstream>
#include <iterator>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

/**
 * Parse a CSV data file and fill the 2d STL vector "data".
 * Limits: only "pure datas" of doubles, not encapsulated by " and without \n inside.
 * Further no formatting in the data (e.g. scientific notation)
 * It however handles both dots and commas as decimal separators and removes thousand separator.
 * 
 * returnCodes[0]: file access 0-> ok 1-> not able to read; 2-> decimal separator equal to comma separator
 * returnCodes[1]: number of records
 * returnCodes[2]: number of fields. -1 If rows have different field size
 * 
 */
vector<int>
readCsvData (vector <vector <double>>& data, const string& filename, const string& delimiter, const string& decseparator){

 int vv[3] = { 0,0,0 };
 vector<int> returnCodes(&vv[0], &vv[0]+3);

 string rowstring, stringtoken;
 double doubletoken;
 int rowcount=0;
 int fieldcount=0;
 data.clear();

 ifstream iFile(filename, ios_base::in);
 if (!iFile.is_open()){
   returnCodes[0] = 1;
   return returnCodes;
 }
 while (getline(iFile, rowstring)) {
    if (rowstring=="") continue; // empty line
    rowcount ++; //let's start with 1
    if(delimiter == decseparator){
      returnCodes[0] = 2;
      return returnCodes;
    }
    if(decseparator != "."){
     // remove dots (used as thousand separators)
     string::iterator end_pos = remove(rowstring.begin(), rowstring.end(), '.');
     rowstring.erase(end_pos, rowstring.end());
     // replace decimal separator with dots.
     replace(rowstring.begin(), rowstring.end(),decseparator.c_str()[0], '.'); 
    } else {
     // remove commas (used as thousand separators)
     string::iterator end_pos = remove(rowstring.begin(), rowstring.end(), ',');
     rowstring.erase(end_pos, rowstring.end());
    }
    // tokenize..
    vector<double> tokens;
    // Skip delimiters at beginning.
    string::size_type lastPos = rowstring.find_first_not_of(delimiter, 0);
    // Find first "non-delimiter".
    string::size_type pos     = rowstring.find_first_of(delimiter, lastPos);
    while (string::npos != pos || string::npos != lastPos){
        // Found a token, convert it to double add it to the vector.
        stringtoken = rowstring.substr(lastPos, pos - lastPos);
        if (stringtoken == "") {
      tokens.push_back(0.0);
    } else {
          istringstream totalSString(stringtoken);
      totalSString >> doubletoken;
      tokens.push_back(doubletoken);
    }     
        // Skip delimiters.  Note the "not_of"
        lastPos = rowstring.find_first_not_of(delimiter, pos);
        // Find next "non-delimiter"
        pos = rowstring.find_first_of(delimiter, lastPos);
    }
    if(rowcount == 1){
      fieldcount = tokens.size();
      returnCodes[2] = tokens.size();
    } else {
      if ( tokens.size() != fieldcount){
    returnCodes[2] = -1;
      }
    }
    data.push_back(tokens);
 }
 iFile.close();
 returnCodes[1] = rowcount;
 return returnCodes;
}
16
задан Alex K 18 November 2018 в 21:02
поделиться

2 ответа

Вы объявили свою структуру между (или, возможно, после) ваших объявлений f2 и f1 . Переместите объявление структуры так, чтобы оно стоит перед обоими объявлениями.

То есть:

struct user_data_s
{
    int L;
};

void f2(struct user_data_s* data) {
      printf("Number %i\n", data->L);
}

void f1(struct user_data_s* data) {
      printf("Number %i\n", data->L);
        f2(data);
}

компилируется без ошибок, но

void f2(struct user_data_s* data) {
      printf("Number %i\n", data->L);
}


struct user_data_s
{
    int L;
};

void f1(struct user_data_s* data) {
      printf("Number %i\n", data->L);
        f2(data);
}

не компилируется, потому что f2 не может узнать, что такое struct user_data_s является.

Возможно, вы привыкли к программированию на языке более высокого уровня, который позволяет размещать ваши объявления / определения практически где угодно (например, C # или Python), но, к сожалению, C компилируется строго сверху вниз.

26
ответ дан 30 November 2019 в 12:20
поделиться

Компилятор уже дал вам довольно хорошее объяснение того, что происходит.

Вы не объявили struct user_data_s заранее. Компилятор впервые видит struct user_data_s в приведенных выше определениях функций. В каждом случае объявление struct user_data_s имеет область видимости блока, т. Е. Локально для соответствующей функции. Это означает, что первое объявление struct user_data_s в определении f1 полностью не связано со вторым объявлением struct user_data_s в определении f2 . Эти объявления объявляют два совершенно разных локальных (для каждой функции) типа struct user_data_s . Вы можете' t вызовите f2 из f1 , как в вашем примере, поскольку их типы параметров совершенно не связаны.

Обычно вы должны иметь struct user_data_s , объявленную в области файла в заранее, вместо того, чтобы объявлять это в определении функции. Вы случайно не забыли включить заголовок в объявление struct user_data_s ?

6
ответ дан 30 November 2019 в 12:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: