c++ ignoring same number in an array - c++

I have an array of random numbers, for example
6 5 4 4 8
I need to sort it and remove/ignore the same numbers while printing afterwards, so what I did is I sorted everything with bubble sorth algorithm and got something like this
4 4 5 6 8
Now in order to print only different numbers I wrote this for loop
for(int i=0;i<n;i++){
if(mrst[i]!=mrst[i-1] && mrst[i]>0){
outFile << mrst[i] << " ";
}
}
My question is, the array I have is at the interval of [0:12], though the first time when I call it, it checks an array index of -1 to see if there was the same number before, but it doesn't really exist, but the value stored in there usually is a huge one, so is there a possibility that there may be stored 4 and because of it, the first number won't be printed out. If so, how to prevent it, rewrite the code so it would be optimal?

Perhaps, you're looking for std::unique algorithm:
std::sort(mrst, mrst + n);
auto last = std::unique(mrst, mrst + n);
for(auto elem = mrst; elem != last; ++elem)
outFile << *elem << " ";

Well, as you noted already, you cannot do the check mrst[i] != mrst[i-1] in case i == 0. So I'm sure you can think of a way of not doing that check in exactly this case ... (This looks very much like a homework assignment, so I'm not really willing to give you a complete solution, but I guess I hinted enough)
Note also that it's undefined behaviour to access memory outside the boundaries of an array, so what you're doing there can do anything from working correctly to crashing your program, entirely at the discretion of the compiler.

Basically you can read from any place in heap. So mrst[-1] may give you some garbage from the memory. But you really should avoid doing this. In your case you can just change "mrst[i]!=mrst[i-1] && mrst[i]>0" to "i==0 || mrst[i]!=mrst[i-1]".
In c++ "A || B" don't execute "B" if the "A" is ok.

Related

How to output 5th integer from an 8 integer long input? Then tell if 5th integer is even or odd?c++

I'm quite new to c++ and I was not sure how I could output the 5th integer from an 8 integer input? Here is what I have so far:
using namespace std;
void main()
{
int SID, i, x ;
cout << "Pleas enter 8 digits :";
cin >> SID;
cout << "The 5th digit is : " << x << endl;
for (SID = i; i < 10; i++);
if (x % 2 = 0) { cout << "It is even number."; }
else { cout << "It is odd number."; }
As you can see I want to use x as the 5th integer but I am not sure how to code that. I know that using modulus division will determine if the 5th integer is even/odd. I know that using a loop here is mandatory and decided to use a for loop but I feel I did not input it correctly.
Just quickly, becuase I am getting the feeling you are very new to this... I think you need to rethink your question and answer...
Few things to try and think about:
Do you want the user to enter a number (int) with 8 digits? If so then think of what operations you need to perform on 12345678 to get the 5th number.
Do you want the user to enter 8 numbers? If so you will need to store each one of them... If you know where you store them, you know where to go looking for the 5th one. No?
Using a for loop could be useful, but what for? I am not sure if you know what are you trying to use it for? Why did you chose i<10?
Maybe make sure you understand what loops do and how to use them.
Overall you should probably break the problem down and ask specific questions. I don't think this is the place for us to solve your entire problem. Also, I have a feeling that once you break your question down to more specific things the answers would already be on StackOverflow somewhere.
Also as owacoder mentioned it might be a good idea to place the cin >> SID inside a loop.

Strangely For loop counter variable gets reduced by .get()

Consider the following piece of code. This function reads the some integers and strings from a file.
const int vardo_ilgis = 10;
void skaityti(int &n, int &m, int &tiriama, avys A[])
{
ifstream fd("test.txt");
fd >> n >> m >> tiriama;
fd.ignore(80, '\n');
char vard[vardo_ilgis]; // <---
for(int i = 1; i <= n; i++)
{
cout << i << ' ';
fd.get(vard, vardo_ilgis+1); // <---
cout << i << endl;
A[i].vardas = vard;
getline(fd, A[i].DNR);
}
fd.close();
}
and input:
4 6
4
Baltukas TAGCTT
Bailioji ATGCAA
Doli AGGCTC
Smarkuolis AATGAA
In this case, variable 'vard' has a length vardo_ilgis = 10, but in function fd.get the read input is vardo_ilgis+1 = 11 (larger than the variable length in which data is stored). I'm not asking how to fix a problem, because it's obvious not to read more than you can store on a variable.
However, I really want to understand the reason of this behaviour: the loop count variable gets decreased by fd.get. Why and how even can this happen? That's the output of this little piece of code:
1 0
1 0
1 0
1 0
1 1
2 2
3 3
4 4
Why did you use +1 ??
fd.get(vard, vardo_ilgis+1);
Overrunning that buffer corrupts some memory. In a simple unoptimized build, that corrupted memory could be the loop index.
the loop count variable gets decreased by fd.get. Why and how even can this happen?
Once you know why you have caused undefined behavior, many people say you aren't supposed to inquire into the details of that undefined behavior. I disagree. By understanding the details, you can improve your ability to diagnose other situations where you don't know what undefined behavior you might have invoked.
All you local variables are stored together, so overwriting one will tend to clobber another.
You describe the variable being "decreased" when in fact it was set to zero. The fact that it was 1 before being zeroed didn't affect its being zeroed. The undefined behavior happened to be equivalent to i&=~255; which for values under 256 is equal to i=0;. It is more accidental that you could see it as i--;
Hopefully it is clear why i stopped being zeroed once you ran out of input.
fd.get(vard, vardo_ilgis+1); makes buffer be written out-of-bounds.
In your case, the area where you write (and where you should not) is probably the same memory area where i is stored.
But, what's most important is that you end up with the so famous undetermined behaviour. Which mean anything could happen and there is no point trying to understand why or how (what happens is platform, compiler and even context specific, I don't think anyone can predict nor explain it).

