I am attempting to take char input from the user, and typecasting it to integer, such the A = 1; B = 2...Z = 26; and store it in an array.
This is the code:
#include <iostream>
using namespace std;
int main(){
char input;
int f[8];
int counter;
for(counter = 0; counter <= 8; counter++){
cin >> input;
f[counter] = (int)input - 64;
if(input == '\n') break;
}
cout << f[0] << endl; }
the if(input = '\n') break; line gives me an error. I am trying to break the loop on entering a new line. What's wrong in that? I am attempting to do this as I am taking 2 lines as input(which isn't important information here).
Why does this code in C++ give me a runtime error?
Because you don't use safe high-level facilities like std::array or std::vector instead of error-prone raw arrays.
The error you made causes undefined behaviour. int f[8]; is an array with 8 elements, indexed from 0 to 7, yet later on, in your loop your condition says counter <= 8, which includes 8. It should be counter < 8. Accessing f[8] is undefined behaviour.
Undefined behaviour means the compiler can build any behaviour into your program, including a crash with an error message.
Here's a safer, modern version of your program:
#include <iostream>
#include <array>
int main() {
std::array<int, 8> f;
for(auto&& element : f) {
char input;
std::cin >> input;
element = static_cast<int>(input) - 'A' + 1;
}
std::cout << f[0] << "\n";
}
Some changes:
Used std::array.
Replaced C-style cast with static_cast.
Used a C++11 range-based for loop. No need to hard-code the array's size in the loop condition.
Removed using namespace std;, which is almost always bad practice and which beginners should not use at all.
Removed your \n check, which will never work because std::cin >> input; disregards all whitespace. You will have to use std::getline to get the behaviour you want. In fact, you will want to do this anyway to get some actual error handling into your program.
Minimised scope of local variables.
The character A is not guaranteed to have the integer value 65. It's safer (and more readable) to write 'A'.
The program is giving you a runtime error because your Array loop is out of bounds. for(counter = 0; counter <= 8; counter++).
You should use for(counter = 0; counter < 8; counter++).
operator >> here skips whitespace by default, which includes newline characters - so you will never see one.
To avoid that you need to use cin.get(). There are other alternatives - you could use getline to read a line at a time and then parse the string you get.
Fixing your subscript out of bounds would be a good idea too, of course.
Related
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';.
I am new in C++.
I encountered in question to find the vowels(i.e. "a","e","i","o","u") in a sub string,
and then I was thinking about change the driver function to get user input.
Unfortunately, this code did not generate execution file in Visual Studio Code nor any error messages.
Any help would be highly appreciated.
FYI, the function code was from GeeksforGeeks.
Thanks!
#include <stdio.h>
#include <string>
using namespace std;
// return true if x is vowel
bool isVowel(char x){
// function to check if x is in vowel or not
return (x == 'a' || x == 'e' || x =='i' || x == 'o' || x=='u');
}
void(FindSubString(std::string str)){
set<char> hash; // to store vowel
// outer loop picks starting characters
// and inner loop picks for ending characters
int n = str.length();
for (int i =0; i<n; i++){
for (int j = i; j <n; j++){
// if current position is not vowel,
// then no more possible string starting from str[i]
if (isVowel(str[j])==false)
break;
// if vowel, insert into hash
hash.insert(str[j]);
//if all vowels are present in current substring
if (hash.size()==5)
cout << str.substr(i, j-i+1) << " ";
}
hash.clear();
}
int main()
{
string str = getstring("insert a string: %s\n", stdin);
FindSubString(str);
return 0;
}
}
So, as mentioned in the comments, there are a number of fatal compiler errors in your code (when I run it through Visual Studio's C++ compiler as is, I get 7 errors - so I'm not sure how you are seeing none).
First, you have a missing closing brace (}) at the end of that function (seemingly, it is after the body of main, instead). Moving the } from the very end of the code to its proper place at the end of the FindSubString function will fix that. (This may be a copy-paste error, or you may be trying to define main inside FindSubString, but that's not allowed in C++.)
Second, you have the wrong and missing header files. Generally, for C++ programs, you should use the <iostream> header rather than <stdio.h>. The latter is generally used for C programs; however, it can be used in C++, but you'll need <iostream> if you want to use std::cout and std::cin. (I'm not sure if this is part of the Standard, but many implementations automatically include stdio.h when you include iostream.) You also need to #include <set> to make use of the std::set container.
And, the last of the fatal errors is your call to getstring. This is not a standard library function. So, you can either define this yourself, or just use the code in the main function below:
int main()
{
string str;
cout << "insert a string: ";
cin >> str;
// string str = getstring("insert a string: %s\n", stdin);
FindSubString(str);
return 0;
}
There is also a 'peculiarity' (though not actually an error, as my first version of this answer suggested) in the way you define your FindSubString function, with the 'extra' (unneeded, and very confusing) set of parentheses. It should be just this:
void FindSubString(std::string str)
{
However, even with all these errors fixed, your code does not work! This is because of a flaw in your logic, in the inner for loop of your FindSubString function. As you have it, that loop will terminate (because of the break; statement) on the first occurrence of a non-vowel.
You should, instead, check if the test letter is a vowel, and insert into the hash set if so. I'm not entirely sure what your definition of a sub-string is, but this code does something approaching what I think you want (feel free to clarify your goal, or correct my assumption):
void FindSubString(std::string str)
{
set<char> hash; // to store vowel
int n = str.length();
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
if (isVowel(str[j])) hash.insert(str[j]); // if vowel, insert into hash
//if all vowels are present in current substring
if (hash.size() == 5)
cout << str.substr(i, j - i + 1) << " ";
}
hash.clear();
}
}
The code shown will find all substrings containing the five vowels.
Sample input:
facetiously
Output:
facetiou facetious facetiousl facetiously acetiou acetious acetiousl acetiously
i am stuck on a problem where, after taking input of an array and sorting it and not doing any operation on it at all, the output shows a different array?
#include <bits/stdc++.h>
using namespace std;
int main() {
// your code goes here
int t;
cin>>t;
while(t--){
int n;
cin>>n;
long long int c[n],h[n],a[n];
for(int i=0;i<n;i++){
cin>>c[i];
}
for(int i=0;i<n;i++){
cin>>h[i];
}
sort(h,h+n);
for(int i=0;i<n;i++){
a[i]=0;
}
int i=0;
int begin=(i+1)-c[i];
int end = (i+1)+c[i];
int j=begin;
while(i<n){
a[j-1]++;
j++;
if(j>end){
i++;
begin=(i+1)-c[i];
end= (i+1)+c[i];
j=begin;
}
}
sort(a,a+n);
for(int i=0;i<n;i++){
cout<<h[i]<<" ";
}
}
return 0;
}
input for h[]={8,8,8,8,8}..n=5
output h[]={10,10,9,9,8}
Here is a version of your code written in reasonably decent C++. I didn't touch the loop in the middle because I have no clue what it's doing. You're using obscure variable names and no comments and doing all kinds of bizarre things with indexes and mixing them up with user input.
Now, reading indexes from user input and using them isn't bad, though in a real program you'd want to be doing lots of bounds checking on that input to make sure people weren't feeding you bad data. But doing all that stuff with such poorly named variables with no explanation is going to leave anybody looking at it scratching their head. Don't do that.
Also, avoid the use of begin and end as variable names, especially if they hold indexes. In most cases it will confuse things terribly as begin and end are important identifiers in the standard library and always refer to iterators, which are sort of like indexes, but most definitely not indexes, adding greatly to the confusion. beginidx and endidx could be acceptable substitutes in this case.
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
using ::std::vector;
using ::std::sort;
using ::std::copy_n;
using ::std::copy;
using ::std::fill;
using ::std::istream_iterator;
using ::std::ostream_iterator;
using ::std::cin;
using ::std::cout;
int main() {
// your code goes here
using vec_el_t = long long int;
int t;
cin >> t;
while (t--) {
int const n = []() { int n; cin >> n; return n; }();
vector<vec_el_t> c{n}, h{n}, a{n};
copy_n(istream_iterator<vec_el_t>{cin}, n, c.begin());
copy_n(istream_iterator<vec_el_t>{cin}, n, h.begin());
// Suggested debugging code:
// cout << "h before sort: "
// copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
// cout << '\n';
sort(h.begin(), h.end());
// Suggested debugging code:
// cout << "h after sort: "
// copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
// cout << '\n';
fill(a.begin(), a.end(), 0);
// Weird, unexplained algorithm begins here
int i = 0;
int begin = (i + 1) - c[i];
int end = (i + 1) + c[i];
int j = begin;
while (i < n) {
a[j - 1]++;
j++;
if (j > end){
i++;
begin = (i + 1) - c[i];
end = (i + 1) + c[i];
j = begin;
}
}
// Weird unexplained algorithm ends here
sort(a.begin(), a.end());
copy(h.begin(), h.end(), ostream_iterator<vec_el_t>{cout, " "});
}
return 0;
}
Changes made... Use vector not a variable length array, which isn't valid C++ anyway and will only work in g++ and clang. Don't use explicit loops if there is an algorithm that will do the job. Try to make as many things const as you can so you can make sure that the compiler catches it if you try to change things you didn't mean to change. Avoid using std; and if you want to import names from ::std import exactly the ones you need. Don't use compiler or library implementation specific header files and use the ones from the standard instead (i.e. no bits/stdc++.h).
As for your problem, I have no idea. I suspect that the index manipulation combined with looping isn't doing what you expect. If you print out the arrays before and after sorting, you will discover that sort only alters order, and not content.
As a general rule, always suspect your own code first and make absolutely sure it's correct. And if you really think it's the library code, prove it beyond a shadow of a doubt before coming here to ask why the library isn't doing what it says it does.
The complicated code I didn't touch looks rife with opportunities for out-of-bounds access, and that results in undefined behavior, which means your program might do absolutely anything in that case. You might change uses of operator [] with calls to the at function (one of the many perks of using vector) instead. That way, attempts at out-of-bounds access will throw an exception.
Within these lines you are accessing a outside its limits:
int i=0;
int begin=(i+1)-c[i]; // begin = 1 - c[0]; <<-- this could be arbitrarily small!
int end = (i+1)+c[i]; // unrelated
int j=begin; // also equal to 1-c[0]
while(i<n){
a[j-1]++; // increment a[-c[0]] which is UB unless c[0]==0
This means undefined behavior (UB), i.e., it could do nothing, it could segfault, or (what apparently happened in your case) access elements of an adjacent data structure.
How can I break a loop when I define an integer array with a number and I want to finish the loop by pressing the ENTER.
I test '\n' and '\r' and '\0' and char(13) and NULL but didn't work !
for example ( in this code i try to stop the loop with ascii code of ENTER) :
#include <iostream>
using namespace std;
int main()
{
int n[100];
for (int i = 0; i < 100 && n[i]!=char(13); i++)
{
cin >> n[i];
}
return 0;
}
The behaviour of your code is undefined: you read an element from n before writing it: int n[100] = {}; is a fix for that.
Your specific problem here is that you need to check the error state of cin if an int is not readable from the stream: use something like std::cin.fail().
Also, don't hardcode character values (presumably that's what char(13) is doing?), as then you're not writing portable code. Use '\r' &c. instead.
You can change the code n[i]!=char(13) to n[i-1]!=char(13), because when you check the value of what your enter, the variable i has been changed to i++, so the value of n[i] is undefined,and you will always get true.
Please i am stuck at this question for half an hour and can't find why the error comes?
Problem code : test
Life, Universe and Everything
#include<iostream>
using namespace std;
int main()
{
int a[20],i;
cin>>a[0];
for(i=1;a[i-1]!=42;i++)
{
cout<<a[i]<<"\n";
cin>>a[i];
}
return(0);
}
Your code tries to access non-existing array elements, which causes segfault. You should stop your loop before the array index gets larger than the length of the array minus 1:
int a[20];
for (i = 1; i < 20 && a[i - 1] != 42; i++)
{
// ...
}
Apart from limit problem, your printing elements without initializing them
//for i = 1, a[i] is uninitialized
cout<<a[i]<<"\n";
On accessing a local variable (like this), you're likely to get garbage value.
This might be better substitute for what you are trying to do:
int a[20],i;
for(i=0;i < 20;i++)
{
cin>>a[i];
if (a[i] == 42)
break;
cout<<a[i]<<"\n";
}
You are trying to print the uninitialized data...
#include<iostream>
using namespace std;
int main()
{
int a[20],i;
cin>>a[0]; // a[0] uninitialized
for(i=1;a[i-1]!=42;i++)
{
cout<<a[i]<<"\n";
cin>>a[i];
}
return(0);
}
In the for loop get the data first and then print it.Your array size is 20 but you are trying to write upto 42.
You use array values before initializing them. C++ doesn't initialize non-static arrays for you unless you tell it to, so $DEITY knows what's in there. And technically, whatever's in there could cause an exception...or any number of other things. (For ints, on an x86 machine, that's actually highly unlikely. But elsewhere, it's possible.)
The user can enter more than 20 numbers. That's really just a special case of the more general problem, though: You allow unknown number of entries, but aren't able to accept them all without crashing.
If you don't know beforehand how many objects there will be, use a vector.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<int> a;
int entry;
cin>>entry;
// Oh, yeah. This. You really, *really* want to check `cin`.
// Otherwise, if the user decided to type "i like cheese", you'd loop
// forever getting zeros while cin tried to parse a number.
// With the array, that'd typically cause a segfault near instantly.
// With a vector, it'll just eat up all your CPU and memory. :P
while (cin && entry != 42) {
a.push_back(entry);
cout << entry << "\n";
cin >> entry;
}
return 0;
}