C++ checking if a string index is a digit - c++

#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string str, temp;
cout << "enter string: \n";
getline (cin, str);
vector<int> vec;
int num;
cout << "str size is " << str.size() <<endl;
for (int j=0; j < str.size(); j++)
{
int num2= str.size()-1;
if (isdigit(str[j]))
{
temp+= str[j];
num = atoi(temp.c_str());
if (num2 ==j)
vec.push_back(num);
}
else if (str[j] == ',')
{
num = atoi(temp.c_str());
temp.clear();
vec.push_back(num);
}
else
{
cout << "error\n";
temp.clear();
}
}
for (int k=0; k < vec.size(); k++)
cout << vec[k] <<endl;
}
I'm trying to make a program to where it reads in a string such as
5,6,7,8,11,120
and it'll separate the numbers from the commas, but if anything else is in the string it'll report it as an error. For example, if it was 5,6,f or 5, ,3 (space).
My program is not working though and I think it has something to do with when I am checking if it's a digit with the (isdigit) function. as it is counting fs, sds, xdx as a digit. Any idea how I can fix this?
EDIT:
I've updated my code but I am still coming across problems. If I type in for example: 3,2,f it's saying that f is 0. How can I fix this?

Use
std::getline(std::cin, str);
instead of
cin >> str;
Your string is getting tokenized to just the first "word". getline() reads in the whole line into str.

Run the program in debug, and set a breakpoint at
cout << "error\n";
If it doesn't halt there for non-digit input, your compiler is buggy.
Your program, as far as I can tell, isn't. (apart from that it doesn't capture the last element, unless you terminate the input with ',')
Also check that you don't include any third-party header that redefines isdigit

Use STL function instead C-style function.
Look at http://www.cplusplus.com/reference/string/stod/

Related

Insert a character into a string

I need to insert a character into a string at every instance of that character. For example if my string was, "This is a test" and my character was 's' then my output would need to look like this: "Thiss iss a tesst"
any idea why this isn't working? Here's what I have so far. I am not supposed to add any extra preprocessor instructions or anything, just using what's here I need to figure this out.
#include <iostream>
#include <string>
using namespace std;
int main(){
string userString;
char userChar;
cin >> userString;
cin >> userChar;
for (int i = 0; i < userString.size(); i++){
if(userString.at(i) == userChar){
userString.insert(userString.begin() + i, userChar);
}
}
cout << userString;
return 0;
Update:
Here's the solution I worked out.
#include <iostream>
#include <string>
using namespace std;
int main(){
string userString;
char userChar;
cout << "enter a string" << endl;
getline(cin, userString);
cout << "enter a character" << endl;
cin >> userChar;
for (int i = userString.size()-1; i >= 0; i--){
if(userString.at(i) == userChar){
userString.insert(userString.begin() + i, userChar);
}
}
cout << userString;
return 0;
}
I don't know why you want to go through the string backwards. Anyway. Your problem is that once you insert a character at some position, your loop will encounter the inserted character again in the next iteration and insert another. Ad infinitum.
#include <cstddef> // std::size_t, the correct type for indexes and sizes of objects in mem
#include <string>
#include <iostream>
int main()
{
std::cout << "Enter a string: ";
std::string userString; // define variables as close
std::getline(std::cin, userString);
std::cout << "Enter a character: ";
char userChar; // to where they're used as possible
std::cin >> userChar;
for (std::size_t i{}; i < userString.size(); ++i) {
if (userString[i] == userChar) { // no need to use std::string::at() 1)
userString.insert(userString.begin() + i, userChar);
++i; // advance the index to not read the same character again.
}
}
std::cout << userString << '\n';
}
1) since it is allready sure that the index will be in a valid range.
Your first solution probably ends up looping infinitely if you ever find one of the chosen character because you always insert one more copy ahead and keeps finding the same char ever after.
std::basic_string has a find function. It's always better to use code offered by a library than self made code. Here's my proposed solution:
std::string& duplicate_char(std::string& str, char val)
{
using std::string;
auto pos = str.find(val); // finds first index of character val or npos if unsuccessful
while (pos != string::npos)
{
str.insert(pos, 1, val); // insert at pos one character val
pos = str.find(val, pos + 2); // find the next occurence of val starting after the newly inserted character
}
return str;
}
You may use this function like this:
int main()
{
std::string testStr{"Thiss iss a tesst"};
duplicate_char(testStr, 's');
std::cout << testStr << std::endl;
}