Beginner difficulty with vectors and while-loops in C++

Update:
So it turns out there were two issues:
The first is that I checked the [k-1] index before I checked k == 0. This was a crash, although mostly fixable, and not the primary issue I posted about.
The primary issue is that the code seems to execute only after I press ctrl+z. Not sure why that would be.
Original:
So, learning from Stroustrup's text in C++ programming, I got to an example on vectors and tried implementing it myself. The gist is that the program user enters a bunch of words, and the program alphabetizes them, and then prints them without repeats. I managed to get working code using a for statement, but one of my initial attempts confuses me as to why this one doesn't work.
To be clear, I'm not asking to improve this code. I already have better, working code. I'm wondering here why the code below doesn't work.
The "error" I get is that the code compiles and runs fine, but when I input words, nothing happens and I'm prompted to input more.
I'm certain there's an obvious mistake, but I've been looking everywhere for the last 8 hours (no exaggeration) just devoted to finding the error on my own. But I can't.
int main() {
vector<string> warray; string wentry; int k = 0;
cout << "Enter words and I'll alphabetize and delete repeats:\n\n";
while (cin >> wentry) warray.push_back(wentry);
sort(warray.begin(), warray.end());
while (k < warray.size()) {
if (warray[k - 1] != warray[k] || k == 0) cout << warray[k] << "\n";
++k;
}
}
My reasoning for why this should work is this: I initialize my array of words, my word entry per input, and a variable to index word output.
Then I have a while statement so that every input is stacked at the end of the array.
Then I sort my array.
Then I use my index which starts at 0 to output the 0th item of the array.
Then so long as there are words in the array not yet reached by the index, the index will check that the word is not a repeat of the prior index position, and then print if not.
No matter what whappens, the index is incremented by one, and the check begins again.
Words are printed until the index runs through and checks all the words in the array.
Then we wait for new entries, although this gets kind of screwy with the above code, since the sorting is done before the checking. This is explicitly not my concern, however. I only intend for this to work once.
To end the cycle of input you need to insert EOF character which is ctrl+d. However, there are other problems in your code. You have k = 0 to start with so the moment you will try warray[k - 1] your code will crash.
At the point where you take
warray[k - 1]
for the first time, k is zero, so you want to get the warray value at index -1, which is not necessarily defined in memory (and even if, I wouldn't do this anyway). So as it compiles, I guess the address is defined in your case by accident.
I would try simply reversing the OR combination in your if-condition:
if (k == 0 || warray[k - 1] != warray[k])
thus for the first iteration (k == 0) it won't check the second condition because the first condition is then already fulfilled.
Does it work then?
You're stuck in the while loop because you don't have a way of breaking out of it. That being said, you can use Ctrl + d (or use Ctrl + z if executing on windows in the command prompt) to break out of the loop and continue executing the code.
As for while loop at the bottom which prints out the sorted vector of values, your program is going to crash as user902384 suggested because your program will first check for warray[k - 1].
Ideally, you want to change the last part of your program to:
while (k < warray.size())
{
if (k == 0 || warray[k - 1] != warray[k])
cout << warray[k] << "\n";
++k;
}
This way, the k == 0 check passes and your program will skip checking warray[k - 1] != warray[k] (which would equal warray[-1] != warray[0] when k=0).
You just needed to reverse:
if (warray[k - 1] != warray[k] || k == 0)
to
if (k == 0 || warray[k - 1] != warray[k] )
for terminating this condition if k = 0.
An alternative.
Although it can termed as a bit off topic, considering you want to work with std::vector<>, but std::set<> is an excellent container which satisfies your current two conditions:
Sort the strings in alphabetical order.
Delete all the repetitions.
Include <set> in your .cpp file, and create a set object, insert all the std::string and iterate through the set to get your ordered, duplicate-free strings!
The code:
int main() {
//Define a set container.
set<string> s;
//A temporary string variable.
string temp;
//Inserting strings into the set.
while (cin >> temp) s.insert(temp);
//Create a set<int> iterator.
set<string>::iterator it;
//Scanning the set
for(it = s.begin(); it != s.end(); ++it)
{
//To access the element pointed by the iterator,
//use *it.
cout<<*it<<endl;
}
return 0;
}
I just recommended this container, because you will study set in Stroustrup's text, and it is very easy and convenient instead of laboring over a vector.

C++ obtaining the short number after a string in an array of bytes

Hey so following this Question
I've gotten stuck again, and yeah I've tried looking through the web and through my textbook. I know its probably bad posting another question so soon, but I'm truly stumped on this problem. So anyways...
The next part of the assignment asks me to find the age of the person, this age is located on the next byte after the name. Basically if the name was "Bob" it would be
[L][u][k][e][\0][\0][1][5]
where all names with even number of characters get 2 null characters to make it even and then the next two bytes store a short integer. At the moment I have tried looking at the string length and then adding more onto the length before placing that onto the offset, but it doesnt seem to work
if (name.length() % 2 != 0) {
offset += (name.length());
age = *((short*)foo+offset);
cout << age << "\n";
} else {
offset += (name.length());
age = *((short*)foo+offset);
cout << age << "\n";
}
You are missing that C and C++ multiply pointer increments by the size of the object being pointed to. So *((short*)foo+offset) actually adds offset times sizeof(short) bytes to foo.
Or maybe you understand this but don't realise that a cast has a higher precedence than an addition, (short*)foo+offset is ((short*)foo)+offset not (short*)(foo+offset).
Anyway what you want is *(short*)((char*)foo + offset). If foo is already a char* or some similar type, then you can omit the cast to char*.

Compare a value with all array elements in one statement

For example:
if (value == array[size]) //if the value (unique) is present in an array then do something
can this be done in one statement without having to call a function or a basic for loop statement?
std::find can do it in one statement, but it's not as trivial as other languages :(
int array[10];
if (array + 10 != find(array, array + 10, 7)) {
cout << "Array contains 7!";
}
Or with std::count:
if (int n = count(array, array + 10, 7)) {
cout << "Array contains " << n << " 7s!";
}
Depending on the problem, you might want to use a set. It has a member function called count() that tells you if something is in the set:
if(myset.count(value) > 0){
doThings();
}
There is no built-in operator to do such a thing.
There are numerous ways to perform the test as what appears to be a single statement from the outside. And some of which use parts already provided by the standard library, so that you wouldn't have to write much code yourself. However, they will inevitably use some form of function call and/or loop at some point which you already ruled out.
So given the restrictions in your question: No, there isn't any way.