AM Z
AM Z

Reputation: 431

How to get input from the user and push it to a list

#include <iostream>
#include <list>

#define print(x) std::cout << x
#define println(x) std::cout << x << std::endl

template<typename T>
T input(const char* string) {
    print(string);
    T temp{};
    std::cin >> temp;
    return temp;
}

int main() {
    std::list<char*> list_of_foods;
    char* food;
    while (1) {
        food = input<char*>("Enter a food name or (exit) to exit: ");
        if (food == "exit") { break; }
        else { list_of_foods.push_back(food); }
    }
    std::list<char*>::iterator food_iterator = list_of_foods.begin();
    println("Your order is:");
    while (food_iterator != list_of_foods.end()) {
        println(*food_iterator);
        food_iterator++;
    }
}

I'm trying to run this code but it exit when I try to type any food name with an "-1073741819" exit code, what did a do wrong exactly ?

Upvotes: 1

Views: 112

Answers (2)

MikeCAT
MikeCAT

Reputation: 75062

T temp{};

Is initializing temp to nullptr, so you cannot have it read something there.

You should use std::string instead:

#include <iostream>
#include <string> // add this to use std::string
#include <list>

#define print(x) std::cout << x
#define println(x) std::cout << x << std::endl

template<typename T>
T input(const char* string) {
    print(string);
    T temp{};
    std::cin >> temp;
    return temp;
}

int main() {
    std::list<std::string> list_of_foods;
    std::string food;
    while (1) {
        food = input<std::string>("Enter a food name or (exit) to exit: ");
        if (food == "exit") { break; }
        else { list_of_foods.push_back(food); }
    }
    std::list<std::string>::iterator food_iterator = list_of_foods.begin();
    println("Your order is:");
    while (food_iterator != list_of_foods.end()) {
        println(*food_iterator);
        food_iterator++;
    }
}

If you want to use char* anyway, template specialization is useful to have it allocate buffer. Also note that comparision of C-style string cannot be done via == and you should use strcmp() instead.

#include <iostream>
#include <cstring> // for using strcmp()
#include <list>

#define print(x) std::cout << x
#define println(x) std::cout << x << std::endl

template<typename T>
T input(const char* string) {
    print(string);
    T temp{};
    std::cin >> temp;
    return temp;
}

template<>
char* input(const char* string) {
    print(string);
    char* temp = new char[1024000]; // allocate enough size and pray not to be attacked
    std::cin >> temp;
    return temp;
}

int main() {
    std::list<char*> list_of_foods;
    char* food;
    while (1) {
        food = input<char*>("Enter a food name or (exit) to exit: ");
        if (strcmp(food, "exit") == 0) { break; }
        else { list_of_foods.push_back(food); }
    }
    std::list<char*>::iterator food_iterator = list_of_foods.begin();
    println("Your order is:");
    while (food_iterator != list_of_foods.end()) {
        println(*food_iterator);
        food_iterator++;
    }
}

Upvotes: 1

cigien
cigien

Reputation: 60208

When you call input with a char* template parameter, the body of the function becomes:

// ...
char * temp{};
std::cin >> temp;
// ...

In this case, the char* is not pointing to valid memory, and trying to read a value into that will invoke undefined behavior.

You should just use std::string instead, since a string will be able to read in input without any need for allocating memory manually.

Upvotes: 0

Related Questions