C++ User defined string needs to contain spaces (but not allowed by program..?)

I'm working on homework for my c++ class, and it's been quite awhile since I've used it. I was wondering if there was a way to allow spaces in a string (instead of it nulling out and ending the string)
my current code is this:
int chapter10() {
string strinput;
char charstr[1000];
int numwords=1;
cout << "Enter a phrase ";
cin >> strinput;
cout << strinput;
const int size = strinput.size() + 1;
strcpy_s(charstr, strinput.c_str());
cout << strinput << endl;
for (int i = 0; i != size; i++) {
if (*(charstr + i) == ' ')
numwords++;
}
cout << "There are " << numwords << " words in that string." << endl;
return 0;
}
The problem I'm having, is for instance, if I type "Hello World" and press enter, it pops the next line (right after the cin) and says "Hello", and the space made it cut the rest of the phrase off.
How does one fix this issue? I don't want to use the str:: things as I barely know what they are, and have really never had to use them, and that would look a bit suspicious to the teacher :P
Update: If you've suggested using getline(cin, strinput); It doesn't work too well. I can from what I see, only type in the 10 to reach my function, but after I press enter, it thinks that I've presses something else, which makes it completely skip the cin to get the string value. But, there is something weird with this, if I type "10 hello world" it does everything correctly. Well, with the exception that it needs to be in the same line as the number to reach the function.
Solved: The use of getline(cin, strinput) works perfectly fine, if you're not using user input before hand. If you are, you're going to need a cin.ignore before the getline(). As stated in the comment by my best answer.
#include <iostream>
#include <iomanip>
#include <string>
#include <limits>
using namespace std;
//~~~Initialize all functions
int chapter10();
//~~~Initializing complete
int main() {
srand(time(0)); //makes rng thingy work instead of choose same numbers cause it doesn't do it on its own. lol
cout << "Enter the chapter number you need to look at: ";
int chapterNumber;
cin >> chapterNumber;
switch (chapterNumber) {
case 1: testingStuff(); break;
case 9: chapter9(); break;
case 10: chapter10(); break;
default: cout << "You chose an invalid chapter number, reload the program."; break;
}
system("pause");//So console doesn't close instantly cause that's not annoying at all...
}
int chapter10() {
string strinput;
char charstr[10000];
int numwords=1;
cout << "Enter a phrase." << endl;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
getline(cin, strinput);
const int size = strinput.size() + 1;
strcpy_s(charstr, strinput.c_str());
for (int i = 0; i != size; i++) {
if (*(charstr + i) == ' ' & *(charstr + (i+1)) != ' ' )//the & is fail safe so multiple space no ++numwords
numwords++;
}
cout << "There are " << numwords << " words in that string." << endl;
return 0;
}
The way I have my code written was I used a switch/case to reach my function. This required user input, which in turn caused my program to 'think' I was still typing for the second input required in the chapter10 function.
Adding in the line of code: cin.ignore(numeric_limits<streamsize>::max(), '\n'); allowed me to cancel the input, and start a new one.
If you want to get all characters an end-user enters on a single line, use getline: instead of cin >> strinput write this:
getline(cin, strinput);
The fact that it is actually std::getline(std::cin, strinput) makes no difference, because your code uses std namespace anyway. In case you were wondering what std:: prefix is, it's a namespace of the Standard C++ library.
You can use getline() function
It copies into a string till a newline is reached or delimiter is found - so it will accept all the spaces till newline is reached
http://www.cplusplus.com/reference/string/string/getline/
or you can also use cin.getline() as shown here -
std::cin input with spaces?
use:
cin >> noskipws >> strinput;
Use std::getline() function. Example:
#include <iostream>
#include <vector>
#include <sstream>
void WordCounter(
const std::vector<std::string> & lines) {
for (int i = 0; i < lines.size(); ++i) {
std::istringstream iss(lines[i]);
std::string word;
int count = 0;
while (iss >> word) {
++count;
}
std::cout << "Line #" << i << " contains " << count << " words." <<
std::endl;
}
}
int main() {
std::string line;
std::vector<std::string> lines;
while (std::getline(std::cin, line)) {
lines.push_back(line);
}
WordCounter(lines);
return 0;
}

