Как инициализировать сопоставление char с char с нулевыми значениями в c ?

#c #dictionary #data-structures

#c #словарь #структуры данных

Вопрос:

Я пытаюсь сохранить родительский элемент каждого узла в неупорядоченной карте, и мне нужно инициализировать значения с помощью NULL, например:

 //This is inside a method of a template class
std::unordered_map<T, T> parent;
parent[start] = NULL;
 

Это выдает предупреждение:

 warning: converting to non-pointer type 'std::unordered_map<char, char, std::hash<char>, std::equal_to<char>, std::allocator<std::pair<const char, char> > >::mapped_type' {aka 'char'} from NULL [-Wconversion-null]
      parent[start] = NULL;
 

Это работает, когда T равно char, но не работает с другими типами.

 //This is inside a method of a template class
std::unordered_map<T, T> parent;
parent[start] = '';
 

Как сделать так, чтобы я мог хранить значение ключей как NULL.
P.S: Я новичок в c .

 T curr = end; // Here end is variable passed by user
 while(curr != NULL) { // I want to check whether current is NULL
 res.push(curr); // res is a stack, and I push the element(value of key)to it
 curr = parent[curr];
}
 

Я хочу проверить наличие нулевого значения и остановить цикл while.

Вот полный код для метода:

 #include<iostream>
#include<vector>
#include<algorithm>
#include<unordered_map>
#include<list>
#include<queue>
#include <climits>
#include <stack>
#include <string>
using namespace std;

template <typename T>
class TemplateGraph {

  private:
    int V;
    unordered_map<T, list<pair<T, int>>> adjList;
    
  public:
    TemplateGraph(int v): V(v) {}
    void addEdge(T from, T to,bool isBiDir, int weight) {
      adjList[from].push_back(make_pair(to, weight));
      if(isBiDir) {
        adjList[to].push_back(make_pair(from, weight));
      }
    }
   void getPath(T start, T end) {
      unordered_map<T, int> dist;
      priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> pq;
      unordered_map<T, T> parent;
      stack<T> res;
// adjList is of type =
// unordered_map<T, list<pair<T, int>>> adjList;
      for(auto vtx: adjList) { 
        T key = vtx.first;
        dist[key] = INT_MAX;
      }
      pq.push(make_pair(start, 0));
      dist[start] = 0;
      parent[start] = 0;
      while(!pq.empty()){
        T top = pq.top().first;
        pq.pop();
        for(auto nbr: adjList[top]){
          T node = nbr.first;
          int wt = nbr.second;
          int newWt = dist[top]   wt;
          if(newWt < dist[node]) {
            dist[node] = newWt;
            pq.push(make_pair(node, dist[node]));
            parent[node] = top;
          }
        }
      }
      T curr = end;
      while(curr != 0) {
        res.push(curr);
        curr = parent[curr];
      }
      while(!res.empty()){
        T node = res.top();
        res.pop();
        cout << node << " ";
      } 
    }
}

int main(){
  TemplateGraph<char> g2(9);
  g2.addEdge('A', 'B', true, 2);
  g2.addEdge('A', 'C', true, 5);
  g2.addEdge('B', 'D', true, 7);
  g2.addEdge('C', 'D', true, 2);
  g2.addEdge('C', 'E', true, 3);
  g2.addEdge('E', 'F', true, 4);
  g2.addEdge('E', 'H', true, 3);
  g2.addEdge('F', 'G', true, 1);
  g2.addEdge('D', 'F', true, 1);
  g2.getPath('A', 'F');
  TemplateGraph<int> g(9);
  g.addEdge(1, 2, true, 4);
  g.addEdge(4, 1, true, 3);
  g.addEdge(2, 3, true, 2);
  g.addEdge(2, 5, true, 4);
  g.addEdge(4, 5, true, 1);
  g.addEdge(3, 8, true, 5);
  g.addEdge(3, 7, true, 2);
  g.addEdge(7, 9, true, 1);
  g.getPath(1, 5);
  return 0;
}
 

Комментарии:

1. char у s нет нулевых значений. Однако они могут иметь нулевое значение. На что вы надеетесь NULL ? » Как сделать так, чтобы я мог хранить значения ключей как NULL » — Похоже, вы устанавливаете значения NULL , а не ключи.

2. Вы просто хотите вставить «значение по умолчанию», например '' , nullptr , 0 , 0.0 в зависимости от T ? Может быть, вы тоже хотите сделать что-то, что std::optional может вам помочь. Дополнительный код может помочь внести ясность.

3. Я хочу инициализировать первый ключ как NULL, и в цикле я добавлю родительский узел для каждого узла. Мне нужно значение NULL для первого ключа, чтобы я мог проверять диапазон при обходе узлов, следуя за его родителем. Примерно так же, как мы делали в алгоритме Дейкстры

4. Я бы предложил другую тактику — вообще не пытайтесь помещать нулевые значения в карту. Добавляйте только те ключи, которым нужно присвоить фактические значения. Вы можете использовать метод map find() , чтобы определить, существует ли данный ключ на карте, и получить итератор для него, только если он существует.

5. @RemyLebeau Спасибо тебе!!! Сейчас он работает нормально…

Ответ №1:

В C нет понятия «пустое значение». Все целые числа имеют целочисленные значения, все символы имеют значения char, и все строки имеют строковые значения, а все указатели имеют значения указателя. Всегда. Теперь, возможно, у вас есть значение, которое вы рассматриваете как пустое, например, nullptr для указателей, '' символов и 0 целых чисел, но переменная все еще существует и содержит это как значение.

Обычно вы можете просто использовать {} , чтобы получить значение по умолчанию для любого типа, и рассматривать это как волшебное «без значения», если хотите. В качестве альтернативы вы можете использовать std::optional<T> , который может иметь значение std::nullopt в дополнение к любому допустимому значению T .

Комментарии:

1. «В C нет понятия «пустое значение» » — на самом деле, оно есть, через std::optional

Ответ №2:

‘ 0’ имеет тип char. NULL — это макрос типа void *

вы можете либо использовать », либо сохранить указатель на символ вместо символа. например, char*

Комментарии:

1. Из cppreference : » В C макрос NULL может иметь тип void* , но это не разрешено в C »

2. Спасибо за ответ, когда T равно char, ‘/ 0’ работает нормально. Но is не работает для int и string(как и ожидалось). Я использую шаблон, поэтому мне нужно решение, которое отлично работает для всех из них, т.е. int, char и string . Есть ли какой-либо способ сделать карту такой, чтобы она могла принимать как T, так и NULL?

3. Я хочу инициализировать первый ключ как NULL и в цикле я добавлю родительский узел для каждого узла. Мне нужно значение NULL для первого ключа, чтобы я мог проверять диапазон при обходе узлов, следуя его родительскому элементу. Вроде того, что мы делали в алгоритме Дейкстры.

4. Тогда как я могу инициализировать переменную с пустым значением? Есть ли какой-нибудь способ? Я исхожу из предыстории JS.