I've recently started learning programming using the C++ language. I wrote a simple program that is supposed to reverse a string which I compile in the Terminal using gcc/g++.
#include <iostream>
using namespace std;
string reverse_string(string str)
{
string newstring = "";
int index = -1;
while (str.length() != newstring.length())
{
newstring.append(1, str[index]);
index -= 1;
}
return newstring;
}
int main()
{
string x;
cout << "Type something: "; cin >> x;
string s = reverse_string(x);
cout << s << endl;
return 0;
}
I've rewritten it multiple times but I always get the same output:
Type something: banana
��
Has anyone had a problem like this or know how to fix it?
Your code initializes index to -1, and then uses str[index] but a negative index has no rational meaning in C++. Try instead initializing it like so:
index = str.length() - 1;
I can see several issues with your code. Firstly, you are initializing index to -1, and then decrementing it. Maybe you meant auto index = str.length()-1;?
I recommend you look at std::reverse, which will do the job you're after.
Your main function then becomes:
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string x;
cout << "Type something: ";
cin >> x;
reverse(x.begin(), x.end());
cout << x << endl;
return 0;
}
If you really want to write your own reverse function, I recommend iterators over array indices. See std::reverse_iterator for another approach.
Note, the above will simply reverse the order of bytes within the string. Whilst this is fine for ASCII, it will not work for multi-byte encodings, such as UTF-8.
You should use a memory debugger like valgrind.
It's a good practice to scan your binary with it, and will make you save so much time.
Related
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'm a beginner programmer... and I can't figure out what the problem is in this bit of code I'm writing for a text adventure. All I want it do At the moment is let the user enter a command, and then it converts it to ALLCAPS and prints that out. It should output this:
What shall I do?
pie
Your raw command was: PIE
But instead, it outputs this:
What shall I do?
pie
PIE
...and then it freezes. Here's the code:
#include <iostream>
#include <string>
#include <cctype>
#include <cstring>
#include <vector>
using namespace std;
void command_case();
string userIn;
string raw_command;
int x = 0;
int main()
{
while(raw_command != "QUIT")
{
cout << "What shall I do?\n";
cin >> userIn;
command_case();
cout << "Your raw command was: " << raw_command << endl;
}
return 0;
}
void command_case()
{
char command[userIn.size()+1];
strcpy(command, userIn.c_str());
while(x < userIn.size()+1)
{
if(islower(command[x]))
{
command[x] = toupper(command[x]);
cout << command[x];
x++;
}
else if(isupper(command[x]))
{
cout << command[x];
x++;
}
}
raw_command = command;
}
I think it may be a problem with the while loop in void command_case(), but I can't figure out exactly what that problem is. I'd appreciate any advice you can give me.
One too much:
while(x < userIn.size()+1)
The problem is with the x variable in the command_case() function.
When x becomes 3 (and "command[x] points to the null character at the end of "pie")
neither islower(command[x]) or isupper(command[x]) are true.
Neither section of the if statement executes, so x stays at 3 forever.
Since "userIn.size()+1" is 4, and x never reaches 4, the loop never exits.
A possible solution is remove the "x++" from both sections of the if statement, and have a single "x++" after the if statement. This will increment x during every loop regardless of what character "command[x]" points to.
You could easily do something like
void command_case()
{
for(int i =0; i<userIn.size(); i++)
{
userIn[i] = toupper(userIn[i]);
}
}
then cout<<userIn in the main
You should remove all cout calls from command_case() function. In fact the whole if-branch in the function is useless and you could just replace it with the following:
command[x]=toupper(command[x]);
For the simplicity you could replace the whole command_case() function with (just remember to #include <algorithm>):
std::transform(userIn.begin(), userIn.end(), userIn.begin(), toupper);
The first line contains an integer n (1 ≤ n ≤ 100). Each of the following n lines contains one word. All the words consist of lowercase Latin letters and possess the lengths of from 1 to 100 characters.
(Source: http://codeforces.com/problemset/problem/71/A)
How would you get input from the user given n? I tried using a while loop but it doesn't work:
#include <iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int i;
while (i<=n) {
cin>>i ;
i++;
}
}
You probably meant to have something like:
#include <iostream>
int main() {
int n;
cin>>n;
int theInputNumbers[n];
for(int i = 0; i<n; ++i) {
cin >> theInputNumbers[i];
}
}
Your loop is really quite far off of what you need. What you wrote is extremely wrong such that I cannot provide advice other than to learn the basics of loops, variables, and input. The assistance you need is beyond the scope of a simple question/answer, you should consider buying a book and working through it cover to cover. Consider reading Programming Principles and Practice Using C++
Here is a working example of something approximating your question's requirements. I leave file input and output as an exercise up to you. I also make use of C++11's front and back std::string members. You would have to access via array index in older versions.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main(){
int totalWords;
cin >> totalWords;
stringstream finalOutput;
for (int i = 0; i < totalWords; ++i){
string word;
cin >> word;
if (word.length() > 10){
finalOutput << word.front() << (word.length() - 2) << word.back();
}else{
finalOutput << word;
}
finalOutput << endl;
}
cout << endl << "_____________" << endl << "Output:" << endl;
cout << finalOutput.str() << endl;
}
With that said, let me give you some advice:
Name your variables meaningfully. "int i" in a for loop like I have above is a common idiom, the "i" stands for index. But typically you want to avoid using i for anything else. Instead of n, call it totalWords or something similar.
Also, ensure all variables are initialized before accessing them. When you first enter your while loop i has no defined value. This means it could contain anything, and, indeed, your program could do anything as it is undefined behavior.
And as an aside: Why are you reading into an integer i in your example? Why are you then incrementing it? What is the purpose of that? If you read in input from the user, they could type 0, then you increment by 1 setting it to 1... The next iteration maybe they'll type -1 and you'll increment it by 1 and set it to 0... Then they could type in 10001451 and you increment by 1 and set it to 10001452... Do you see the problem with the logic here?
It seems like you are trying to use i as a counter for the total number of iterations. If you are doing this, do not also read input into i from the user. That completely undermines the purpose. Use a separate variable as in my example.
this script is supposed to output array values that were inputted by the user into array "store." I am trying to store all the char array values into string temp. I get the error on line 12: "[Error] invalid conversion from 'char*' to 'char' [-fpermissive]." Would appreciate any help!
Edit: so I fixed the declaration and now at least it compiles, but the answer I get on my cmd is all jumbled up. Why is this so? The cmd only correctly couts the first string but after the space, it messes up.
#include <iostream>
#include <cstdlib>
using namespace std;
void coutArray(char[], int);
int main()
{
char store[50];
cout << "enter text: " << endl;
cin >> store;
coutArray(store, 50);
system("pause");
return 0;
}
void coutArray(char store[], int max)
{
string temp = "";
int i = 0;
while (i < max)
{
temp += store[i];
i++;
}
cout << temp << endl;
}
Using input from all answerers I finally got the fixed code:
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
void coutArray(char[], int);
int main()
{
char store[50] = {0};
cout << "enter text: " << endl;
cin.getline(store, 50);
coutArray(store, 50);
system("pause");
return 0;
}
void coutArray(char store[], int max)
{
string temp = "";
int i = 0;
while (i < max && store[i]!=0)
{
temp += store[i];
i++;
}
cout << temp << endl;
}
Thanks everyone. i learned a lot!!!
When you get an input using "cin" your input automatically ends with 0 (NULL).
You just need to add one little piece of code to your while statement.
instead of this :
while (i < max)
use this :
while (i < max && store[i]!=0)
Now it will stop when the input string is finished and won't print any garbage existed in the array beforehand.
To show that cin does add terminating zero, i initialized the array to 46, and put a breakpoint after the cin
so I fixed the declaration and now at least it compiles, but the answer I get on my cmd is all jumbled up. Why is this so?
Not sure what you mean by jumbled up. But since you did not tell us what you typed its hard to know it looks like it worked to me:
> ./a.out
enter text:
Plop
Plop�ȏU�
Notice that since my input is only 4 characters long. This means that a lot of the characters in the array still have undefined (ie random values). This is why I am seeing junk. To get past this initialize the array to have all 0 values.
char store[50] = {0};
Even bettern use a C++ object than handles longer strings.
std::string store;
std::getline(std::cin, store);
Note: passing arrays to functions by value is not a good idea. On the other end they have decayed to pointers and thus do not act like arrays anymore (they act like pointers whose semantics are similar but not identical).
If you must pass an array pass it by reference. But I would use a C++ container and pass that by reference (it is much safer than using C constructs). Have a look at std::string
The declaration of the function is wrong. Should be void coutArray(char *, int);
Look at the Implicit Conversion rules to understand what the compiler can do and what it cannot to do for you.
The issue with your program was that you were probably entering in less characters than the maximum size of the buffer. Then when you passed the maximum size as the parameter to coutArray, you assigned unfilled slots in the char array to temp. These unfilled slots could contain anything, as you have not filled them up to that point.
Your program is still correct, but what would be better would be to use read so that the number of bytes you specify is the minimum number of bytes that can be entered:
std::cin.read(store, 50);
Even better solution would be to use std::string:
std::string store;
std::cin >> store;
// or for the entire line
std::getline(std::cin, store);
It also follows that your coutArray should be changed to:
void coutArray(std::string);
// ...
void coutArray(std::string str)
{
std::cout << str << std::endl;
}
Look at this way
template<typename T, size_t N>
void MyMethod(T (&myArray)[N])
{
//N is number of elements, myArray is the array
std::cout<<"array elements number = "<<N<<endl;
//put your code
string temp;
temp.resize(N+1);//this is for performance not to copy it each time you use += operator
int i = 0;
while (i < max)
{
temp += store[i];
i++;
}
cout << temp << endl;
}
//call it like this
char arr[] = "hello world";
MyMethod(arr);
Please tell me why my code to reverse the input string is giving me various errors.
#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;
void ReverseString(string &aString);
int main(){
string info;
cout << "What's your string?" << endl;
getline(cin, info);
ReverseString(info);
cout << ReverseString(string info) << " compare with: " << info << endl;
system("pause");
return 0;
}
void ReverseString(string &aString){
for(int i = 0; i < aString.length(); i++)
{
string temp = 0; // initialize temporary string
temp = temp + aString.at(aString.length() - 1 - i); // hold temporary string
if(i => aString.length()) /*assign temp string to aString when all chars are processed*/
{
temp = &aString;
}
}
}
Hi you could simplify your code a lot by using the STL
for example:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
std::string str = "Hello World";
cout << str << endl;
std::reverse(str.begin() , str.end());
cout << str << endl;
return 0;
}
let me know if this is not suitable to your needs as theres a few other ways to do it too.
Without STL:
There are some corrections/changes to your code required, which I have supplied below. However you may want to look at some documentation on referencing variables to get an idea of how it works, such as:
http://www.cprogramming.com/tutorial/references.html
http://www.thegeekstuff.com/2013/05/cpp-reference-variable/
http://en.wikipedia.org/wiki/Reference_(C++)
What is a reference variable in C++?
http://www.tutorialspoint.com/cplusplus/cpp_references.htm
Correct reference and pointer use is a major part of C++ and allows for some of the most powerful functionality in the language, provided it is used correctly, or major headaches and mental scarring if used incorrectly, so it is worth, even essential, to have a firm grasp of them.
And even then expect the odd misuse to crop up every-so-often. :)
#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;
void ReverseString(string &aString);
int main(){
string info;
cout << "What's your string?" << endl;
getline(cin, info);
cout << info << " compare with: ";
ReverseString(info);
cout << info << endl;
system("pause");
return 0;
}
void ReverseString(string &aString)
{
int len = aString.length();
string temp = aString;// initialize temporary string
aString ="";
for(int i = 0; i < len; i++)
{
aString += temp[len - (1+ i)]; // assigns the reversed value to the referenced string
}
}
Just noticed the quote below from #zac-howland : so true, I have however left the code in as an illustrative piece. Provided some reading is done on this as well as plenty of experimentation I hope NewProgrammer will get the information and skill-set he needs to go forward.
#include<iostream>
#include<string>
#include <algorithm>
using namespace std;
string info;
string rvrs(string &str)
{
std::reverse(str.begin(),str.end());
return str;
}
int main()
{
cout<<"What is your string :: ";
getline(cin,info);
cout<<rvrs(info);
cout<<endl;
return 0;
}
You have a few syntactical errors in addition to your logical ones:
cout << ReverseString(string info) << " compare with: " << info << endl;
ReverseString(string info) will pass in an empty string to your ReverseString function (if it even compiles - which looks like it should not since you have 2 info's in the same scope). What you wanted is:
cout << ReverseString(info) << " compare with: " << info << endl;
In your reverse function, you only need to go to length() / 2.
Since you are passing by reference, changes you make to the string within the function will be reflected in the object you passed into it. That is, the original info will be reversed. If you want it to operate on a copy, you need to pass it by copy, not by reference.
Finally, cout << ReverseString(info) is not useful (if it even compiles) as ReverseString returns a void. You should have it return a string (the reversed string).
You have a number of problems.
string temp = 0; // initialize temporary string
It doesn't really make sense to initialize a string to 0. Just string temp; would be fine here.
temp = temp + aString.at(aString.length() - 1 - i); // hold temporary string
That's not quite how I'd do things, but I guess it should work.
if(i => aString.length())
This condition doesn't seem to make sense. Your loop is defined to iterate with i going from 0 to the length of the string -1, so it can never be greater than or equal to the string length.
/*assign temp string to aString when all chars are processed*/
{
temp = &aString;
}
Here the code doesn't match the comment. The comment says you're going to assign to aString, but the code assigns something to temp. The comment is probably closer to what you really want. But you still need to fix the condition, and probably want to do this after the loop has finished executing. So in pseudo-code, you'd end up with something like:
for (all characters in the string)
add the next character in the string to the end of temp
assign temp back to the original string