Reading a sentence until ENTER key pressed using 2-D char array

I need to read a sentence word by word until "ENTER" key is pressed. I used a do..while loop to read words until ENTER key is pressed. Please suggest me some conditions for checking ENTER key press (or) others ways for reading similar input.
#include<iostream>
#include<string.h>
using namespace std;
int main(){
char a[100][20]={'\0'};
int i=0;
do{
cin>>a[i++];
} while( \\ Enter key is not pressed );
for(int j= 0 ; j < i ; j++)
cout<< a[j] << " ";
return 0;
}
The statement
cin>>a[i++];
blocks at the prompt already, until the ENTER key is pressed. Thus the solution is to read a single line at once (using std::getline()), and parse the words from it in a separate step.
As your question is tagged c++, you can do the following:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
int main() {
std::string sentence;
std::cout << "Enter a sentence please: "; std::cout.flush();
std::getline(std::cin,sentence);
std::istringstream iss(sentence);
std::vector<std::string> words;
std::string word;
while(iss >> word) {
words.push_back(word);
}
for(std::vector<std::string>::const_iterator it = words.begin();
it != words.end();
++it) {
std::cout << *it << ' ';
}
std::cout << std::endl; return 0;
}
See the fully working demo please.
As an improvement the current standard provides an even simpler syntax for the for() loop:
for(auto word : words) {
std::cout << word << ' ';
}
while (cin.peek() != '\n') {
cin >> a[i++];
}
First, I must say that πάντα ῥεῖ's solution is better.
But it might be to much for you if, you are beginner.
Besides, I think you want in 2-D array, not vectors.
#include<iostream>
#include<string.h>
using namespace std;
int main(){
/*
All of this is simplified.
For example there are no check if user entered word larger than 100 chars.
And that's not all, but because of simplicity, and easy of understanding....
*/
char a[100][20]={'\0'};
char c;
char buffer[2000];
int i=0, j, k = 0;
/*
Read in advance all to way to ENTER, because on ENTER key all data is flushed to our application.
Untill user hits ENTER other chars before it are buffered.
*/
cin.getline(buffer, 2000, '\n');
do {
c = buffer[k++]; //read one char from our local buffer
j = 0;
//while we don't hit word delimiter (space), we fill current word at possition i
// and of cource while we don't reach end of sentence.
while(c != ' ' && c != '\0'){
a[i][j++] = c; //place current char to matrix
c = buffer[k++]; //and get next one
}
i++; //end of word, go to next one
//if previous 'while' stopped because we reached end of sentence, then stop.
if(c == '\0'){
break;
}
}while(i < 20);
for(j= 0 ; j < i ; j++)
cout<< a[j] << " ";
cout << endl;
return 0;
}
How about using this as your while statement
while( getchar() != '\n' );
You'll need the <stdio.h> header file for this.
See the ideone link
You can try
cin.getline(buffer, 1000);

Representing a User Entered String Diagonally

