Basic doubt in QT using C++ about making objects - c++

int main (int argc, char* argv[])
{
QApplication app(argc, argv);
QTextStream cout(stdout, QIODevice::WriteOnly);
// Declarations of variables
int answer = 0;
do {
// local variables to the loop:
int factArg = 0;
int fact(1);
factArg = QInputDialog::getInteger(0, "Factorial Calculator",
"Factorial of:", 1);
cout << "User entered: " << factArg << endl;
int i=2;
while (i <= factArg) {
fact = fact * i;
++i;
}
QString response = QString("The factorial of %1 is %2.\n%3")
.arg(factArg).arg(fact)
.arg("Do you want to compute another factorial?");
answer = QMessageBox::question(0, "Play again?", response,
QMessageBox::Yes | QMessageBox::No);
} while (answer == QMessageBox::Yes);
return EXIT_SUCCESS;
}
Link taken from here
originally from above link...
Can you help me out with "QInputDialog..(4th line of do while loop)" How do I get to know about which arguments does it have?
I saw the documentation but i couldnt find out, whats this "0" and "1" in arguments..

Read the docs. Basically - first is a parent widget (NULL in this case), and the 1 after label is a default value.

Related

Qt console application does not work as intended with text based menu and user input handling

I want to write a simple console application with qt (I am planning to extend it with qt stuff like signal slot etc).
The program will have a loop that displays a menu and depending on user input should do some processing.
I have written it in this way but it does not work. I think the problem is where a.exec() should be called....it does not matter if I call it before or after the menu loop ...
void Test(unsigned int s, QString& result) {
qDebug() << "Going to test: " << s;
result = "Not yet filled in :)";
}
constexpr std::string_view menu =
"1: Call function\n"
"q: Quit\n";
int main(int argc, char* argv[]) {
QCoreApplication a(argc, argv);
a.exec();
char response {'\0'};
QString resultHolder;
do {
std::cout << menu;
switch(response) {
case '1':
Test(0, resultHolder);
QTimer::singleShot(500, [&resultHolder]() {
std::cout << "Result is: " << resultHolder.toStdString();
});
break;
case 'q':
a.exit();
break;
default:
std::cout << "Invalid command!";
break;
}
std::cin >> response; // Read char
} while (response != 'q');
a.exit(0);
return 0;
}
How should one write such application with Qt?

Segmentation fault: unable to fix the problem

I'm new to C++, and I'm trying to write a project that interacts through command line. Right now, whenever I run my main (which is the executable), I always receive a segmentation fault error when the main program finished.
Edit comment:
I'm told by tutor to use as little as C++ features such as vectors or strings ... I'm also very new to C++, so i'm trying to utilize as many basic C functions as I can.
I'm
My main function looks like this:
int main(int argc, char** argv) {
cout << "starting mvote..." << endl;
int run_flag = 1;
char* actionBuffer = (char*)malloc(100 * sizeof(char));
char* action = (char*)malloc(16 * sizeof(char));
char* readPtr;
char exit[4] = { 'e','x','i','t' };
//parse command line argumentand get the filename
char* filename = argv[2];
cout << filename;
FILE* fp;
char line[64];
//from here, I'm opening the file and read it by lines
fp = fopen(filename, "r");
if (fp == NULL) {
cout << "file not exists";
return -1;
}
while (fgets(line, 64, fp) != NULL) {
cout << line << "\n";
}
fclose(fp);
while (run_flag == 1) {
cout << "what do you want?\n " << endl;
cin.getline(actionBuffer, 1024);
if (strcmp(actionBuffer, exit) == 0) {
cout << "bye!";
run_flag = 0;
break;
}
//if not exit, Look for the space in the input
readPtr = strchr(actionBuffer, ' ');
int size = readPtr - actionBuffer;
//extract the operation
strncpy(action, actionBuffer, size);
for (int i = 0; i < size; i++) {
cout << "operation:" << action[i];
}
// depend on the operation specified before the first empty space
run_flag = 0;
}
free(actionBuffer);
free(action);
return 0;
}
Description:
I first try to open up a csv file which lies in the same folder as main, and I read the file line by line. Then, I just implement a simple command where you can type exit and quit the program.
I allocate two memory, actionBuffer and action, which are used to hold command
Problem: a segmentation fault [core dumped] always exists when I type exit and hit enter, and then the process finished.
Research: So I learned that segmentation fault is due to accessing a memory that does not belongs to me. But where in my program am I trying to access such a memory?
Any advice is appreciated! Thank you.
Just to give you an idea, this would be an example of C++ code
#include<iostream>
#include<fstream>
#include<string_view>
#include<string>
#include<sstream>
#include<exception>
int main(int argc, char** argv) {
std::cout << "starting mvote...\n";
//parse command line argumentand get the filename
std::string filename = argv[2]; // NO CHECKS!
std::cout << filename <<'\n';
//from here, I'm opening the file and read it by lines
{
std::ifstream ifs(filename);
if (!ifs) {
throw std::invalid_argument("file not exists");
}
std::string line;
while (std::getline(ifs, line)) {
std::cout << line << '\n';
}
}
bool run_flag = true;
while (run_flag) {
std::cout << "what do you want?\n";
std::string userInput;
std::getline(std::cin, userInput);
if (userInput == "exit") {
std::cout << "bye!\n";
return 0;
}
std::stringstream userInputSs(userInput);
std::string operation;
while(userInputSs >> operation){
std::cout << "operation: " << operation << '\n';
}
}
}

