QStringList multiple entries and comparison - qt5

I am using QInputDialog::getText to allow the user to input a string. The user should enter an arbitrary number of comma separated integers.
Then I would like to check if there is a duplicate.
In order to convert the input to integers, I have tried the following:
Split the input into a list using the QString::split with comma as an argument
Iterate over the elements of the QStringList
for (int i = 1; i <= list.count(); i++)
{
list.at(i).toInt();
}
The loop leads to a crash.
How to fix this?

Cause
Because the element index in the list is zero-based, i.e. starts from 0 and runs up to count - 1, your loop tries to access a non-existing element with index count and your program crashes.
Solution
Either change
for (int i = 1; i <= list.count(); i++)
to
for (int i = 0; i < list.count(); i++)
or even better, use a ranged for
for (const QString &substr : list)
Then use QList::takeFirst() and QList::contains in a while loop to check for duplicates.
Example
Here is an example I have prepared for you:
#include <QApplication>
#include <QInputDialog>
#include <QMessageBox>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
const QString &str(QInputDialog::getText(nullptr, "Input integers",
"Enter comma separated integers."
" Do not use spaces."));
QList<int> numbers;
bool hasDuplicate = false;
for (const QString &substr : str.split(','))
numbers.append(substr.toInt());
while (numbers.count() && !hasDuplicate)
hasDuplicate = numbers.contains(numbers.takeFirst);
QMessageBox::information(nullptr, "Result",
hasDuplicate ? "There is at least one duplicate"
: "All numbers are unique");
return 0;
}
Result
For the example input of
11,22,33
this message is shown
For the example input of
11,22,33,22
this message is shown

Related

File input not working