I am currently a bit stuck. I need to write a program in c++ that allows a user to enter a string (any length with any amount of spaces) and the program then need's to represent this diagonally. I can get it to work but only for the first word and not for any word's entered after the first word. Below you can find my code.
Thanks People!
#include <iostream>
#include <string>
using namespace std;
int main()
{
string strHello;
cin >> strHello;
for(int k = 0; k < strHello.length(); k++)
{
for (int x = 0; x <= k; x++)
{
if (k==x)
cout << strHello.at(x);
else
cout << " ";
}
cout << '\n';
}
return 0;
}
Yes the problem is as others have mentioned, that >> operator stops reading at the first white space character found, so std::getline() does the job, and aditionally you don't need the nested loops, take a look at this
#include <iostream>
#include <string>
using namespace std;
int
main(void)
{
string text;
string spaces;
getline(cin, text);
for (int k = 0 ; k < text.length() ; ++k)
cout << (spaces += ' ') << text.at(k) << endl;
return 0;
}
The problem is in your input, not your output. The problem is that you only call
cin >> strHello;
once. This reads in only the first sequence of non-white-space characters that are delimited by any amount of {white-space, begin of input, end of input}. So, your program will only read in the first such sequence of any input and discards any white space in the input.
Use getline, e.g
std::getline(cin, strHello);
cin will read only the first string it see before white space. e.g. "hello world" will have only hello in strHello.
cin >> will break up the input string at whitespace characters. You should use getline() instead.
getline(cin,strHello);
Here is a program that I think will help:
#include <iostream>
#include <string>
#define MAX_LEN 100
using namespace std;
int main()
{
char strHello[MAX_LEN] = { 0 };
cout << "Enter a string";
cin.getline(strHello, MAX_LEN);
for (int k = 0; k < sizeof(strHello); k++){
for (int x = 0; x <= k; x++){
if (k == x)
cout << strHello[x];
else
cout << " ";
}
cout << '\n';
}
return 0;
}

C++ Making a char array recognise spaces upon input

I'm trying to make a program that flips the words you input. The problem comes when I try to write the word and it asks twice for the input:
cin >> Arr >> myStr;
It is logical that it ask twice but everytime I try to use getline the compiler gives out an error (and even if it worked I have to give the input twice) and I need it to include spaces in the character array.
Here is my full code:
#include <iostream>
#include <string>
using namespace std;
string myStr;
string newVal;
int i;
int main()
{
char Arr[i];
cout << "Enter: ";
cin >> Arr >> myStr;
for (i = myStr.length(); i >= 0; i--)
{
cout << Arr[i];
}
cout << endl;
return 0;
}
The loop works.
The first problem can be corrected by achieving the proper use of getline.
The second one, I have got no idea (use a single input to assign two variables).
Thanks in advance, and I apologise if this is too much of a ridiculous question.
Maybe you can try to have a look to this solution that it's more C++ style than yours:
#include <iostream>
#include <string>
int main() {
std::string myStr;
std::cout << "Please give me a string: ";
if(std::getline(std::cin, myStr)) {
for(std::string::reverse_iterator it = myStr.rbegin();
it != myStr.rend();
++it) {
std::cout << *it;
}
std::cout << std::endl;
}
}
I suggest to you to use always std::string in C++ because has all the methods and function that you could need. So don't waste your time with char array like you do in C.
Here it is, as I said. I was digging around and came up with this:
#include <iostream>
#include <string>
using namespace std;
string myStr;
int i;
int main()
{
cout << "Enter: ";
getline (cin, myStr);
i = myStr.size();
cout << i << endl;
char Arr[i];
for (int a = 0; a <= i; a++)
{
Arr[a] = myStr[a];
}
for (i; i >= 0; i--)
{
cout << Arr[i];
}
return 0;
}
I did not know string contents could also have array-like behaviour. Test it out! Works like a charm (as far as tested).
The way I formatted the code it takes no more than 27 lines of code.
Thanks everyone involved, you helped me a lot.
P.S: Couldn't answer before, I can't do it soon enough with my reputation.