I am writing a program that creates a stack using linked lists. I have all the functionality finished like push(), pop(), top(), etc.
The thing I am trying to figure out is how to remove two values from the stack, add them together, then push that into the stack. This is part of the assignment and we have to continue to do it until all the items are added together and only the sum remains in the stack.
Any help or tips would be appreciated!
EDIT: I solved my problem by just making another function!
Thank you to everyone who tried to help!
Here is my code:
#include <cstdlib>
#include <iostream>
using namespace std;
//Creating a node structure
struct node
{
int data;
struct node *next;
};
//class stack
class stack
{
struct node *top;
int size;
public:
stack()
{
top=NULL;
}
void push(); // insert an element
void pop(); // delete an element
void stackTop(); //retrive top item without removal
void stackSize(); //return the size of the stack
void isEmpty(); // return 1 if empty, 0 if not
void show(); // show the stack
};
//push items into a stack
void stack::push()
{
int value;
struct node *ptr;
cout << "\nEnter a number to insert: ";
cin >> value;
ptr = new node;
ptr->data = value;
ptr->next = NULL;
if(top != NULL)
{
ptr->next = top;
}
top = ptr;
cout<<"\nNew item is inserted to the stack!!!" << endl;
size ++;
}
//remove the top item
void stack::pop()
{
struct node *temp;
if(top == NULL)
{
cout<<"\nThe stack is empty!!!";
return;
}
temp = top;
top = top->next;
cout << "\nPoped value is " << temp->data << endl;
delete temp;
size--;
}
//retrive top value without removing it
void stack::stackTop()
{
struct node *temp;
if(top == NULL)
{
cout<<"\nThe stack is empty!!!";
return;
}
temp = top;
cout << "The top item is: " << temp->data << endl;
delete temp;
}
//show the stack
void stack::show()
{
struct node *ptr1 = top;
cout << "\nThe stack is:" << endl;
while(ptr1 != NULL)
{
cout << ptr1->data << " ->";
ptr1 = ptr1->next;
}
cout << "NULL" << endl;
}
//return if empty or not
void stack::isEmpty()
{
if(top == NULL)
{
cout<<"\nThe stack is empty!!!" << endl;
return;
}
else
{
cout << "\nThe stack is not empty!!!" << endl;
return;
}
}
//return the number of items in the stack
void stack::stackSize()
{
if(top == NULL)
{
cout<<"\nThe stack is empty!!!" << endl;
return;
}
else
{
cout << "\nThe stack has " << size << " items" << endl;
return;
}
}
//main function
int main()
{
stack s;
int choice;
while(1)
{
cout << "\nSTACK USING LINKED LIST" << endl << endl;
cout << "1:PUSH" << endl;
cout << "2:POP" << endl;
cout << "3:DISPLAY STACK" << endl;
cout << "4:RETRIVE TOP ITEM" << endl;
cout << "5:GET THE SIZE" << endl;
cout << "6:IS THE STACK EMPTY?" << endl;
cout << "7:EXIT" << endl;
cout << "Enter your choice(1-7): ";
cin >> choice;
switch(choice)
{
case 1:
s.push();
break;
case 2:
s.pop();
break;
case 3:
s.show();
break;
case 4:
s.stackTop();
break;
case 5:
s.stackSize();
break;
case 6:
s.isEmpty();
break;
case 7:
exit(0);
break;
default:
cout << "\nPlease enter correct choice(1-7)!!!" << endl;
break;
}
}
return 0;
}
Is the interface you have mandatory? Normally you would have your pop() operation return the value you just popped (rather than void), instead of just printing it. If you do that, your problem becomes simple, and you can just repeatedly use your algorithm to add them together.
As a matter of fact, pop(), stackTop(), stackSize(), and isEmpty() should probably all return their values. If the print statements aren't required within the functions, you could then just have your main program print the values it finds.
Related
With the Jetson Nano I connected a PS4 controller via bluetooth and the device showed up under /dev/input/js0. However when I connect the controller via bluetooth to my Coral board, I am seeing nothing at that location, maybe because of Mendel instead of Ubuntu? What is the recommended way to connect a PS4 controller and access it from C++? Is there a different joystick I should use?
After doing some research I learned about the difference between joydev and evdev on linux. It seems my PS4 controller showed up as a joydev device on the Jetson, whereas on the Coral running Mendel it showed up as an evdev device. I found some example C++ code for evdev devices from Croepha
/ David Butler here: https://handmade.network/forums/t/3673-modern_way_to_read_gamepad_input_with_c_on_linux
I modified this code for the PS4 controller like this:
void runJoystick() {
auto gamepad = open("/dev/input/event4", O_RDONLY | O_NONBLOCK); //todo use /proc/bus/input/devices instead
assert(gamepad != -1);
std::cout << "Running joystick" << std::endl;
while (m_still_running) {
struct input_event events[8]; // 8 events per frame is pretty extreme, more like 1 or 2, sometimes as high as 4
auto r1 = read(gamepad, events, sizeof events);
if (r1 != -1) {
int new_event_count = r1 / sizeof(struct input_event);
for (int evi = 0; evi < new_event_count; evi++) {
auto& ev = events[evi];
switch (ev.type) {
case EV_ABS: {
switch (ev.code) {
case ABS_X: { // left x
// std::cout << "type " << ev.code << "value:" << ev.value << std::endl;
} break;
case ABS_Y: { // left y
// std::cout << "type " << ev.code << "value:" << ev.value << std::endl;
} break;
case ABS_Z: { // right x
// std::cout << "type " << ev.code << "value:" << ev.value << std::endl;
} break;
case ABS_RZ: { // right y
// std::cout << "type " << ev.code << "value:" << ev.value << std::endl;
} break;
}
} break;
case EV_KEY: {
switch (ev.code) {
case BTN_A: { // square
std::cout << "Square ";
} break;
case BTN_B: { // x
std::cout << "X ";
} break;
case BTN_C: { // circle
std::cout << "Circle ";
} break;
case BTN_X: { // triangle
std::cout << "Triangle ";
} break;
}
if (ev.value) {
std::cout << "Pressed " << std::endl;
} else {
std::cout << "Released " << std::endl;
}
} break;
}
}
}
assert(r1 != -1 || errno == EWOULDBLOCK || errno == EAGAIN);
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}
I am new to libqmi and wanted to start by just opening a new device. But the callback function is never getting called and therefore no device object returned.
I running the code on Ubuntu 64 Bit.
On this website: https://developer.gnome.org/gio/stable/GAsyncResult.html
I found how this should be handled and programmed it that way, but it still doesn't work.
#include <iostream>
#include <libqmi-glib/libqmi-glib.h>
#include <gio/gio.h>
using namespace std;
void device_create_start(const char* device_file);
void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data);
int something = 0;
int main()
{
cout << "Start\n";
device_create_start("/dev/cdc-wdm0");
cout << "DEBUG: Something: " << something << "\n";
cout << "Stop\n";
return 0;
}
void device_create_start(const char* device_file)
{
GFile* file = g_file_new_for_path(device_file);
if(file)
{
GCancellable* cancellable = g_cancellable_new();
GAsyncReadyCallback callback = device_create_stop;
gpointer user_data = NULL;
cout << "INFO: qmi_device_new starting!\n";
qmi_device_new(file, cancellable, callback, user_data);
cout << "INFO: qmi_device_new started!\n";
cout << "INFO: Waiting!\n";
usleep(10000);
cout << "INFO: Is cancelled?: " << g_cancellable_is_cancelled(cancellable) << "\n";
cout << "INFO: canceling!\n";
g_cancellable_cancel(cancellable);
cout << "INFO: Waiting again!\n";
usleep(100000);
cout << "INFO: Is cancelled?: " << g_cancellable_is_cancelled(cancellable) << "\n";
something = 1;
}
else
{
cout << "ERROR: Could not create device file!\n";
}
}
void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data)
{
cout << "INFO: device_create_stop\n";
something = 2;
cout << "INFO: qmi_device_new_finish starting\n";
GError *error;
QmiDevice* device = qmi_device_new_finish(res, &error);
cout << "INFO: qmi_device_new_finish started\n";
if(device == NULL)
{
cout << "ERROR: Could not create device!\n";
}
else
{
cout << "INFO: Device created!\n";
//device_open(device);
}
}
When I run this code the output is:
Start
INFO: qmi_device_new starting!
INFO: qmi_device_new started!
INFO: Waiting!
INFO: Is cancelled?: 0
INFO: canceling!
INFO: Waiting again!
INFO: Is cancelled?: 1
DEBUG: Something: 1
Stop
The code in the callback function is never called.
Update 1
I simplified the code and changed some things that I oversaw on the gnome reference site, like a static callback function. But this doesn't work either
#include <iostream>
#include <libqmi-glib/libqmi-glib.h>
#include <gio/gio.h>
#include <glib/gprintf.h>
using namespace std;
void device_create_start(const char* device_file);
static void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data);
int something = 0;
int main()
{
g_printf ("Start\n");
device_create_start("/dev/cdc-wdm0");
cout << "DEBUG: Something: " << something << "\n";
while(true)
{
;
}
cout << "Stop\n";
return 0;
}
void device_create_start(const char* device_file)
{
GFile* file = g_file_new_for_path(device_file);
if(file)
{
cout << "INFO: qmi_device_new starting!\n";
qmi_device_new(file, NULL, device_create_stop, NULL);
cout << "INFO: qmi_device_new started!\n";
something = 1;
}
else
{
cout << "ERROR: Could not create device!\n";
}
}
static void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data)
{
g_printf ("Hurray!\n");
something = 2;
}
The new output:
Start
INFO: qmi_device_new starting!
INFO: qmi_device_new started!
DEBUG: Something: 1
Does anyone has a clue why this is not working?
As Philip said (hey Philip!), you're missing the main loop. The qmi_device_new() function is an method that finishes asynchronously, and once finished, the result of the operation is provided in the callback function you provide. In order for the asynchronous function to even do something, you need to have a GMainLoop running for as long as your program logic runs.
I need to read and inject XMP metadatas in an mp4 container.
I know this is possible on android with the "mp4parser" library, but I couldn't find an equivalent for iOS.
For the read part, is it possible to read every footage from the camera roll to inspect their 360 XMP metadatas quickly ?
For the writing, I'm trying to use Adobe's XMP toolkit. I have an mp4 video in a folder, and I want to inject into it some 360 metadatas.
After injecting the metadatas (I suppose it works), I export the video to the camera roll, but it looks like the video is converted to m4v and it lost every metadata I've written. Is it expected, or is my code wrong ?
Here's the code :
MetadataManager.mm
#import "MetadataManager.h"
#define IOS_ENV 1
#include <string>
#define TXMP_STRING_TYPE std::string
#define XMP_INCLUDE_XMPFILES 1
#include "XMP.incl_cpp"
#include "XMP.hpp"
#include <iostream>
#include <fstream>
using namespace std;
#implementation MetadataManager {
}
+ (void)write360Metadatas:(NSString *)filePath {
if (!SXMPMeta::Initialize())
exit(1);
if (!SXMPFiles::Initialize())
exit(1);
SXMPFiles myFile;
XMP_OptionBits opts = kXMPFiles_OpenForUpdate | kXMPFiles_OpenUseSmartHandler;
std::string status = "";
std::string filePathStd = std::string([filePath UTF8String]);
// First, try to open the file
bool ok = myFile.OpenFile(filePathStd, kXMP_UnknownFile, opts);
if( ! ok ){
status += "No smart handler available for " + filePathStd + "\n";
status += "Trying packet scanning.\n";
// Now try using packet scanning
opts = kXMPFiles_OpenForUpdate | kXMPFiles_OpenUsePacketScanning;
ok = myFile.OpenFile(filePathStd, kXMP_UnknownFile, opts);
}
if(ok){
SXMPMeta meta;
myFile.GetXMP( &meta );
displayPropertyValues(&meta);
injectMetadatas(&meta);
// Check we can put the XMP packet back into the file
if(myFile.CanPutXMP(meta))
{
// If so then update the file with the modified XMP
myFile.PutXMP(meta);
}
// Close the SXMPFile. This *must* be called. The XMP is not
// actually written and the disk file is not closed until this call is made.
myFile.CloseFile();
}
}
SXMPMeta createXMPFromRDF()
{
const char * rdf =
"<rdf:SphericalVideo xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'"
" xmlns:GSpherical='http://ns.google.com/videos/1.0/spherical/'>"
"<GSpherical:Spherical>true</GSpherical:Spherical>"
"<GSpherical:Stitched>true</GSpherical:Stitched>"
"<GSpherical:StitchingSoftware>Spherical Metadata Tool</GSpherical:StitchingSoftware>"
"<GSpherical:ProjectionType>equirectangular</GSpherical:ProjectionType>"
"</rdf:SphericalVideo>";
SXMPMeta meta;
// Loop over the rdf string and create the XMP object
// 10 characters at a time
int i;
for (i = 0; i < (long)strlen(rdf) - 10; i += 10 )
{
meta.ParseFromBuffer ( &rdf[i], 10, kXMP_ParseMoreBuffers );
}
// The last call has no kXMP_ParseMoreBuffers options, signifying
// this is the last input buffer
meta.ParseFromBuffer ( &rdf[i], (XMP_StringLen) strlen(rdf) - i );
return meta;
}
void injectMetadatas(SXMPMeta * meta)
{
// Add an item onto the dc:creator array
// Note the options used, kXMP_PropArrayIsOrdered, if the array does not exist it will be created
meta->AppendArrayItem(kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered, "Author Name", 0);
meta->AppendArrayItem(kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered, "Another Author Name", 0);
// Now update alt-text properties
meta->SetLocalizedText(kXMP_NS_DC, "title", "en", "en-US", "An English title");
meta->SetLocalizedText(kXMP_NS_DC, "title", "fr", "fr-FR", "Un titre Francais");
// Display the properties again to show changes
cout << "After update:" << endl;
displayPropertyValues(meta);
// Create a new XMP object from an RDF string
SXMPMeta rdfMeta = createXMPFromRDF();
// Append the newly created properties onto the original XMP object
// This will:
// a) Add ANY new TOP LEVEL properties in the source (rdfMeta) to the destination (meta)
// b) Replace any top level properties in the source with the matching properties from the destination
SXMPUtils::ApplyTemplate(meta, rdfMeta, kXMPTemplate_AddNewProperties | kXMPTemplate_ReplaceExistingProperties | kXMPTemplate_IncludeInternalProperties);
// Display the properties again to show changes
cout << "After Appending Properties:" << endl;
displayPropertyValues(meta);
}
void displayPropertyValues(SXMPMeta * meta)
{
// Read a simple property
string simpleValue; //Stores the value for the property
meta->GetProperty(kXMP_NS_XMP, "CreatorTool", &simpleValue, 0);
cout << "meta:CreatorTool = " << simpleValue << endl;
// Get the first and second element in the dc:creator array
string elementValue;
meta->GetArrayItem(kXMP_NS_DC, "creator", 1, &elementValue, 0);
if(elementValue != "")
{
cout << "dc:creator[1] = " << elementValue << endl;
meta->GetArrayItem(kXMP_NS_DC, "creator", 2, &elementValue, 0);
cout << "dc:creator[2] = " << elementValue << endl;
}
// Get the the entire dc:subject array
string propValue;
int arrSize = meta->CountArrayItems(kXMP_NS_DC, "subject");
for(int i = 1; i <= arrSize;i++)
{
meta->GetArrayItem(kXMP_NS_DC, "subject", i, &propValue, 0);
cout << "dc:subject[" << i << "] = " << propValue << endl;
}
// Get the dc:title for English and French
string itemValue;
string actualLang;
meta->GetLocalizedText(kXMP_NS_DC, "title", "en", "en-US", 0, &itemValue, 0);
cout << "dc:title in English = " << itemValue << endl;
meta->GetLocalizedText(kXMP_NS_DC, "title", "fr", "fr-FR", 0, &itemValue, 0);
cout << "dc:title in French = " << itemValue << endl;
// Get dc:MetadataDate
XMP_DateTime myDate;
if(meta->GetProperty_Date(kXMP_NS_XMP, "MetadataDate", &myDate, 0))
{
// Convert the date struct into a convenient string and display it
string myDateStr;
SXMPUtils::ConvertFromDate(myDate, &myDateStr);
cout << "meta:MetadataDate = " << myDateStr << endl;
}
cout << "----------------------------------------" << endl;
}
#end
Any help would be appreciated, thanks.
I've finally succeeded, using the c++ port of "spatial-media" instead of Adobe's xmp toolkit.
spatial-media (github repository)
I am using openCV's setmousecallback() function to break from the for while loop(of webcam video frames) as soon as user presses mouse right click..
But the program is getting hang instead. Someone can help me please..
Below is the code i am using, please pardon me for any compilation error
//mouse callback funtion
void getMouseLoc(int event, int xCor, int yCor, int flags, void* userInput)
{
Point3_<int> *mouseInputs = (Point3_<int>*)userInput;
mouseInputs->x= xCor;
mouseInputs->y = yCor;
mouseInputs->z = event;
}
// for loop
for( ; ; )
{
camera >> frame;
imshow("averageFrame", aver`enter code here`ageFrame);
setMouseCallback("averageFrame", getMouseLoc, &mouseInputs);
if( mouseInputs.z == EVENT_RBUTTONDOWN)
{
cout << "topmost cordinates of ROI selected by user" << endl;
count << mouseInputs.x << " and " << mouseInputs.y << endl;
break;
}
}
//mouse callback function
void getMouseLoc(int event, int xCor, int yCor, int flags, void* userInput)
{
Point3_<int> *mouseInputs = (Point3_<int>*)userInput;
mouseInputs->x= xCor;
mouseInputs->y = yCor;
mouseInputs->z = event;
}
// this does not have to be inside the loop, once is enough:
Point3_<int> mouseInputs;
setMouseCallback("averageFrame", getMouseLoc, &mouseInputs);
// for loop
for( ; ; )
{
camera >> frame;
imshow("averageFrame", aver`enter code here`ageFrame);
// you're missing a call to waitKey(), else your image won't get updated !!
int k = waitKey(40);
if ( k == 27 ) break; // esc pressed.
if( mouseInputs.z == EVENT_RBUTTONDOWN)
{
cout << "topmost cordinates of ROI selected by user" << endl;
count << mouseInputs.x << " and " << mouseInputs.y << endl;
break;
}
}
#include <iostream>
#include <string>
using namespace std;
struct Node{
Node *next;
int data;
};
int main(){
Node* head = NULL;
int data;
cin >> data;
Node*m = head;
while(data >0){
cout <<"enter a data";
cin >> data;
m -> data = data;
m -> next = m;
}
while(m -> next != NULL){
cout << m -> data << endl;
}
return 0;
}
Here is simple code that takes values when they are greater than 0 and make a linked list. after you enter a negative value, the while loop is terminated and prints the values.
However, the code gives me segmentation fault when it asks enter a data and after it takes the data. I could not solve it, what is the reason?
You get uninitialized pointer here. If you define link to next node as Node *next; you should initialise pointer with address to valid Node object before use.
And
Node* head = NULL;
...
Node*m = head;
...
m -> data = data; // NPE
as you can see, you trying to call member data of NULL object.
How to fix it:
Anways initialize pointer with valid address. For example:
int main(){
Node head;
head.next = NULL;
int data;
cout << "enter a data ";
cin >> data;
Node *prev = &head;
prev->data = data;
while(data >0){
Node *next = new Node();
cout <<"enter a data ";
cin >> data;
next->data = data;
next->next = NULL;
prev->next = next;
prev = next;
}
Node* m = &head;
while(m -> next ){
cout << m -> data << endl;
m = m->next;
}
return 0;
}