Getting character values from an array of strings - c++

I'm trying to practice some c++ stuff and have gotten stuck on something which has been difficult to google or find the answer too.
basically say we have:
char* myarray[] = {"string","hello", "cat"};
how would I got about say getting myarray[1] which is "string" and then traversing through the letter s t r i n g.
I was looking at vectors and wonder if that is the route to take or maybe taking myarray[1] and storing it into another array before iterating through it. What is the best way of doing this

That's very easy in C++11 (using std::string rather than a pointer to an array of characters):
#include <iostream>
#include <string>
int main()
{
std::string myarray[] = {"string","hello", "cat"};
for (auto c : myarray[0]) { std::cout << c << " "; }
}
Output (live example):
s t r i n g

The following code:
for(int i = 0; i < strlen(myarray[0]); i++) {
printf("%c\n", myarray[0][i]);
}
Will print out
s
t
r
i
n
g
If you're looking to practice C++ and not C, I suggest learning std::string and std::vector. They are not always the solution but usually using them first is the right answer. The memory layout of std::vector<std::string> will be different and it is important to understand this.

Related

Want to take a sentence input of words separated by hyphen. Then sort the words in sentence alphabatically and return sentence in same hyphen format?

Example:
Input: this-is-a-sentence
Output: a-is-sentence-the
I am learning C++ so don't know what approach should I use there is time and space constraints.
Here is my code by far:
#include <cstring>
#include <iostream>
#include <sstream>
#include <algorithm>
using namespace std;
int main(){
string words[10];
int j = 0;
string str = "A-computer-science-portal-for-geeks";
for (int i = 0; i < str.length(); ++i) {
if (str[i] == '-') {
str[i] = ' ';
}
}
stringstream ssin(str);
while (ssin.good() && j < str.length()){
ssin >> words[j];
++j;
}
sort(words,words+str.length(),greater<int>());
for(int i = 0; i < str.length(); i++){
cout << words[i] << endl;
}
return 0;
}
What I did is took string input replaced all Hyphens(-) with Space. Saw this sstream method in internet used it to separate the words and append words to array. Now I just have to sort array and return it in hyphen format.
Or just suggest some easy method to do so plz.
I can do it Python but in C++ its bit difficult for me! :)
First things first, change this:
std::sort(words, words + str.length(), std::greater<int>());
which is wrong in many ways, since size of the array words is 10, but the length of str in this case is 35 which is outside the bounds of words, so essentially undefined behavior. In addition, std::greater<int>() is for integers, not for strings.
Consider changing it to this:
// The below line will sort 'words' in lexicographic order followed by empty strings
std::sort(std::begin(words), std::end(words), [] (std::string const& a, std::string const& b) {
return a < b && a != "";
});
This will sort the array of strings properly.
Secondly, look at this snippet:
for (int i = 0; i < str.length(); ++i)
if (str[i] == '-')
str[i] = ' ';
std::stringstream ssin(str);
while (ssin.good() && j < str.length()){
ssin >> words[j];
++j;
}
Now, the above is inefficient as you would need to convert all the hyphens into spaces by iterating through the whole string and then proceed to extract the words from the string. Moreover, this snippet is also prone to undefined behavior for the same reason as above. (Because of j < str.length())
Instead, you can just directly extract the words from the string using std::getline(ssin, words[j], '-'):
std::stringstream ssin(str);
// Extracts all words separated by '-' and puts them inside 'words'
for (int j = 0; std::getline(ssin, words[j], '-'); j++);
Final runnable code:
#include <iostream>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <string>
int main(){
std::string words[10] = {};
std::string str = "A-computer-science-portal-for-geeks";
std::stringstream ssin(str);
for (int j = 0; std::getline(ssin, words[j], '-'); j++);
std::sort(std::begin(words), std::end(words), [] (std::string const& a, std::string const& b) {
return a < b && a != "";
});
for (auto it = std::begin(words); it != std::prev(std::end(words)); ++it)
std::cout << *it << (std::next(it)->empty() ? "" : "-");
}
Do note that the behavior of the above program is undefined when your string contains more than 10 words separated by hyphens. Consider increasing that limit if needed, or just use std::vector<std::string> which resizes dynamically:
#include <iostream>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>
int main() {
std::vector<std::string> words;
std::string str = "A-computer-science-portal-for-geeks";
std::stringstream ssin(str);
while (std::getline(ssin, [&words] () -> std::string& {
words.emplace_back();
return *words.rbegin();
}(), '-'));
std::sort(std::begin(words), std::end(words), [] (std::string const& a, std::string const& b) {
return a < b && a != "";
});
for (auto it = std::begin(words); it != std::prev(std::end(words)); ++it)
std::cout << *it << (std::next(it)->empty() ? "" : "-");
}
sort(words,words+str.length(),greater<int>());
First of all, you're passing greater<int>() which is a struct object with () operator overload that compares two ints as (first > second) but your array is of std::string so greater<std::string>() is what you should be using. Or you could just use std::greater<>() and let the comparison call deduce the type.
Second, str.length() is the number of characters in str, not the words. So you should use sort(words, words + count_of_words, std::greater<>()) instead.
for(int i = 0; i < str.length(); i++){
cout << words[i] << endl;
}
Same in last loop, you're accessing out of bounds and invoking undefined behavior as str.length() > 10. It should be i < count_of_words.
You can use j as count_of_words here resulting in:
sort(words, words + j,std::greater<>());
for(int i = 0;i < j;i++)
This is maybe too advanced for you, but I would like to show it to you anyway.
Maybe you can get a better understanding of the power of modern C++. Modern C++ has many predefined library functions. You can look in CPP reference (https://en.cppreference.com/w/) for details. But sometimes it is hard to understand for starters.
Basically, just 3 lines of code are necessary.
Let us divide your problem in smaller parts. You want to split a sentence in smaller parts (words). The parts(words) are separated by a hyphen (-). The resulting words need to be stored somewhere.
To drill down further, you need a “storage”. You have chosen a fixed size C-style array with 10 elements. That will work for your approach, but in general not. Because it has a fixed size and cannot grow dynamically. What is the solution? The std::vector. It is the common solution for dynamic growable storage areas and used everywhere. The usage is quite similar to a C-style array, but it is much more powerful. And best of all. It grows as needed. Dynamically.
Additionally it has many constructors, that help to initialize elements of the std::vector. One of them is a constructor that is taking a begin and an end iterator. And it will initialize the elements of the std::vector with all elements pointed to and in the range of the iterators.
Good, next. Splitting a string. That is a very old and common task. Often it is called “Tokenize”, because we will split a string into Tokens. And the tokens can be specified using patterns. And patterns can be specified using regular expressions. And those are available as std::regex.
Putting all this together, we can define a std::vector as
std::vector words
and initialize it with iterators. And we will use the std::sregex_token_iterator for that. It will iterate over all words, or, in our case, over all “things” separated by a hyphen.
So,
std::vector words(std::sregex_token_iterator(test.begin(), test.end(), separator, -1), {});
Will split the text into words and store the results in the std::vector. By the way. In this case the std::vector does not need a type (like std::string), because the type can be deduced from the parameters. This is a C++17 feature and called CTAD.
The next step is really easy. Sorting the words. We will simply use the available std::sort function. I guess, no further explanation necessary.
And last but not least, we want to show the result to the user.
Also, for output activities, we have an iterator. The std::ostream_iterator will output anything for us. With that, we can simply “copy” (using std::copy) all words to std::cout. The copy-function will simply “invoke” the iterator, and this guy will output the current value.
Because we do not want an hyphen at the very end of the output, we use a std::ostream_joiner which works like the before, but omits the last hyphen.
Then, finally, we get the following example code:
#include <experimental/iterator>
#include <vector>
#include <iostream>
#include <string>
#include <regex>
#include <algorithm>
const std::regex separator{R"(-)"};
const std::string test {"A-computer-science-portal-for-geeks"};
int main() {
std::vector words(std::sregex_token_iterator(test.begin(), test.end(), separator, -1), {});
std::sort(words.begin(), words.end());
std::copy(words.begin(), words.end(), std::experimental::make_ostream_joiner(std::cout, "-"));
return 0;
}
This program has been compiled and tested with
X86-64 GCC 11.2 and x86-64 clang 12.01.1 using C++ 17 language (-std=c++17)
on site: Compiler Explorer (godbolt.org)

C++ beginner, Access Violation when trying to print out values

I've recently started learning c++ after 5 years with python and am struggling quite a bit when it comes to loops. the whole for(;;) business.
in python i was used to:
for x in y:
print(x)
> x
> y
> z
however in c++ i seem to need two semi-colons like
for(;;)
what i would like to do is print the paths of my directories given in the below code. Thank you for your time!
#include <windows.h>
#include <string>
#include <iostream>
#pragma comment(lib, "user32.lib")
using namespace std;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// -- main
int main(void) {
// -- console
SetConsoleTextAttribute(hConsole, 12);
// -- paths
string ScanDir[2] = {"C:/Users/Stephen/Downloads/", "C:/Users/Stephen/Documents/"};
// -- loops
for (int i = 0; i < ScanDir->length(); ++i) {
string ss = ScanDir[i];
cout << ss.c_str() << "\n";
}
return 0;
}
here is the error:
error screenshot
In C++ arrays are not objects in the OOP sense and do not have methods. They are just a dumb block of memory.
ScanDir->length()
is not getting the length of the array. Instread ScanDir is decaying to a pointer to the first string in the array and length is being called on this string. As a result
for (int i = 0; i < ScanDir->length(); ++i)
iterates length of the first string times, not length of the array, and shoots off the end of the array and into the unknown. This invokes Undefined Behaviour which in this case lead to a crash.
The smart thing to do is use a Range-based for loop
for (const auto & dir: ScanDir) {
cout << dir.c_str() << "\n";
}
which figures out the dimensions for you. Some additional reading on the const auto & bit: What is the correct way of using C++11's range-based for?
You can also use
for (int i = 0; i < std::size(ScanDir); ++i)
if compiling to C++ 17 or better or replace the magic number 2 in
string ScanDir[2] = {"C:/Users/Stephen/Downloads/", "C:/Users/Stephen/Documents/"};
with a constant that can be used wherever the size of the array is required.
Another alternative is replace the array with a smarter container like std::array
std::array<std::string, 2> ScanDir = {"C:/Users/Stephen/Downloads/", "C:/Users/Stephen/Documents/"};
which has a size method.
ScanDir->length() is the length of your strings which is notably greater than 2. You can either use 2 as upper loop boundary or sizeof(ScanDir) / sizeof(ScanDir[0]), or type the loop itself as for(auto const &ss: ScanDir) count << ss.c_str() << '\n';.

Printing all longest matching substrings

I have an assignment for finding all of the longest matching sub-strings between the strings "B D C A B A" and "A B C B D A B". There are a lot of partial solutions to this online but none that do what I need them to. I created this to find one longest matching sub-string, but I need to be able to find all of them, there should be 6 in total.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void myLMS(string one, string two);
int main()
{
string s1 = "ABCBDAB";
string s2 = "BDCABA";
myLMS(s1, s2);
return 0;
}
void myLMS(string one, string two) {
vector<vector<char>> lms;
vector<char> one_lms;
for (int i = 0; i < two.length(); i++) {
for (int j = i + 1; j < one.length(); j++) {
if (two[i] == one[j]) {
one_lms.push_back(two[i]);
break;
}
}
}
lms.push_back(one_lms);
for (int i = 0; i < lms[0].size(); i++) {
cout << lms[0][i];
}
}
Is there a way for me to continue with this method and get the outcome I'm looking for or is another approach needed?
Edit: I found this solution https://www.geeksforgeeks.org/printing-longest-common-subsequence-set-2-printing/
but I'm not really interested in just copying from a program as that doesn't really help me. It also only accomplishes half of what I'm trying to do.
From the assignment prompt it looks like the first three strings printed from this example are there as well as the same three only backwards. Reversing the strings doesn't get those backwards sub-strings so how would they be calculated?
Your logic is incomplete by quite a bit. Here's some pseudo-code to help you get started.
for each character in string 1
for each character in string 2
if char_1 == char_2
possible substring match
do the next chars match?
yes
there is a substring - now find longest
no
no substring match, continue the loop
I can't understand what's the need to solve it in this manner since your input strings are fixed you run for loops from first char of one string to last -1 char and and run another nested for loop for each subsequent characters if a match is found like the program of finding out common substring that all of us have done in the beginning.

calculating occurrences of values in an input stream

I am a college student who is currently learning programming. one of the problem statements given to us was:
user inputs an integer n followed by n different integers. Without using arrays or strings, find the number which occurs the most number of times in the input stream.
we are required to use the simplecpp package which is basically easier commands than standard c++. for example we write repeat(n) to get a for loop with n iterations.
What can i do to solve the problem?.
I thought of creating a number like
10101010[number]10101010[number2]...
to store the input and then splitting but this fails to solve the problem.
we are not allowed to use anything like while loops or string manipulation to solve the problem.the only solutions i could think of were using the string method and then manipulating the string but apparently that is not allowed.
Any method to do this and such other problems where input cannot be stored in an array?
Assuming you are allowed to use normal streaming, and other std:: headers, that are not specifically forbidden
#include <iostream>
#include <map>
#include <algorithm>
using counter = std::map<int, int>;
using element = std::map<int, int>::const_reference;
bool compare_second(element lhs, element rhs)
{
return lhs.second < rhs.second;
}
int main()
{
counter data;
int n = 0;
std::cin >> n;
for (int i = 0; i < n; ++i)
{
int current = 0;
std::cin >> current;
data[current]++;
}
if (n > 1)
{
std::cout << std::max_element(data.begin(), data.end(), compare_second)->second;
}
return 0;
}

How to flip a part of an array?

I need to flip a part of an array, keeping the rest unchanged.
I have a function that flips and entire array, but... To use it, I have to take a part from my array, flip it with the function and paste it on its place. It's uncomfortable and not so fast. I need a method that works very fast.
Example:
int array[10] = {1,2,3,4,5,6,7,8,9,10};
flip(array,2,6); //Flip the part between index 2 and 6
After that, the array should look so:
{1,2,7,6,5,4,3,8,9,10}
Please, help, I need a really quick answer...
There is an algorithm in the standard library exactly for this: void reverse( BidirIt first, BidirIt last );
Here is an example of how to solve your problem with std::reverse function.
#include <algorithm>
#include <iostream>
int main() {
int array[10] = {1,2,3,4,5,6,7,8,9,10};
std::reverse(array + 2, array + 7);
for (int i = 0; i < 10; ++i) {
std::cout << array[i] << " ";
}
}
Please note that I replaced indices 2 and 6 in your example with 2 and 7. This is because std::reverse reverses the elements in the range [first, last).