I have been trying different techniques to tackling this problem and I am quite new to C++ or programming in general. This problem comes from a book I'm reading over called "Accelerated C++" and so far I'm only on the 3rd chapter so I'm trying to tackle the problem with only what has been taught in the 3rd chapter. When I run the program it runs fine, but as soon as I input a single word I get a segmentation fault. Could anyone explain to me why that is happening? Also if my ways are extremely inefficient with the knowledge I know so far, hinting towards a better way to do things within the chapter boundaries would be great!
Here is the code:
#include <iostream>
#include <algorithm>
#include <ios>
#include <string>
#include <vector>
#include <iomanip>
using namespace std;
int main()
{
//ask for the first sentence to be typed in.
cout << "Please enter some words: ";
vector<string> word_storage;
vector<int> word_count;
string x;
int y = 0;
//words inputed pushed into vector(word_storage) or incremented if they exist
while(cin >> x) {
for(int i = 0; i <= y; i++) {
if(x != word_storage[i]) {
word_storage.push_back(x);
word_count.push_back(1);
} else {
word_count[i] += 1;
}
}
y++;
}
cout << endl;
//get size of word_storage
typedef vector<double>::size_type vec_sz;
vec_sz size = word_storage.size();
//system prints how many of each word exist
for(int j = 0; j <= size; j++) {
cout << "There are: " << word_count[j]
<< " of the word " << word_storage[j];
}
cout << endl;
return 0;
}
P.S. I apologize in advanced for the eye-sore coding.
Vectors contain their own size. I believe you've probably got two bugs. First, you the '<=' in your for loop is going to walk off the end of the vector, it should be '<'. Second, you're iterating y when you're not adding words to word_storage.
I think you're find part should look more like:
while(cin >> x) {
for(int i = 0; i < word_storage.size(); i++) {
if(x != word_storage[i]) {
word_storage.push_back(x);
word_count.push_back(1);
} else {
word_count[i] += 1;
}
}
}
There are also a few other improvements that could be made, not the least of which would be to use a structure to tie the storage and the count to the same vector, and using iterators. Consider that when you get to those chapters.
for(int i = 0; i <= y; i++) {
if(x != word_storage[i]) {
word_storage is an unintialized/empty vector. And you are trying to access on a empty vector is causing segmentation fault. As an example, at the beginning of the loop, there is nothing in the vector to do an subscript operation on it.
Do the [] operation on the word_storage, if it's size is greater than i.
Related
Several people are playing a game. Every player has a certain individual number of victories and losses (which might be equal or different). Write a program that prints the name and final result of each of them,.
Note: If there is a player with multiple attempts, the victories and losses are added to the final result.
Input
• Until you receive the string "End", you are given the players’ information in the following order:
- Name: string
- Victories: a positive integer
- Losses: a positive integer
using namespace std;
int main() {
char str[100][20], t[20];
int i, j;
int n;
cin >> n;
int first[100];
int second[100];
for (i = 0; i < n; i++) {
cout << " ";
cin >> str[i];
cin >> first[i];
cin >> second[i];
}
for (i = 1; i < n; i++) {
for (j = 1; j < n; j++) {
if (strcmp(str[j - 1], str[j]) > 0) {
strcpy_s(t, str[j - 1]);
strcpy_s(str[j - 1], str[j]);
strcpy_s(str[j], t);
}
}
}
// cout << "\n Names Sorted in Alphabetical Order : \n\n";
for (i = 0; i < n; i++) {
cout << " ";
cout << str[i] << endl;
cout << first[i] - second[i] << endl;
}
return 0;
}
First, Your choice of data structures is questionable. You essentially have three arrays, side by side by side, that must all be maintained together when modifying the "order" of any one of them. That is the crucial piece of logic missing in your code.
Second, you're utilizing none of the standard C++ library, save for IO operations. Although this can compile, and may even work, you're not fulfilling a key attribute of an arbitrary number of entries. You code assumes the first input is a count of players. Nowhere in the problem description is that assumption validated. You should be reading name,victories,losses as a trio continuously until "End" is read for the name and/or you reach eof on stdin (the latter is assumed but safely so). Dynamic storage is required, and the C++ standard library as a multitude of containers available to make that possible, the most common being std::vector
#include <iostream>
#include <vector>
#include <string>
#include <utility>
int main()
{
std::vector< std::string > names;
std::vector< int > wins;
std::vector< int > losses;
std::string name;
int win;
int loss;
while (std::cin >> name && (name != "End") && std::cin >> win >> loss)
{
names.emplace_back(name);
wins.emplace_back(win);
losses.emplace_back(loss);
}
size_t len = names.size();
while (len-- > 0)
{
for (size_t j = 0; j < len; ++j)
{
if (names[j + 1] < names[j])
{
// swap all three arrays
std::swap(names[j + 1], names[j]);
std::swap(wins[j + 1], wins[j]);
std::swap(losses[j + 1], losses[j]);
}
}
}
std::cout << "Names Sorted in Alphabetical Order:\n";
for (size_t i = 0; i < names.size(); ++i)
{
std::cout << names[i] << '\n';
std::cout << wins[i] - losses[i] << '\n';
}
return 0;
}
Note, this is incredibly non-maintainable. As more and more information is associated with each name (not just wins and losses, but perhaps home address, telephone number, playing style or position etc.) maintaining yet more arrays becomes a nightmare. Rather, you opt for an object to host all player information, and single container that holds instances of that object. No doubt you'll be learning more on that in your studies.
But in the meantime, the code above complies with the problem statement, while addressing the key piece of logic missing in your posted code. If you're going to swap names during sorting, you have to swap win/loss records as well, so the player in some arbitrary position n has their wins/losses come along for the ride.
No wonder that someone will whine that it is a homework comment and not to help.
AJod Accrd i think that you need to do a public class and then do a map of string and pair of 2 integers
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n; //currently 7
while(n > 0)
{
for(int i = 0; i < n; i++)
{
if(i != 0)
{
//cout << i << "/" << n << endl;
float test = 1.0 * i / n;
vector<int> total(test);
sort(total.begin(), total.end());
cout << total[i] << endl;
}
}
n--;
}
}
Edit: Pasted my whole code. I am just a bit confused about why it is a segmentation error. I checked the internet and I don't think this is any of "Accessing a freed address", "Improper use of scanf", or an uninitialized pointer.
It's a segmentation error because you're accessing unallocated memory.
total [i]
is never allocated because in the line:-
vector<int> total(test);
the value of test is always 0, i is always less than n inside the loop so i/n must therefore be zero - the C/C++ languages round integer division to zero (and lots of other languages too); so no elements are added to the vector when it is created (you've used the fill constructor).
Why is this do while loop infinitely executing?
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
unsigned int base;
cout << "Base: ";
cin >> base;
for (int i = 1; i <= base; i++) {
int j = 0;
do {
cout << "#";
j++;
} while (j = i);
cout << endl;
};
system("pause");
// keep on building up until you reach 'base'
return 0;
}
I am really confused about this. This program is supposed to create a triangle like this
#
##
###
(user inputs bottom number, so in this example the base = 3)
Anybody help fix my rookie mistake?
You might wanna try while (j == i);.
j = i is a variable declaration/assignment which will always be true as long as it succeeds. It seems like you want to compare the two, so use the equal to operator: ==.
Edit: Made a typo and therefore the same mistake as your question shows. Fixed that.
Like for example:
#include <iostream>
using namespace std;
int main()
{
for (int n=10; n>0; n--){
cout<< n <<", ";}
}
This will output the numbers 10,9,8,7,6,5,4,3,2,1
So is there a new way so I just get the last instance of the loop, the 1?
I new at this and google isn't giving me any answers.
There is no direct way to detect whether the current iteration of a for loop is the last one. But if the behavior of the loop is predictable, you can usually write code that can detect when you're on the last iteration.
In this case, you could do something like:
if (n == 1) {
cout << n << "\n";
}
in the body of the loop. (Of course it would be simpler in this case to replace the entire loop with cout << "1\n";, but I presume this is an example of something more complex.)
In more complicated cases, you can save whatever information you need in the body of the loop:
int value_to_print:
for ( ... ) {
value_to_print = i;
}
std::cout << value_to_print << "\n";
On each iteration, value_to_print is replaced by the current value of i. The final value is the value of i on the last iteration.
You could create a variable (outside the loop) to hold the "current" value of n; whatever happens to the loop (exit condition reached, break, an exception is thrown...) the value will stay there:
int last_n;
for (int n=10; n>0; n--) {
last_n = n;
cout<< n <<", ";
if (something) {
break; // works in this case
} else if (something else) {
throw some_random_error; // works in this case too
}
}
cout << "The last value of 'n' was " << last_n << endl;
You can use a simple if statement for that.
int main()
{
for (int n=10; n>0; n--) {
cout << n << ", ";
if( n == 1 ) {
return n;
}
}
}
The simplest way to accomplish this is: -
#include <iostream>
using namespace std;
int main()
{
int x;
for (int n = 10; n > 0; n--){
x = n;
}
cout << x;
return 0;
}
I'm new to programming too and was trying to figure out something which will allow me to get the last instance of my loop as output.
I tried something and got the output, see if it can help you (if there's a mistake please let me know).
Here user input string is being replaced by "*" and instead of giving output of every instance i have made so only last instance is given as output.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
int string_length;//string length
cout<<"Enter your Email-ID: ";
cin>>str;
string_length = str.length(); //to give the length of input string and use it for the loop
cout<<"lentgh of the string: "<<string_length <<endl;
for(int x = 0; x <= string_length; x++){
str[x] = '*';
while(x==string_length) //string_length is the last instance of the loop
{
cout<<"Here's your Encrypted Email-ID: " <<str<<endl;
break;
}
}
return 0;
}
The two vectors the user enters will always be in alphabetical order, and the function merge_items places those values in one vector seeing which one comes before the other by using the < operator, the code initially gave a segmentation fault and at certain times, it doesn't show the last element.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void merge_items(vector<string>& a1,vector<string>& b1,vector<string>& merged);
int main(){
vector<string> v1,v2;
string a,b;
int n1,n2;
cout << "How many values for v1? " << endl;
cin >> n1;
for(int i = 0;i < n1;i++){
cin >> a;
v1.push_back(a);
}
cout << "How many values for v2? " << endl;
cin >> n2;
for(int i = 0;i < n2;i++){
cin >> b;
v2.push_back(b);
}
vector<string> merge;
merge_items(v1, v2, merge);
for(int i = 0;i < merge.size();i++){
cout << merge[i] << endl;
}
return 0;
}
void merge_items(vector<string>& a1,vector<string>& b1,vector<string>& merged){ int i1 = 0,i2 = 0;
string temp;
while(i1+i2 < (a1.size()-1+b1.size()-1)){
if(a1[i1] < b1[i2]){
temp = a1[i1];
merged.push_back(temp);
i1++;
}else{
temp = b1[i2];
merged.push_back(temp);
i2++;
}
}
}
This is the appropriate way to merge:
std::merge(a1.begin(), a1.end(),
b1.begin(), b1.end(),
std::back_inserter(merged));
As far as what's wrong with your solution. A couple things.
First, once you reach the end of one of the two vectors, you need to stop comparing against that vector and just copy whatever elements are left from the other vector. So you need to compare i1 against a1.size(), separately from your comparison of i2 against b1.size(). With what you're doing now, when you reach the end of one vector, you continue comparing against out of bounds elements from that vector, which is undefined behavior, and likely the cause of your segmentation faults.
Second, you don't need to be subtracting 1 from the size of the vectors. The way you're doing it will leave you with a merged vector which has 2 fewer elements than the combined sizes of the source vectors.