Using callback function to retrieve NULL values in C++ / SQLite

I am using C++ and SQLite for a basic messageboard system. I have Datetime fields in my Messages table called 'posted' for the original post date, and 'edited' for the edited date, which is NULL if the message has not been edited. I can post messages successfully but I am running into problems when trying to display posted messages with a NULL edited value.
static int getData(const char* s)
{
sqlite3* DB;
int exit = sqlite3_open(s, &DB);
string sql = "SELECT MSGID, POSTED, EDITED, CONTENT FROM MESSAGES WHERE USERID IS '123' ";
"ORDER BY DATETIME(POSTED) DESC;";
sqlite3_exec(DB, sql.c_str(), callback, NULL, NULL);
sqlite3_close(DB);
return 0;
}
static int callback(void* NotUsed, int argc, char** argv, char** azColName)
{
for (int i = 0; i < argc; i++) {
cout << azColName[i] << ": " << argv[i] << endl;
}
return 0;
}
In the console this returns:
MSGID: 1
POSTED: 2020-03-27 12:14:59
EDITED:
Then diverts to the end of the program without displaying the content value.
I am setting EDITED to NULL when posting a message, and I've also tried leaving out setting the value at all, and entering an empty string, but I'm getting the same problem. If I remove EDITED from the SQL statement, it continues to the end and shows the CONTENT value.
static int getData(const char* s)
{
sqlite3* DB;
int exit = sqlite3_open(s, &DB);
string sql = "SELECT MSGID, POSTED, CONTENT FROM MESSAGES WHERE USERID IS '123' ";
"ORDER BY DATETIME(POSTED) DESC;";
sqlite3_exec(DB, sql.c_str(), callback, NULL, NULL);
sqlite3_close(DB);
return 0;
}
static int callback(void* NotUsed, int argc, char** argv, char** azColName)
{
for (int i = 0; i < argc; i++) {
cout << azColName[i] << ": " << argv[i] << endl;
}
return 0;
}
returns
MSGID: 1
POSTED: 2020-03-27 12:14:59
CONTENT: This is a message
so I assume it is something to do with how the callback function handles the NULL value, but I'm struggling to find guidance on how to display the NULL values and continue with the rest of the For loop.
Thanks!
EDIT:
Following on from Paul Sanders' prompt, I've amended the callback function to the following, which is displaying how I wanted it to:
static int callbackMsg(void* NotUsed, int argc, char** argv, char** azColName)
{
for (int i = 0; i < argc; i++) {
cout << azColName[i] << ": ";
if (argv[i]) {
cout << argv[i] << endl;
}
else
cout << endl;
continue;
}
cout << endl;
return 0;
}
MSGID: 1
POSTED: 2020-03-27 12:14:59
EDITED:
CONTENT: This is a message

How do I make a QAudioOutput object play from a buffer?

int main(int argc, char *argv[])
{
QCoreApplication b(argc, argv);
QBuffer *buffer;
QAudioOutput *a;
QAudioFormat format;
format.setSampleRate(8000);
format.setChannelCount(1);
format.setSampleSize(8);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (info.isFormatSupported(format))
{
cout << "Format supported" << endl;
}
else
{
cout << "Format not supported" << endl;
}
char *data = (char*)malloc(32768 * sizeof(char));
//generating a sound
for (int i = 0; i<256; ++i)
{
for (int j = 0; j<128; ++j)
{
data[i * 128 + j] = (char)j;
}
}
cout << "Created samples" << endl;
//copying into the buffer
buffer = new QBuffer;
buffer->open(QIODevice::ReadWrite);
buffer->seek(0);
buffer->write(data, 32768);
cout << "Filled buffer" << endl;
//playing
QThread thr;
a = new QAudioOutput(format);
//a->moveToThread(&thr);
//thr.start();
//QMetaObject::invokeMethod(a, "start", Q_ARG(QIODevice*, buffer));
a->start(buffer);
system("pause");
return b.exec();
}
I am trying to make my console application output sound and I can't figure out why my QAudioOutput object doesn't do that. I placed the code above. Can you tell me what did I do wrong?
P.S. If i write that vector to a file and play it as raw sound I can hear a low frequency buzz.
First, you definitely shouldn't have system("pause") before your main loop as #Hayt mentioned.
Second, you should seek to the beginning after you've written the data.
buffer->write(data, 32768);
buffer->seek(0);

execvp() causing EXC_SOFTWARE and bizarre cin.getline loop?

