I've done some self learning in the past with c++ online but gave up, till I bought a textbook on it and giving it another go. In my past research, I never read anything on vector arrays (or maybe I did and don't remember, who knows).
Anyway it says like regular arrays, vector arrays can be created for any data type and I'm trying to get a char vector array going and I'm running into some compile errors take a look.
I want an array of 26 that houses all the letters in the alphabet capitalized. So 65 to 91 I think. If there is and easier way to initialize the array with the letter I'm interested in learning that way.
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector <char> vchChar(26, 65);
for (int iii = 0; iii < vchChar.size(); iii++ )
{
for (int jjj = 65; jjj < 91; jjj++)
{
vchChar(iii) = jjj;
cout << "vchChar(" << iii+1 << ") is:\t" << vchChar(iii) << endl;
}
//cout << "vchChar(" << iii+1 << ") is:\t" << vchChar(iii) << endl;
}
return 0;
}
Originally I had square brackets instead of the parenthesise, fixed that and had hoped it would work but that got a whole set of new problems when I tried changing them in the cout statements. When I had them in square brackets it printed out in the terminal fine no compile errors. So now I have the cout statements like
cout << "vchChar(" << iii+1 << ") is:\t" << vchChar[iii] << endl;
I thought vector arrays where incremented by one from the element before it. But all I got when I printed vchChar into the terminal where all 'A's. So I tried playing around with another for loop to assign them by one from the element before it. I got some different outputs then I'd desired, and cant find the right algorithm to do it.
I'll keep at it, but an answer on this post is just as good for me. I have little idea what I'm doing so post everything you've got, but keep in mind that I probably wont have any idea what you're talking about :S. I've probably left something out because I've change the code a bit when troubleshooting, so if there are any question ask, and thank for your time.
I do not see any sense in your code. If I have understood correctly what you need is the following
#include <iostream>
#include <vector>
#include <numeric>
int main()
{
std::vector<char> vchChar(26);
std::iota( vchChar.begin(), vchChar.end() , 'A' );
for ( char c : vchChar ) std::cout << c << ' ';
std::cout << std::endl;
return 0;
}
Or you can write it even the following way
#include <iostream>
#include <vector>
#include <numeric>
int main()
{
std::vector<char> vchChar( 'Z' - 'A' + 1 );
std::iota( vchChar.begin(), vchChar.end() , 'A' );
for ( char c : vchChar ) std::cout << c << ' ';
std::cout << std::endl;
return 0;
}
If your compiler does not support standard algorithm std::iota and the range-based for statement then you can write
#include <iostream>
#include <vector>
#include <numeric>
int main()
{
std::vector<char> vchChar( 'Z' - 'A' + 1 );
for ( char c = 'A'; c <= 'Z'; ++c ) vchChar[c - 'A'] = c;
for ( std::vector<char>::size_type i = 0; i < vchChar.size(); ++i )
{
std::cout << "vchChar[" << i << "] is:\t" << vchChar[i] << std::endl;
}
return 0;
}
Take into account that it is a bad idea to use magic numbers as 65 or 91. For example if the program will run in an IBM mainframe then the result will be unexpected because there is another coding system, that is EBCDIC instead of ASCII.
As for statement
vchChar(iii) = jjj;
then it is invalid. Expression vchChar(iii) means a call of the operator function with one argument that is not defined in class std::vector.
You have at least the following issues in your code:
Setting a vector element is not done by myVector(index), but myVector[index], so basically the operator[]. In this special case, however, you can just push them in a row to the back.
You are trying to print one element of the array with vchChar(iii), but you should use the .at(index) method.
It is not crucial, but in this special case, you could use the iterator pattern to go through the vector rather than dealing with the indexing. Even if you do not do that, it is needless to use iii and jjj for variable names instead of the regular i and j.
I would prefer to use size_t or the vector<char>::size_type for the loop counters as you compare one of them against the vector size.
You are setting the elements more than once because you have a nested loop.
You are needlessly constructing the vector differently than the default.
You are using hard coded integers rather than actual characters.
Therefore, your correct code would look like this:
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector <char> vchChar;
for (char c = 'A'; c <= 'Z'; ++c)
vchChar.push_back(c);
for (vector<char>::size_t i = 0; i < vchChar.size(); ++i)
cout << "vchChar(" << i+1 << ") is:\t" << vchChar.at(i) << endl;
return 0;
}
Disclaimer: this is just compilation and runtime fix. I have not dealt with use case and design issues. There are better solutions as I partially mentioned them, but I decided to make your code with the least impact.
You do not need nested loops.
{
vector<char> vchChar;
for (char letter = 'A'; letter <= 'Z'; ++letter) {
vchChar.push_back(letter);
}
for (int i = 0; i < (int) vchChar.size(); ++i) {
cout << vchChar[i];
}
}
Related
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
class thing{
public:
vector<unsigned short> vec;
thing(string);
};
int main(){
thing adam("12345");
for(int i = adam.vec.size() - 1;i >= 0;i--){
cout << adam.vec[i] << endl;
}
}
thing::thing(string str){
for(int i = str.size() - 1; i >= 0;i--){
cout << str[i] << endl;
vec.push_back(str[i]);
}
}
I'm trying to make a constructor that takes in a string and fills the vector with the string in reverse, but instead of filling the vector with the values 5,4,3,2,1, it fills it with 53,52,51,59,49. This happens when I call push_back() and I'm confused on why.
I'm trying to make a constructor that takes in a string and fills the vector with the string in reverse
You probably don't really want to do that. As #JesperJuhl suggests - you can always just access the string in reverse. Why the needless copy?
instead of filling the vector with the values 5,4,3,2,1, it fills it with 53,52,51,59,49
You're mistaking the characters '5', '4', '3' with their integer values. The values of string elements are numbers, but those numbers are indices into some character set. Without going into too much detail about - here's the relevant fragment of the character set in your case:
Indeed, the character '5' has index 53 (decimal) within the character set, '4' has 52 and so on.
for(int i = adam.vec.size() - 1;i >= 0;i--)
cout << adam.vec[i] << endl;
Your code to insert in reverse order is working just fine. But you are displaying the vector in reverse order also, so it goes back to previous order. To display in correct order, just use:
thing adam("12345");
for(size_t i = 0; i < adam.vec.size(); i++)
cout << adam.vec[i] << ' ';
cout << endl;
//or
for(const auto &element : adam.vec)
cout << element << ' ';
cout << endl;
Your method for(int i = str.size() - 1; i >= 0;i--){...} for iterating backward works in most cases, but casting size in to int can be a problem. The standard library offers other methods. Example:
thing::thing(string str)
{
std::copy(str.crbegin(), str.crend(), std::back_inserter(vec));
}
Or use iterators to traverse forward or backward.
The purpose of this code is to take a file that has been passed into the program and generate the letter frequency of each letter in the file. In above code, I remove punctuation and convert to lowercase letters.
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
int main()
{
string fileContent = "qr rqh zrxog kdyh eholhyhg lq wkh odvw bhduv ri wkh qlqhwhhqwk fhqwxub wkdw wklv";
int count[26] = { 0 }; // an array the size of the alphabet.
for(int f = 0; f < fileContent.length(); f++) // run til the file end.
{
if(fileContent[f] == 32) // to take care of the spaces.
{
f++; // also tried "continue;" and yeild different and also incorrect results.
}
if(fileContent[f] >= 48 && fileContent[f] <= 57) //take care of numbers.
{
f++; // tried "continue;"
}
count[fileContent[f]]++;
}
for(int p = 0; p < 26; p++)
{
cout << char(p + 97) << ": " << count[p] << endl;
}
return 0;
}
When I run this code I get some accurate frequencies, and some horribly incorrect ones (seems like every other result is wrong, yet after a few letters it trails off into astronomically large numbers). Any way to do this better? what is wrong with this code? As per request I have added some more of the code (including a string with a random 100 in it) as it was apparently not clear enough)
For more context, this program is for a Ceasar shift decoder I'm working on. I am in basic c++ and would greatly appreciate any advise from you more experienced devs. thank you!
In your program, this statement:
count[fileContent[f]]++;
should be:
count[fileContent[f]-97]++; //Assuming that all alphabets are in lowercase
If you do not do -97, it is trying to increase the value at index fileContent[f] of count array, which may be beyond the limit of count array.
Also, make sure to continue in both the if blocks and you don't need to do f++ explicitly in both the if blocks as in the for loop you are already doing f++.
You are doing things the difficult way: using C-style arrays, magic numbers in your code, and risking buffer overflows everywhere.
Compare your code to this:
#include <string>
#include <iostream>
#include <map>
using namespace std;
int main()
{
string fileContent = "qr rqh zrxog kdyh eholhyhg lq wkh odvw bhduv ri wkh qlqhwhhqwk fhqwxub wkdw wklv";
map<char, int> counts;
for (char ch : fileContent)
++counts[ch];
for (char ch = 'a'; ch <= 'z'; ++ch)
cout << ch << ": " << counts[ch] << '\n';
}
Or to print all the map contents (if you do not want to print 0 for letters that did not occur) you can use:
for (auto& item : counts)
cout << item.first << ": " << item.second << '\n';
Exercise for the reader to add in the code to exclude the spaces and numbers. Hint: look up the cctype header.
I'm trying to reverse a string in my C++ code line below revStr.at(j) = str.at(size);
But it doesn't change any of the elements in revStr.
Is there another way to do it without using any libraries.
#include <iostream>
#include<sstream>
#include <iterator>
using namespace std;
int main() {
ostringstream d;
long long c = 123456789;
d << c;
//cout << c << endl;
string str = d.str();
//cout << str.at(0) << endl;
int size = str.size() - 1;
//cout << size << endl;
ostringstream e;
e << str;
string revStr = e.str();
for (int i = size; size==0; size--) {
//cout << str.at(size);
int j = 0;
revStr.at(j) = str.at(size);
j++;
} // End For
cout << "Original String is :" << str << endl;
cout << "Reversed String is :" << revStr << endl;
}
Use std::reverse:
#include <string>
#include <algorithm>
#include <iostream>
int main()
{
std::string test{"Hello"};
std::cout << "Original string: " << test << std::endl;
std::reverse(test.begin(), test.end());
std::cout << "Reversed string: " << test << std::endl;
return 0;
}
Output:
Original string: Hello
Reversed string: olleH
If you just want to reverse a string, you should use std::reverse, as described by Tyler Lewis. It is the best option.
If you want to learn C++, then writing your own version is good practice.
The line
for (int i = size; size==0; size--)
means “Create a new int called i and set it to size initially. Then, while size is zero, do the following and then decrement size”.
There are three problems with this:
Size is not zero unless you entered a one-character string
Since you never use i, there’s no point in declaring it
Inside the loop you use j which is set to zero each time.
You can fix the first by changing the middle part of the for loop to size >= 0 (but be careful—if you later change it so that size is an unsigned type, because it doesn’t make sense for it to be negative, that code won’t work; it’s generally better to increment going up instead). You can fix the second by using i everywhere in the loop statement, and not changing size. You can fix the third by using i in the loop body, and not declaring a new variable inside the loop.
I noticed you used std::string so I used std function swap and string. Depending on if you consider this as a 'library'. There are several definitions of 'reverse'. You could reverse the word order in a string, or a pure char to char reversal like I wrote. Reversal could also mean changing character case, etc... but this is simply swap first and last. Then swap the 2nd and 2nd to last, then swap the 3rd and 3rd to last, etc...
So some points from your code. You only need to loop half the string length. The swap is from the ith and the ith to last. So the last is numCharacters - 1, thus the ith to last would be Last - i or numCharacters - 1 - i. I believe this is what you intended by using a farLeft(i) and a farRight(j) index.
#include <iostream>
void reverseStringInPlace(std::string &stringToReverse)
{
int numCharacters = stringToReverse.length();
for (int i=0; i<numCharacters/2; i++)
{ std::swap(stringToReverse[i], stringToReverse[numCharacters-i-1]); }
}
int main()
{
std::string stringToReverse = "reversing a string";
std::cout << stringToReverse << std::endl;
reverseStringInPlace(stringToReverse);
std::cout << stringToReverse << std::endl;
return 0;
}
Output:
reversing a string
gnirts a gnisrever
Changes made to the piece of code in question, it works.
for (unsigned int i = size; size >= 0; size--) {
revStr[j] = str[size];
j++;
}
My name is Matt. I'm new to StackOverflow and am fairly new to C++. Currently working my way through C++ Primer by Lippman.
I'm doing an exercise in the book, and task is to read integers in to the vector, and then multiply those integers by doing first and last, second and second to last, third and third last etc.
I did it myself without looking anything up, or else I'd barely learn if I just copied... my program compiles and acts as expected. My question is: did I do this correctly? is there a more efficient way of doing it?
I not only want to learn how to make working code, but I want to do it correctly. Thank you in advance!
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
using std::cout; using std::cin; using std::vector; using std::endl;
using std::string;
int main()
{
vector<int> numbers;
int usernum = 0;
cout << "Enter some numbers: ";
while (cin >> usernum)
{
numbers.push_back(usernum);
}
unsigned maxElement = numbers.size() - 1;
unsigned minElement = 0;
for (auto i : numbers)
{
cout << numbers[minElement] << " * " << numbers[maxElement] << " = " << numbers[minElement] * numbers[maxElement] << "\n";
++minElement;
--maxElement;
}
return 0;
}
In a comment, you said:
I've noticed it doesn't actually work as fully expected. It goes through vector and multiplies everything twice as maxElement goes right through to beginning, and minElement goes through to end. Not sure how to stop it once it's only done the operation on each one time.
If you don't want to repeat the multiplications, you need to change the for loop a bit.
for ( ; minElement <= maxElement; ++minElement, --maxElement)
{
cout << numbers[minElement] << " * " << numbers[maxElement] << " = " << numbers[minElement] * numbers[maxElement] << "\n";
}
PS
When you use this logic, you'll need to make sure that minElement and maxElement are of a signed type. Otherwise, you will run into problems if numbers has only one element.
The first thing that feels strange for me is the namespaces you are using.
Instead of doing: using namespace std::vector; you can fairly just do using namespace std; because you call std::vector anyways: vector<int> numbers;***. This applies to any "used" namespace you work with. Just do using namespace std; once and for all.
***I am unsure that std::vector/std::cout/... is even a namespace. std - is a namespace. std::vector should be a class under std namespace:
namespace std
{
template<typename T> class vector<T> {...};
}
How come it "acts as expected". I do not get an idea of this loop: while(cin >> usernum). How do you know when the user input is finished from that point? For a first glimpse (did not compile/run it myself) I expect it either:
not compile
crash at runtime or having undefined behaviour
run the while-loop infinitely
Use this instead:
for (int i = 0, end_of_vector = numbers.size(); i < end_of_vector/2; i++)
{
cout << numbers[i] << " * " << numbers[end_of_vector - 1 - i] << " = " << numbers[i] * numbers[end_of_vector - 1 - i] << "\n";
}
Reasons:
In this case you do not need any special variables to store first and last vector indexes.
You iterate only through a half of an array.
Using for (auto i : numbers), is is expected to use i as an element of numbers vector. But you do not do this, instead, you use numbers as is. Thus, this for-loop is ambiguous
So I am trying to delete duplicate chars in a partially filled array. The array is populated from a file located on my PC. My array population method is working fine; however, my duplicate deleting method is not. Here is my method:
void deleteRepeated(char array[], int* numberUsed)
{
for (int x = 0; x < *numberUsed ; x++)
{
cout << "Positions used: " << *numberUsed << endl;
for (int y = x+1; y < *numberUsed; y++ )
{
cout << "Positions used: " << *numberUsed << endl;
if (array[y] == array[x])
{
cout << "Positions used: " << *numberUsed << endl;
for (int z = y; z < *numberUsed; z++)
array[z] = array[z+1];
y--;
*numberUsed--;
cout << "Positions used: " << *numberUsed << endl;
}
}
}
}
I am passing the entire array, and the number of indices used in that array. The array length is 10, and my tests, I am using 6 out of those 10 with the chars: {'g', 'g', 'n', 'o', 'r', 'e'}. What am I doing wrong?
NOTE: "cout << "Positions used: " << *numberUsed << endl" is being used to check if the method is correctly deleting or not. In the most inner loop where index is z, is where the method starts to go bonkers.
Any help would be much appreciated.
(I wrote the first part of this answer before I read your comment about STL not being allowed, but I'll leave it anyways because I think it's rather neat code.)
You could use the functionality that the C++ standard library makes available to you. Use std::string instead of char arrays (that's nearly always a good idea), then you can do the following (note: C++11 only because of unordered_set and std::begin):
#include <string>
#include <unordered_set>
#include <iostream>
#include <iterator>
std::string uniquechars(const std::string& s) {
std::unordered_set<char> uniquechars(std::begin(s), std::end(s));
std::string newstring(std::begin(uniquechars), std::end(uniquechars));
return newstring;
}
int main() {
std::string teststr("thisisanexamplesentence");
std::cout << "The unique characters of " << teststr << " are " << uniquechars(teststr) << std::endl;
}
Note that it doesn't keep the original order of the characters though, so if that's needed this does not work.
If you have to work without the standard library, you have to dig a bit deeper. #TimChild above already made a good start diagnosing what's wrong with your program, but there are more efficient solutions, for example keeping some kind of record of which characters you have already seen. As you're working with chars, I would consider a bit-field that can hold markers (extra overhead of 256/8=32 bytes) or if that's not too much, just a plain array of bools (extra overhead 256 bytes). As the latter is easier to implement and the code is more legible:
void deleteRepeated(char array[], int *numused) {
bool seenthischar[256] = {false};
char *readpointer = &array[0];
char *writepointer = &array[0];
int length = *numused;
for ( ;readpointer <= &array[0] + length; readpointer++) {
if (seenthischar[((unsigned char) *readpointer)]) {
*numused--;
} else {
seenthischar[((unsigned char) *readpointer)] = true;
*writepointer = *readpointer;
writepointer++;
}
}
}
This only has one loop, so it only has to go through the array once, i.e. its time complexity is linear in the length of the input array.
Every time you find a dup you reduce the number chars used
*numberUsed--;
but remember this controlling the first loop index
for (int x = 0; x < *numberUsed ; x++)
so try this
int count =*numberUsed;
for (int x = 0; x < count ; x++)
this way you visit all the original chars in the array.