I have this C++ program that will get key code and store it as a string in a text file. After I run the program the file is supposed to appear alongside my cpp file but I doesn't appear. I think is got to do with the Save function where the file input and output is happening. Does anyone notices any errors(I get none while compiling).
#include <iostream>
#include <Windows.h>
#include <Winuser.h>
#include <fstream>
using namespace std;
int Save (int Key_Stroke, char *file);
int main(){
char i;
while(1){
for(i = 8; i <= 190; i++){
if(GetAsyncKeyState(i) == -32767){
Save(i, "LOG.TXT");
}
}
}
system("PAUSE");
return 0;
}
int Save (int Key_Stroke, char *file){
if((Key_Stroke == 1) || (Key_Stroke == 2) || (Key_Stroke == 5))
return 0;
FILE *OUTPUT_FILE;
OUTPUT_FILE = fopen(file, "a+");
fprintf(OUTPUT_FILE, "%s", &Key_Stroke);
fclose(OUTPUT_FILE);
cout << Key_Stroke << endl;
return 0;
}
When using C fprintf (this isn't typically used in C++, see ofstream) you don't use reference operator & because you are passing value to function, not address. Also formatting string is wrong, you want to write int %d, not array of chars %s (more here)
Your Save function should look like
int Save(int Key_Stroke, const char *file)
{
if((Key_Stroke == 1) || (Key_Stroke == 2) || (Key_Stroke == 5))
return 0;
FILE *OUTPUT_FILE = fopen(file, "a+");
if(OUTPUT_FILE != NULL)
{
fprintf(OUTPUT_FILE, "%d", Key_Stroke);
fclose(OUTPUT_FILE);
}
cout << Key_Stroke << endl;
return 0;
}
Also notice const keyword in second argument of the function. This should be used to avoid writing to constant area of memory - directly written array of chars "LOG.TXT" .
Next thing, you should always check if the file you are trying to write to is correctly opened if(OUTPUT_FILE != NULL) .

Stange behavior with my C string reverse function

I'm just an amateur programmer...
And when reading, for the second time, and more than two years apart, kochan's "Programming in Objective-C", now the 6th ed., reaching the pointer chapter i tried to revive the old days when i started programming with C...
So, i tried to program a reverse C string function, using char pointers...
At the end i got the desired result, but... got also a very strange behavior, i cannot explain with my little programming experience...
First the code:
This is a .m file,
#import <Foundation/Foundation.h>
#import "*pathToFolder*/NSPrint.m"
int main(int argc, char const *argv[])
{
#autoreleasepool
{
char * reverseString(char * str);
char *ch;
if (argc < 2)
{
NSPrint(#"No word typed in the command line!");
return 1;
}
NSPrint(#"Reversing arguments:");
for (int i = 1; argv[i]; i++)
{
ch = reverseString(argv[i]);
printf("%s\n", ch);
//NSPrint(#"%s - %s", argv[i], ch);
}
}
return 0;
}
char * reverseString(char * str)
{
int size = 0;
for ( ; *(str + size) != '\0'; size++) ;
//printf("Size: %i\n", size);
char result[size + 1];
int i = 0;
for (size-- ; size >= 0; size--, i++)
{
result[i] = *(str + size);
//printf("%c, %c\n", result[i], *(str + size));
}
result[i] = '\0';
//printf("result location: %lu\n", result);
//printf("%s\n", result);
return result;
}
Second some notes:
This code is compiled in a MacBook Pro, with MAC OS X Maverick, with CLANG (clang -fobjc-arc $file_name -o $file_name_base)
That NSPrint is just a wrapper for printf to print a NSString constructed with stringWithFormat:arguments:
And third the strange behavior:
If I uncomment all those commented printf declarations, everything work just fine, i.e., all printf functions print what they have to print, including the last printf inside main function.
If I uncomment one, and just one, randomly chosen, of those comment printf functions, again everything work just fine, and I got the correct printf results, including the last printf inside main function.
If I leave all those commented printf functions as they are, I GOT ONLY BLANK LINES with the last printf inside main block, and one black line for each argument passed...
Worst, if I use that NSPrint function inside main, instead of the printf one, I get the desired result :!
Can anyone bring some light here please :)
You're returning a local array, that goes out of scope as the function exits. Dereferencing that memory causes undefined behavior.
You are returning a pointer to a local variable of the function that was called. When that function returns, the memory for the local variable becomes invalid, and the pointer returned is rubbish.

Why does my program keeps repeating the line even if a valid input is enter?

int main(int argc, const char * argv[])
{
#autoreleasepool {
int userInput= 6 ;
char userChar='\0';
//creating new instances
Dice *a = [[Dice alloc] init];
//creating new objects
Die *d1 = [[Die alloc] initWithSides:&userInput];
Die *d2 = [[Die alloc] initWithSides:&userInput];
//adding dices
[a addDice:d1];
[a addDice:d2];
while(1)
{
printf("Press R to roll dices and Q to exit \n> ");
scanf("%c",&userChar);
if (userChar == 'r' | userChar =='R')
{
for (int i=0; i<10; i++)
{
[a rollDice];
printf("Dice 1 =%d\n",d1.returns);
printf("Dice 2 =%d\n",d2.returns);
printf("The total values of both dice is %d\n",a.totalValue);
printf("Does the dices have same value? Y(1) N(0) => %d\n\n",a.allSame);
}
}
else if (userChar == 'q' | userChar == 'Q')
{
return 0;
}
else
{
printf("Enter a valid command!\n");
}
}
}
}
I tried to create a loop that repeats itself and when r is pressed, do the roll dice and q when user wants to quit the program. otherwise, keep repeating itself until either proper input is enter. but i don't get it why if i enter an input, it will repeat the phase that are in else? Like this,
Press R to roll dices and Q to exit
>l
Enter a valid command!
Press R to roll dices and Q to exit
>Enter a valid command! //Why does it repeats itself here??
Press R to roll dices and Q to exit
>
hey try to use following code it must work.
scanf(" %c",&userChar);
If you enter
l<RETURN>
in your console then there are two characters in the input buffer: the "l" and
a newline.
The first scanf() reads the "l" and the second scanf() reads the newline.
While this can be solved by modifying the scan format, a much better solution to read
an entire line from user input is to use fgets(), e.g.
char buf[100];
while (fgets(buf, sizeof(buf), stdin) != NULL) {
userChar = buf[0];
// ...
}
And note that the logical "or" operator is ||, not |!

How to add a sum of numbers that end in a specific number

First of all sorry if my English is poor.I tried searching for an answer to my dilema without any success for about two hours.I imagine this question is rather easy for you guys, but i just started out with programmin.
So using x code/objective c im trying to add all the numbers from 1 to 500 but only numbers that end in 7.For example like : 7,17,27 and so on.I only want does numbers added up.
What i have :
int main(int argc, const char * argv[])
{
int sum = 0 ;
for (int i = 0; i <= 500; i++) {
if (i%10 == 7) {
sum = sum +i;
}
}
NSLog(#"Total sum is:%i", sum);
return 0;
}
The only change I would make is...
for (int i = 7; i <= 500; i += 10) {
sum += i;
}
This will speed up your sum by a factor of 10.
Of course, you can use arithmetic progression to get a single equation.

Objective c, Scanf() string taking in the same value twice

Hi all I am having a strange issue, when i use scanf to input data it repeats strings and saves them as one i am not sure why.
Please Help
/* Assment Label loop - Loops through the assment labels and inputs the percentage and the name for it. */
i = 0;
j = 0;
while (i < totalGradedItems)
{
scanf("%s%d", assLabel[i], &assPercent[i]);
i++;
}
/* Print Statement */
i = 0;
while (i < totalGradedItems)
{
printf("%s", assLabel[i]);
i++;
}
Input Data
Prog1 20
Quiz 20
Prog2 20
Mdtm 15
Final 25
Output Via Console
Prog1QuizQuizProg2MdtmMdtmFinal
Final diagnosis
You don't show your declarations...but you must be allocating just 5 characters for the strings:
When I adjust the enum MAX_ASSESSMENTLEN from 10 to 5 (see the code below) I get the output:
Prog1Quiz 20
Quiz 20
Prog2Mdtm 20
Mdtm 15
Final 25
You did not allow for the terminal null. And you didn't show us what was causing the bug! And the fact that you omitted newlines from the printout obscured the problem.
What's happening is that 'Prog1' is occupying all 5 bytes of the string you read in, and is writing a null at the 6th byte; then Quiz is being read in, starting at the sixth byte.
When printf() goes to read the string for 'Prog1', it stops at the first null, which is the one after the 'z' of 'Quiz', producing the output shown. Repeat for 'Prog2' and 'Mtdm'. If there was an entry after 'Final', it too would suffer. You are lucky that there are enough zero bytes around to prevent any monstrous overruns.
This is a basic buffer overflow (indeed, since the array is on the stack, it is a basic Stack Overflow); you are trying to squeeze 6 characters (Prog1 plus '\0') into a 5 byte space, and it simply does not work well.
Preliminary diagnosis
First, print newlines after your data.
Second, check that scanf() is not returning errors - it probably isn't, but neither you nor we can tell for sure.
Third, are you sure that the data file contains what you say? Plausibly, it contains a pair of 'Quiz' and a pair of 'Mtdm' lines.
Your variable j is unused, incidentally.
You would probably be better off having the input loop run until you are either out of space in the receiving arrays or you get a read failure. However, the code worked for me when dressed up slightly:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char assLabel[10][10];
int assPercent[10];
int i = 0;
int totalGradedItems = 5;
while (i < totalGradedItems)
{
if (scanf("%9s%d", assLabel[i], &assPercent[i]) != 2)
{
fprintf(stderr, "Error reading\n");
exit(1);
}
i++;
}
/* Print Statement */
i = 0;
while (i < totalGradedItems)
{
printf("%-9s %3d\n", assLabel[i], assPercent[i]);
i++;
}
return 0;
}
For the quoted input data, the output results are:
Prog1 20
Quiz 20
Prog2 20
Mdtm 15
Final 25
I prefer this version, though:
#include <stdio.h>
enum { MAX_GRADES = 10 };
enum { MAX_ASSESSMENTLEN = 10 };
int main(void)
{
char assLabel[MAX_GRADES][MAX_ASSESSMENTLEN];
int assPercent[MAX_GRADES];
int i = 0;
int totalGradedItems;
for (i = 0; i < MAX_GRADES; i++)
{
if (scanf("%9s%d", assLabel[i], &assPercent[i]) != 2)
break;
}
totalGradedItems = i;
for (i = 0; i < totalGradedItems; i++)
printf("%-9s %3d\n", assLabel[i], assPercent[i]);
return 0;
}
Of course, if I'd set up the scanf() format string 'properly' (meaning safely) so as to limit the length of the assessment names to fit into the space allocated, then the loop would stop reading on the second attempt:
...
char format[10];
...
snprintf(format, sizeof(format), "%%%ds%%d", MAX_ASSESSMENTLEN-1);
...
if (scanf(format, assLabel[i], &assPercent[i]) != 2)
With MAX_ASSESSMENTLEN at 5, the snprintf() generates the format string "%4s%d". The code compiled reads:
Prog 1
and stops. The '1' comes from the 5th character of 'Prog1'; the next assessment name is '20', and then the conversion of 'Quiz' into a number fails, causing the input loop to stop (because only one of two expected items was converted).
Despite the nuisance value, if you want to make your scanf() strings adjust to the size of the data variables it is reading into, you have to do something akin to what I did here - format the string using the correct size values.
i guess, you need to put a
scanf("%s%d", assLabel[i], &assPercent[i]);
space between %s and %d here.
And it is not saving as one. You need to put newline or atlease a space after %s on print to see difference.
add:
when i tried
#include <stdio.h>
int main (int argc, const char * argv[])
{
char a[1][2];
for(int i =0;i<3;i++)
scanf("%s",a[i]);
for(int i =0;i<3;i++)
printf("%s",a[i]);
return 0;
}
with inputs
123456
qwerty
sdfgh
output is:
12qwsdfghqwsdfghsdfgh
that proves that, the size of string array need to be bigger then decleared there.