I am trying to make a function thats reads a character string from the stdin and stores it in a character vector and also stores the position of the special character -(#) in an integer vector. It is given that the input will consist only of lowercase alphabets and the special character i.e '#'. Both the character and integer vectors are global. I can't figure out why I am getting runtime error. Here is my code:-
vector<int> v;
vector<char> s;
inline int input() //called in main when we have to read input
{
char p=getchar();
register int i=0;
while((p>='a'&&p<='z')||(p=='#'))
{
s.push_back(p);
if (p=='#')
{
v.push_back(i);
}
p=getchar();
i++;
}
return 0;
}
while((p>='a'&&p<='z')||(p=='#))
You don't have '#'
It would help if you put the nature of the error that you get at run-time. It would also help if you gave examples of inputs that cause this error.
A few observations, which may give you some pointers to the cause of the error:
Your vectors are global variables. It would be much better if you passed them into the function and do not store them at global scope. This will allow you to much better track where they are being accessed and changed which will make your code much more maintainable.
Neither vector gets cleared at the start of the function so will continue to build up through subsequent calls. This may or may not be what you want to do.
The function will terminate early if you do not either type a lowercase letter or '#'. This looks deliberate, but of course any punctuation, capitals, numbers, or spaces will cause early termination.
You always return 0 from the function. If the function is not written to return a value it should be declared as void.
I would also remove your use of inline and register which are unlikely to give you anything of an appreciable speed increase.
Related
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1;
cin>>s1;
int n=s1.size();
string s2;
for(int a=0;a<n;a++)
{
s2[a]=s1[n-1-a];
}
cout<<s2;
}
However I am not getting any output, But I can print elements of reversed string. Can anybody please help.
string s2; // no size allocated
for(int a=0;a<n;a++)
{
s2[a]=s1[n-1-a]; // write to somewhere in s2 that doesn't exist yet
You are writing into elements of s2 that you never created. This is Undefined Behaviour, and anything may happen, including appearing to work normally. In this case, you are probably overwriting some random place in memory. It might crash, or that memory might really exist but not break anything else right away. You might even be able to read that back later, but it would only seem to work by pure accident.
You could catch this problem by always using s2.at(a) to access the data, as it will do a range check for you. ([] does not do a range check). There's a cost to this of course, and sometimes people will skip it in circumstances where they are certain the index cannot be out of bounds. That's debateable. In this case, even though you were probably sure you got the maths right, it still would have helped catch this bug.
You need to either create that space up front, i.e. by creating a string full of the right number of dummy values, or create the space for each element on demand with push_back. I'd probably go with the first option:
string s2(s1.size(), '\0'); // fill with the right number of NULs
for(int a=0;a<n;a++)
{
s2.at(a)=s1.at(n-1-a); // overwrite the NULs
You might want to choose a printable dummy character that doesn't appear in your test data, for example '#', since then it becomes very visible when you print it out if you have failed to correctly overwrite some element. E.g. if you try to reverse "abc" but when you print it out you get "cb#" it would be obvious you have some off-by-one error.
The second option is a bit more expensive since it might have to do several allocations and copies as the string grows, but here's how it would look:
string s2; // no space allocated yet
for(int a=0;a<n;a++)
{
s2.push_back(s1.at(n-1-a)); // create space on demand
I assume you are doing this as a learning exercise, but I would recommend against writing your own reverse, since the language provides it in the library.
You are utilizing something called Undefined Behaviour in your code. You try to access element of s2 at a position, but your string does not have that many chars (it's empty).
You can use std::string::push_back function to add a character on the last postion, so your code would look like this:
for(int a=0;a<n;a++)
{
s2.push_back(s1[n-1-a]);
}
EDIT, to address the other question, your console window probably closes before you can notice. That's why "you don't get any output".
Try this: How to stop C++ console application from exiting immediately?
You can use the inbuilt reverse function in c++
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s1 = "string1";
reverse(s1.begin(),s1.end());
cout << s1;
return 0;
}
Hope that helps :)
You can just construct the string with reverse iterators:
std::string reverse ( std::string const& in )
{
return std::string { in.crbegin(), in.crend() };
}
I was trying to write a program to enter texts like passwords (display "*" instead of the character which in input by the user).
The problem is, when I use char arrays to store the password, the program works fine, but when I use a string class variable for the same purpose, my program crashes while displaying the string.
Here is the code:
// *********THIS CODE WORKS FINE***********
#include <iostream>
#include<string>
#include<conio.h>
int main()
{
using namespace std;
int i=0;
cout<<"Enter a password,press ENTER to finish writing"<<endl;
char passw[20];
passw[i]=getch();
while(passw[i]!=13)
{
i++;
cout<<"*";
passw[i]=getch();
}
passw[i+1]='\0';
cout<<"\nPassword is "<<passw;
return 0;
}
Now when I replace char passw[20] with string passw:
//**********THIS CODE CRASHES!!*********
#include <iostream>
#include<string>
#include<conio.h>
int main()
{
using namespace std;
int i=0;
cout<<"Enter a password,press ENTER to finish writing"<<endl;
string passw;
passw=getch();
while(passw[i]!=13)
{
i++;
cout<<"*";
passw[i]=getch();
}
cout<<"\nPassword is "<<passw;
return 0;
}
Can anybody explain why this is happening?
Just started with strings and there's just too much for me to know about strings :)
In string you can use string concatenation.
you can save your char and add it to your string variable.
char ch;
string pass;
ch=getch();
pass=pass+ch;
You're accessing a location (passw[i]) that is not yet existing in your std::string and you're not storing it correctly to a string. You should use the method passwd.push_back(char) to store it.
Check for reference: http://en.cppreference.com/w/cpp/string/basic_string/push_back
A string works differently compared to a char array. You probably know that char passw[20] in your first example creates an array with space for up to 20 chars. These can then be accessed using operator[] without a problem. A string, unlike a basic array, is a dynamic data structure, meaning it grows and shrinks over time as your program runs. Its content can also be accessed using operator[], however, this will not append to the string, it can only be used to change what is already there.
It's important to note that in c++, not all operations will perform what is known as bounds checking. In your second example, you access the i-th character of your string and write a character to that location. However, what would happen if you try to write, for instance, to the 10-th character of a string that only has space for 5? When doing so via operator[], the program will write to whatever location the 10-th character would be at, even though that part of memory is actually not part of the string. Anything could be there and will be overwritten by that operation. As you can probably imagine, this is not desirable at all and can lead to all sorts of problems later down the line. If you're lucky, your program will crash immediately on the write. It did not in your case, however, that's not a good thing; writing out of bounds can cause a heap corruption (the heap being a certain part of memory) which generally leads to a crash at some point down the line.
It's fine to use operator[] to change a strings characters if and only if you know whatever index you're accessing is within the strings size. Otherwise, you need to append to the string using an appropriate member function. These will enlarge the string if necessary.
You always need to pay attention when working with dynamic memory and what parts of it you're accessing (in your first example, for instance, you would also write out of bounds if your password is too long).
Is it possible to fix size of string variable. For example I want string variable str_new of capacity 5. P.S: I don't want to use char str_new[5]. I want to use string class. So the variable declaration should not use keyword char. Is this possible?
EXAMPLE: string str_new;
Is there any way to make sure that str_new size is fixed as 5. This question might be absurd. Please enlighten.
This code throws exception just after execution of one iteration of 'for' loop. There might be better ways to copy one string to another. But I want to copy it as mentioned below. Can someone tell me how to fix the bug, or below code cannot be fixed as its totally messed up?
string str_old = "abcde";
string str_new;
for (int i = 0; i < 5; i++)
{
str_new[i]= str_old[i];
}
However This code works fine if I do following changes
string str_new = " ";
So do I really need to explicitly initialize with blank spaces. Or there can be any other way.
You are asking two questions, and this sound very much like a homework question.
Is it possible to fix size of string variable.
There isn't any reasonable way to fix the size of a string to a size of X, and I can't think of any possible reason why you would even want to try to do so. That said, if there really is some business/homework rule that requires this, then simply check the size of the string before putting anything into it, if the size of the string plus the size of what you plan on inserting is over '5', then do something else.
For enlightenment on why, read up on the "zero one infinity rule".
This code throws exception just after execution of one iteration of 'for' loop. There might be better ways to copy one string to another.
Your code throws an exception because you are trying to replace the first character of str_new with a different character, but your object doesn't have a first character to replace.
But I want to copy it as mentioned below. Can someone tell me how to fix the bug, or below code cannot be fixed as its totally messed up?
Why do you want to use that for loop? That again leads me to believe this is some sort of homework assignment, because this is definitely not a good way to copy one string into another. A simple assignment is all that is necessary:
string str_new = str_old;
But I get it, you want to use the for loop and you don't even want a loop based on the actual size of str_old. Here you go:
string str_old = "abcde";
string str_new(5, 0);
assert(str_old.size() >= 5);
for (int i = 0; i < 5; ++i) {
str_new[i]= str_old[i];
}
The above code creates a string str_new that has five elements in it that are all equal to 0. It then checks to make sure that str_old actually is 5 characters long. Then it replaces each 0 with a copy of the character at the corresponding position in str_old.
Don't put that kind of code in a real program, but if it satisfies the homework assignment, then go for it.
Why don't you do
string.reserve()
If you want initialized a string of the right capacity, you can do
string.resize()
void resize (size_t n);
void resize (size_t n, char c);
Resize string
Resizes the string to a length of n characters.
void reserve (size_t n = 0);
Request a change in capacity
Requests that the string capacity be adapted to a planned change in size to a length of up to n characters.
If n is greater than the current string capacity, the function causes the container to increase its capacity to n characters (or greater).
I am writing a program in C++ that uses the following function which has two character pointers (of course, acting as strings) as its formal arguments :
void takeword (char *dstr, const char *from)
{
int i=0, j=0;
printf ("\n %s", dstr);
getch();
exit(0);
while (!isalpha(from[i])) //positioning to the first letter in te line
i++;
do
{
dstr[j]=from[i];
j++;
i++;
}while (isalpha(from[i]));
dstr[j]='\0'; //terminating the word with a null character
};
My problem is that the two strings dstr and from are being allocated the same memory space.
As a result, the changes being made in dstr are being reflected in from which I don't want.
So, what to do to ensure that they are allocated different memory locations ?
The only case that the code you've given does not handle in a satisfactory way is the case that dstr > from && dstr < from + strlen(from).
To fix this, you have three options:
You write your function in a way that ensures correct operation independent of whether the two strings overlap or not. This is likely to involve a temporary buffer.
You document in the function declaration that the function won't handle overlapping buffers correctly, and make sure that the calling code does not violate this restriction. In this case you might consider adding the restrict keyword to the function arguments to document this assumption both to the programmer and the compiler (which will be able to do additional optimizations. It would also be a good idea to insert an assert() that checks for the overlapping condition.
You go in the opposite direction and change the function signature to void takeword (char *string) and document that it will move the first word to the start of the string and add a terminating null character.
It is up to you to decide which solution you prefer in your situation, it all depends on the use case at hand.
I have been trying to return an array of strings for a function for a couple of days to no avail. While I was searching around StackOverflow, I found that it would be a better idea to have a parameter that will be assigned the value of an array. So, here is my code example (not the actual usage, but a mockup of how I am trying to use the function). I am sorry if the code is a bit sloppy. I have been testing things out with it for a while.
void splitOn(string message, string delim, string***toCh) {
string** rString = new string*;
string lArr[numberOf(message, delim)+1];
for(int index=0; index<numberOf(message, delim)+2; index++) {
lArr[index]=message.substr(0, message.find(delim)).c_str();
message = message.substr(message.find(delim)+1, message.length());
rString[index]=&lArr[index];
cout << "IN LOOP "<<*rString[index]<<endl;
}
rString[numberOf(message, string(delim))] = &message;
toCh=&rString;
}
int main(){
string***arr;
splitOn("fox.over.lazy.dog", ".", arr);
cout << **arr[0]<<endl;
Note:
numberOf() takes a string and a delimiter(string) and returns how many times the delimiter is found within the string.
strings are from std::string
lArr (the local array within the loop) and *rString all give correct output.
Although I am trying to assign the array to a parameter, learning how to return an array is more appealing to me.
I could hack this together with a file and getLine(), but I would prefer to learn how to properly do this.
You're trying to return local variables, which will never work. You and your caller need to agree on how to allocate the return value. In C++ as the commenters mention this would normally be done by passing a reference to a vector to handle your allocation for you.
In C you have two options, you can either get the caller to pass in a big enough allocation, or use multiple calls to malloc in the callee (not forgetting the calls to free in the caller!)
For instance, if you pass a writable character array, you can simply overwrite the separator characters with null characters to split it up into individual strings without having to allocate new copies.