I'm running some code on Mac OSX 10.6.6 and XCode 3.2.4 and I have some pretty standard code: fork(), if pid == 0 then execvp with a command and the args (the args include the command as the first element in the array, and the array is null terminated).
We're going over this in my Operating Systems class and our assignment is to write a simple shell. Run commands with their args and switches, both redirects (< and >) and pipe (|). I'm getting several problems.
1) Sometimes I get the EXC_SOFTWARE signal while debugging (so far I haven't gotten it if I run the app outside of XCode, but I'm new to Mac and wouldn't know what that would look like if I did)
2) Sometimes the getline for the next command gets junk that seems to be printed by other couts. This begins looping forever, exponentially breaking. I have tested with printing getpid() with every prompt and only the beginning process prints these out, I don't appear to have an accidental "fork bomb."
Here's what I have so far:
#include <iostream>
#include <string>
#include <unistd.h>
using namespace std;
char** Split(char* buffer, int &count) {
count = 1;
for (int i = 0; i < strlen(buffer); i++) {
if (buffer[i] == ' ') {
count++;
}
}
const char* delim = " ";
char* t = strtok(buffer, delim);
char** args = new char*[count + 1];
for (int i = 0; i < count; i++) {
args[i] = t;
t = strtok(NULL, delim);
}
args[count] = 0;
return args;
}
void Run(char** argv, int argc) {
int pid = 0;
if ((pid = fork()) == 0) {
//for testing purposes, print all of argv
for (int i = 0; i < argc; i++) {
cout << "{" << argv[i] << "}" << endl;
}
execvp(argv[0], argv);
cout << "ERROR 1" << endl;
exit(1);
} else if (pid < 0) {
cout << "ERROR 2" << endl;
exit(2);
}
wait(NULL);
}
int main(int argc, char * const argv[]) {
char buffer[512];
char prompt[] = ":> ";
int count = 0;
while (true) {
cout << prompt;
cin.getline(buffer, 512);
char **split = Split(buffer, count);
Run(split, count);
}
}
It's exactly what I have, you should be able to cut, paste, and build.
I'm not the best at C++, and chances are there's a memory leak when I don't delete split but my main focus is the EXC_SOFTWARE signal and see what I'm doing wrong with my looping issue. Any thoughts?
EDIT:
The assignment requires very limited error checking and I'm assuming all input is correct. By correct I mean properly formatted and limited for my app to run the command, i.e. no bizarre space count, no & to run async, no multi piping commands, etc.
One problem is that you do not check the return from cin.getline(), so if you type EOF, the code goes into a tight loop. You're also leaking memory.
Try:
while (cout << prompt && cin.getline(buffer, sizeof(buffer))
{
int count = 0;
char **split = Split(buffer, count);
Run(split, count);
delete[] split;
}
The code in Split() does not really handle blank lines at all well. It seems to take an aeon to run execvp() when the only arguments are null pointers, which is what happens if you return a blank line.
I'm able to run multiple simple commands (such as 'vim makefile' and 'make shell' and 'ls -l' and 'cat shell.cpp' and so on - I even did a few with more than two arguments) OK with this, and I can quit the command (shell) with Control-D and so on. I have fixed it so it compiles with no warnings from g++ -O -Wall -o shell shell.cpp. I have not fixed the splitting code so that it handles empty lines or all blank lines correctly.
#include <iostream>
#include <string>
#include <unistd.h>
using namespace std;
char** Split(char* buffer, int &count) {
count = 1;
for (size_t i = 0; i < strlen(buffer); i++) { // #1
if (buffer[i] == ' ') {
count++;
}
}
char** args = new char*[count + 1];
const char* delim = " ";
char* t = strtok(buffer, delim);
for (int i = 0; i < count; i++) {
args[i] = t;
t = strtok(NULL, delim);
}
args[count] = 0;
return args;
}
void Run(char** argv, int argc) {
int pid = 0;
if ((pid = fork()) == 0) {
//for testing purposes, print all of argv
for (int i = 0; i < argc; i++)
{
if (argv[i] != 0) // #2
cout << "{" << argv[i] << "}" << endl;
else
cout << "{ NULL }" << endl; // #3
}
execvp(argv[0], argv);
cout << "ERROR 1" << endl;
exit(1);
} else if (pid < 0) {
cout << "ERROR 2" << endl;
exit(2);
}
wait(NULL);
}
int main(int argc, char * const argv[]) {
char buffer[512];
char prompt[] = ":> ";
while (cout << prompt && cin.getline(buffer, sizeof(buffer))) // #4
{
int count = 0;
char **split = Split(buffer, count);
if (count > 0) // #5
Run(split, count);
delete[] split; // #6
}
}
I've marked the significant changes (they mostly aren't all that big). I'm compiling with GCC 4.2.1 on MacOS X 10.6.6.
I can't readily account for the garbage characters you are seeing in the buffer.
You're making the assumption that the input line contains one more token than spaces. This assumption may fail if the input line is empty, ends or begins with a space or contains multiple consecutive spaces. In these cases, one of the calls to strtok will return NULL, and this will crash the forked process when you try to print that argument in Run. These are the only cases in which I've encountered problems; if you've encountered any others, please specify your input.
To avoid that assumption, you could do the counting with strtok the same way you do the tokenizing. That's generally a good idea: if you need two things to coincide and you can do them the same way, you introduce an additional source of errors if you do them differently instead.