Вектор ініціалізації структур


76

Я хочу знати, як я можу додати значення до мого вектора структур за допомогою push_backметоду

struct subject
{
  string name;
  int marks;
  int credits;
};


vector<subject> sub;

Тож як тепер я можу до нього додавати елементи?

У мене є функція, яка ініціалізує ім'я рядка (ім'я теми до нього)

void setName(string s1, string s2, ...... string s6)
{
   // how can i set name too sub[0].name= "english", sub[1].name = "math" etc

  sub[0].name = s1 // gives segmentation fault; so how do I use push_back method?

  sub.name.push_back(s1);
  sub.name.push_back(s2);
  sub.name.push_back(s3);
  sub.name.push_back(s4);

  sub.name.push_back(s6);

}

Виклик функції

setName("english", "math", "physics" ... "economics");

1
інші засоби вектора ініціалізації: stackoverflow.com/questions/4155845/vector-of-structures
jpalecek

Гей, я додав нову відповідь, будь ласка, дивіться на це
Onk_r

Відповіді:


94

Створіть вектор, push_back елемент, а потім змініть його так:

struct subject {
    string name;
    int marks;
    int credits;
};


int main() {
    vector<subject> sub;

    //Push back new subject created with default constructor.
    sub.push_back(subject());

    //Vector now has 1 element @ index 0, so modify it.
    sub[0].name = "english";

    //Add a new element if you want another:
    sub.push_back(subject());

    //Modify its name and marks.
    sub[1].name = "math";
    sub[1].marks = 90;
}

Ви не можете отримати доступ до вектора за допомогою [#], поки елемент не існує у векторі з цим індексом. Цей приклад заповнює [#], а потім модифікує його.


2
subject.resize(2);може бути дещо швидшим і зрозумілішим рішенням ... або навіть vector<subject> sub(2);.
Kerrek SB

1
Так, я згоден. :) Я не думав, що він цілком зрозумів би перерозподіл для ефективності та того, як вектор збільшується в розмірах - це більше схоже на вступ до проблеми c ++.
Джон Хамфріс - w00te

1
@ w00te Я додав пару лапок, які ви, мабуть, забули додати. Сподіваюся, це нормально.
Натан Стреппель,

2
@nims Все добре! :) Я здивований, що помилка три роки висіла у питанні з 25000 переглядів, ха-ха.
Джон Хамфріс - w00te

56

Якщо ви хочете використовувати новий чинний стандарт, ви можете зробити це:

sub.emplace_back ("Math", 70, 0);

або

sub.push_back ({"Math", 70, 0});

Вони не вимагають побудови за замовчуванням subject.


2
Перша частина вашої відповіді не є точною; ви не можете emplace_back структуру без відповідного ctor rextester.com/VQWCT51042
Jean-Simon

13

Ви також можете використовувати сукупну ініціалізацію зі спискового списку ініціалізації для подібних ситуацій.

#include <vector>
using namespace std;

struct subject {
    string name;
    int    marks;
    int    credits;
};

int main() {
    vector<subject> sub {
      {"english", 10, 0},
      {"math"   , 20, 5}
    };
}

Іноді, проте, члени структури можуть бути не такими простими, тому вам потрібно допомогти компілятору у виведенні його типів.

Отже, поширюючись на вищесказане.

#include <vector>
using namespace std;

struct assessment {
    int   points;
    int   total;
    float percentage;
};

struct subject {
    string name;
    int    marks;
    int    credits;
    vector<assessment> assessments;
};

int main() {
    vector<subject> sub {
      {"english", 10, 0, {
                             assessment{1,3,0.33f},
                             assessment{2,3,0.66f},
                             assessment{3,3,1.00f}
                         }},
      {"math"   , 20, 5, {
                             assessment{2,4,0.50f}
                         }}
    };
}

Без assessmentвкладеного в дужку ініціалізатора компілятор зазнає невдачі при спробі вивести тип.

Вищевказане було скомпільовано та перевірено на gcc в c ++ 17. Однак він повинен працювати з c ++ 11 і далі. У c ++ 20 ми можемо побачити синтаксис позначення, я сподіваюся, що це дозволить зробити наступне

  {"english", 10, 0, .assessments{
                         {1,3,0.33f},
                         {2,3,0.66f},
                         {3,3,1.00f}
                     }},

джерело: http://en.cppreference.com/w/cpp/language/aggregate_initialization


10

Ви не можете отримати доступ до елементів порожнього вектора за індексом.
Завжди перевіряйте, що вектор не порожній та індекс дійсний під час використання []оператора on std::vector.
[]не додає елементи, якщо жоден не існує, але це спричиняє невизначену поведінку, якщо індекс недійсний.

Ви повинні створити тимчасовий об’єкт своєї структури, заповнити його, а потім додати до вектора, використовуючи vector::push_back()

subject subObj;
subObj.name = s1;
sub.push_back(subObj);

3

Подивившись прийняту відповідь, я зрозумів, що якщо знати розмір необхідного вектора, тоді нам потрібно використовувати цикл для ініціалізації кожного елемента

Але я знайшов нове, щоб зробити це, використовуючи default_structure_element, як показано нижче ...

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;

typedef struct subject {
  string name;
  int marks;
  int credits;
}subject;

int main(){
  subject default_subject;
  default_subject.name="NONE";
  default_subject.marks = 0;
  default_subject.credits = 0;

  vector <subject> sub(10,default_subject);         // default_subject to initialize

  //to check is it initialised
  for(ll i=0;i<sub.size();i++) {
    cout << sub[i].name << " " << sub[i].marks << " " << sub[i].credits << endl;
  } 
}

Тоді я думаю, що це хороший спосіб ініціалізації вектора структури, чи не так?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.