Need to input data about multiple structure variables (format - 3 groups of 2 numbers in one line). Used "for" and custom input function (also it calculates some parameters). Now tryed to use "std::cin" :
typedef struct {
short width;
short height;
short left;
short top;
int S;
short orientation;
} Rectangle;
bool input_rectangle(Rectangle* rect) {
short width;
short height;
std::cin >> width >> height;
(*rect).width = width;
(*rect).height = height;
(*rect).S = width * height;
(*rect).top = 0;
(*rect).left = 0;
if(width>height) {
(*rect).orientation = HORIZONTAL;
}
else {
(*rect).orientation = VERTICAL;
}
return width!=0 || height!=0;
}
int main() {
Rectangle* rectangles = new Rectangle[RECTANGLES_COUNT];
...
while(1) {
...
for(int i=0;i<RECTANGLES_COUNT;i++) {
will_continue = will_continue || input_rectangle(&rectangles[i]);
}
if(!will_continue) {
break;
}
else {
int S = calculate(rectangles);
}
...
}
}
It give wrong result. Tryed to add debug output to "calculate" :
for(int i=0;i<RECTANGLES_COUNT;i++)
std::cout << rectangles[i].width << " x " << rectangles[i].height << " = " << rectangles[i].S << "\n";
Example of result.
4 16 6 6 5 10 #my input
4 x 16 = 64 #right
0 x 0 = 0 #??? Must be 6 x 6 = 36
0 x 0 = 0
646 x 6 = 36
0 x 0 = 0
0 x 0 = 0
365 x 10 = 50
0 x 0 = 0
0 x 0 = 0
How can I improve it? Also I tryed to use scanf("%hd %hd", &width, &height); (may ise pure C in this task), but it give same result.
Used g++ compiler / (gcc for pure C version)
From your debug output code, I'm gathering that for your test purposes RECTANGLES_COUNT is actually defined to 3.
Also, since it is able to perform any kind of computations, and given that the || operator is subject to lazy-evaluation, you must be initializing will_continue to false.
What's happening is when your first input (i=0) is in fact valid (i.e. width or height is not 0), will_continue gets set true. Then since true || anything must be true, input_rectangle is no longer called (lazy-evaluation) for i=1,2,... So only rectangle[0] gets set in that loop. When you latter call your debug output in calculate, you show all 3 rectangles' width/height/S including 2 that have presumably been initialized to 0 (and remain to their initial value).
I'm guessing (though not shown) that int S = calculate(rectangles) might in fact assigns the sum of rectangle[i].S (which happens to be equal to rectangle[0].S, since the others are 0s) to S which you are then printing. That would explain the lines containing 646 (64 followed by 6 x 6) and 365 (36 followed by 5 x 5).
I'm guessing what you wanted was probably more along the lines of:
...
while(1) {
...
bool will_continue = false;
for(int i=0;i<RECTANGLES_COUNT;i++) {
will_continue = input_rectangle(&rectangles[i]);
if (!will_continue) {
break;
}
}
if(!will_continue) {
break;
}
else {
int S = calculate(rectangles);
}
...
}
return width!=0 || height!=0;
should be
return width!=0 && height!=0;
Related
I created a program with a function to convert numbers from a string to a numeric variable (the program will be copied below). I started off using a double; however, for some reason, whenever I built it, it kept rounding the last number up or down if I used decimals. I don't understand why so I would be grateful for any insight you guys could share with me.
#include <iostream>
using namespace std;
//variables initialised in a set of curly brackets are called local variables
//variables initialised outside a set of curly brackets are called global variables
// local variables can only be used in that set of curly brackets
// global variables can be used anywhere after it has been declared
// global variables are automatically set to 0 when it has not been assigned a value
//a void function is a function that returns nothing
//StringName.length() returns the length of a string
/*----------------------------------------FUNCTION-------------------------------------*/
int pow(int a, int b){
int c = 1;
for(int i=0;i<b;i++){
c*=a;
}
return c;
}
float StringNoToNo(string a){
float b=0.0;
int y = 1;
int s = 0;
//cout<<"a.length() is: "<<a.length()<<endl;
for(int i = (a.length()); i>0;i--){
// cout<<"the loop: "<<(a.length()-i)<<endl;
int z = a[i-1];
//cout<<"z = "<<z<<endl;
switch(z){
case 48 ... 57:
// cout<<"(a[i]>=48)&&(a[i]<=57) is true"<<endl;
//cout<<"pow(10.0,(a.length()-i)) = "<<pow(10.0,(a.length()-i))<<endl;
//cout<<"a.length() - i = "<<(a.length()- i)<<endl;
b += ((a[i-1]-48)* pow(10.0,(a.length()-i-s)));
// cout<<"b= "<<b<<endl;
break;
case 46:
y=pow(10,(a.length()-i));
// cout<<"y = "<<y<<endl;
if(s==0){
s++;}else{
goto v;
}
break;
default:
v:
// cout<<"(a[i]<48)||(a[i]>57) is true"<<endl;
cout<< "the number was not written properly"<<endl;
return 0;
break;
}
}
//cout<<" b = "<<b<<endl;
//cout<<"b/y = "<<b/y<<endl;
return (b/y);
}
/*----------------------------------------FUNCTION-------------------------------------*/
// overloading functions - you can create multiple functions with the same name so as long
// as they have different parameters.
// as long as the function is declared at the beginning, even if the function meant to
// overload it is written at the end of the code, it can still be used.
main() {
string no;
cout << "write a number: ";
cin >> no;
cout << "the number is: "<<StringNoToNo(no)<<endl;
}
At first, I used the double variable for the function and then changed it to float. After that, I used cout at various parts of the loop to see what was going on at every step of the way but still couldn't understand the problem.
The input and output I get are:
write a number: 1234.6789
the number is: 1234.68
Process returned 0 (0x0) execution time : 4.713 s
Press any key to continue.
Of course, if I remove the // from the cout functions:
write a number: 1234.6789
the number is: a.length() is: 9
the loop: 0
z = 57
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 1
a.length() - i = 0
b= 9
the loop: 1
z = 56
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 10
a.length() - i = 1
b= 89
the loop: 2
z = 55
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 100
a.length() - i = 2
b= 789
the loop: 3
z = 54
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 1000
a.length() - i = 3
b= 6789
the loop: 4
z = 46
the loop: 5
z = 52
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 100000
a.length() - i = 5
b= 46789
the loop: 6
z = 51
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 1000000
a.length() - i = 6
b= 346789
the loop: 7
z = 50
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 10000000
a.length() - i = 7
b= 2.34679e+06
the loop: 8
z = 49
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 100000000
a.length() - i = 8
b= 1.23468e+07
1234.68
Process returned 0 (0x0) execution time : 24.055 s
Press any key to continue.
b= 1.23468e+07 proves that your function isn't rounding, it's returning the correct value.
It's actually cout << that's doing the rounding. Use cout << precision(8) to make it display 8 digits of precision instead of the default of 6 digits.
I'm having an issue with my C++ code that involves receiving input from the user and filling an array based on that input. For my function fillArray(), I need a way to read all inputs from one line and to fill an array with those inputs until the user inputs -1 at the end, something other than a positive integer, or exceeds the threshold of 20 elements.
For example, if I input
1 2 3 4 5 6 -1 on one line, I want the displayArray() function to output 1 2 3 4 5 6, or if i write 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21, I want displayArray() to output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20.
It seems that whenever I input -1 at the end, displayArray() outputs something like
1 2 3 4 5 6 94837 or some arbitrarily big number. If somebody could help me out with this, I'd appreciate it, here's my code:
#include <iostream>
using namespace std;
const int CAPACITY = 20;
void displayArray(int array[], int numElements)
{
for (int i = 0; i < numElements; i++)
cout << array[i] << " ";
cout << endl;
}
void fillArray(int array[], int& numElements)
{
int arrayPosition = 0;
int testArrayPosition = 0;
int testArray[CAPACITY];
bool continueReading = true;
cout << "Enter a list of up to 20 integers or -1 to end the list";
do
{
cin >> valueEntered;
if (valueEntered == -1)
{
continueReading = false;
} else if (valueEntered != -1) {
array[arrayPosition] = valueEntered;
arrayPosition++;
}
} while ((continueReading==true) || (arrayPosition >= CAPACITY));
numElements = (arrayPosition+1);
}
int main()
{
int array[CAPACITY];
int numArrayElements = 0;
fillArray(array, numArrayElements);
displayArray(array, numArrayElements);
cout << "NumArrayElements: " << numArrayElements << endl;
}
The code you posted does not compile. You refer in several places to a variable valueEntered without ever having declared it.
Also, the following construct does not make sense:
if (valueEntered == -1)
{
[...]
}
else if (valueEntered != -1)
{
[...]
Since the condition expression of the second if statement is the exact negation of the condition expression of the first statement, the second if statement is superfluous and can be removed, like this:
if (valueEntered == -1)
{
[...]
}
else
{
[...]
However, since you stated in your question that anything else than a positive integer (not just -1) should cause your program to end, you will want to change that part of your program to the following:
if (valueEntered <= 0)
{
continueReading = false;
}
else
{
array[arrayPosition] = valueEntered;
arrayPosition++;
}
Also, as has already been stated by someone else in the comments section, the line
while ((continueReading==true) || (arrayPosition >= CAPACITY));
should be changed to
while ( continueReading && arrayPosition < CAPACITY )
and the line
numElements = (arrayPosition+1);
should be changed to
numElements = arrayPosition;
I want to ask your help, I want to display a two dimensional array in c++, whose every second two rows are changing periodically between 0 and 1.
For example n = 5, m = 4 the program will write this:
0 0 0 0
0 0 0 0
1 1 1 1
1 1 1 1
0 0 0 0
I'm still a beginner in C++. I tried it myself to see if I could do it.
The only thing you need to know is, when to assign 1 to your row and when to assign 0.
These are the the rows where you have to give every number the value 0:
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18
again:
0,1,4,5,8,9,12,13,16,17
If you look at them like this, they don't make much sense. But if you divide them into two lists like this:
0,4,8,12,16
and
1,5,9,13,17
you can see that the first list consist of numbers, that are the result of n * 4, and the second list is the result of n * 4 + 1
So you just have to make an if-statement where the requirement is
(i%4 == 0 || i%4 == 1)
Here is my complete code. It's probably not the best solution:
#include <iostream>
using namespace std;
int main()
{
const int n = 20, m = 4;
int array[n][m];
int i = 0, j = 0;
while ( i < n)
{
if (j < 4)
{
if (i%4 == 0 || i%4 == 1)
array[i][j] = 0;
else
array[i][j] = 1;
cout << array[i][j] << ", ";
j++;
}
else {
j = 0;
i++;
cout << endl;
}
}
}
In programming, modulus is useful to keep numbers in range not exceeding an upper bound limit.
For example:
int value = 0;
for (int x=0; x<100; x++)
cout << value++%8 << " "; //Keeps number in range 0-7
Output:
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7...
Now consider this situation:
int value = 5;
for (int x=0; x<100; x++)
cout << value-- << " ";
Output: 5 4 3 2 1 0 -1 -2 -3 -4 -5 -6 -7...
My question is: How to set the lower bound limit to 0 WITHOUT using any conditional statement like if or switch case?
Output I want: 5 4 3 2 1 0 0 0 0 0 0 0 ...
How about std::max?
int value = 5;
for (int x=0; x<100; x++) {
cout << value << " ";
value = std::max(0, --value);
}
Use std::max(value,0) or the ternary operator. Both will compile to code without conditional jumps.
Perhaps it can be done with
typedef unsigned u32b;
u32b sat_subu32b(u32b x, u32b y)
{
u32b res = x - y;
res &= -(res <= x);
return res;
}
which is taken from here. More specifically it seems to implement saturated subtraction; the saturated decrement would be
u32b sat_dec(u32bx)
{
u32b res = x-1;
res &= -(res <= x);
return res;
}
and seems to be branch-free.
The two situations are different. As you've shown, the % will make the numbers loop around from 0 to 7, whereas in the negative case you seem to be asking for the max.
Depending on whether you count the ternary operator as a conditional, you could do:
int value = 5;
for (int x=0; x<100; x++)
cout << value > 0 ? value-- : 0 << " ";
This has the side effect that value will no longer be decremented once it has reached 0.
Alternatively, you could use a std::max:
int value = 5;
for (int x=0; x<100; x++)
cout << std::max(0, value--) << " ";
using max function in std.
max function detail:
template <class T> const T& max (const T& a, const T& b) {
return (a<b)?b:a;
}
Alright, so I've been working on a project, and have come to this problem. I get this message when running my program:
Unhandled exception at 0x76fa15de in programmingproj.exe: 0xC0000005: Access violation reading location 0x00000000.
Here is the code that Visual Studio says is the errors:
float **LoadImg(const char *filename)
{
float **data = { 0 };
char *buf = new char[32];
std::string buf2;
std::ifstream filebuf(filename);
filebuf.getline(buf, 32);
// Reiterate over each pixel, very inefficient, needs to be fixed.
for (int x = 0; x < (IMAGE_SIZE_X - 1); x++)
{
for (int y = 0; y < (IMAGE_SIZE_Y - 1); y++)
{
filebuf.getline(buf, 32);
// Only copy the values.
for (int i = 8; i < 32; i++)
{
if (buf[i] != '\t' && buf[i] != ' ')
{
buf2 += buf[i];
}
}
// Set the pixel's value.
data[x][y] = (float)strtodbl(buf2);
}
}
filebuf.close();
return data;
}
Here is a sample of the format I'm trying to read:
x y Value
1 1 0
1 2 0
1 3 0
1 4 0
1 5 10.159
1 6 5.225
1 7 1.337
1 8 0
1 9 0
1 10 0
I only need to load the value field into the proper pixel (x, y).
The strtodbl function is just a quick thing i wrote up to replace atof and/or strtod.
EDIT: IMAGE_SIZE_X and IMAGE_SIZE_Y are just constants for the size of the image (97x56).
You've declared data as a pointer to a pointer, and you're using data but you've never allocated space and set data to point to it. You must do that before you try to read/write what data is supposed to point to.