How do you parse a c-string? - c++

Hi I'm trying to take a c-string from a user, input it into a queue, parse the data with a single space depending on its contents, and output the kind of data it is (int, float, word NOT string).
E.g. Bobby Joe is 12 in 3.5 months \n
Word: Bobby
Word: Joe
Word: is
Integer: 12
Word: in
Float: 3.5
Word: months
Here's my code so far:
int main()
{
const int maxSize = 100;
char cstring[maxSize];
std::cout << "\nPlease enter a string: ";
std::cin.getline(cstring, maxSize, '\n');
//Keyboard Buffer Function
buffer::keyboard_parser(cstring);
return EXIT_SUCCESS;
}
Function:
#include <queue>
#include <string>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <vector>
namespace buffer
{
std::string keyboard_parser(char* input)
{
//Declare Queue
std::queue<std::string> myQueue;
//Declare String
std::string str;
//Declare iStringStream
std::istringstream isstr(input);
//While Loop to Read iStringStream to Queue
while(isstr >> str)
{
//Push onto Queue
myQueue.push(str);
std::string foundDataType = " ";
//Determine if Int, Float, or Word
for(int index = 0; index < str.length(); index++)
{
if(str[index] >= '0' && str[index] <= '9')
{
foundDataType = "Integer";
}
else if(str[index] >= '0' && str[index] <= '9' || str[index] == '.')
{
foundDataType = "Float";
break;
}
else if(!(str[index] >= '0' && str[index] <= '9'))
{
foundDataType = "Word";
}
}
std::cout << "\n" << foundDataType << ": " << myQueue.front();
std::cout << "\n";
//Pop Off of Queue
myQueue.pop();
}
}
}
Right now with this code, it doesn't hit the cout statement, it dumps the core.
I've read about using the find member function and the substr member function, but I'm unsure of how exactly I need to implement it.
Note: This is homework.
Thanks in advance!
UPDATE: Okay everything seems to work! Fixed the float and integer issue with a break statement. Thanks to everyone for all the help!

Your queue is sensible: it contains std::strings. Unfortunately, each of those is initialised by you passing cstring in without any length information and, since you certainly aren't null-terminating the C-strings (in fact, you're going one-off-the-end of each one), that's seriously asking for trouble.
Read directly into a std::string.

std::istreams are very useful for parsing text in C++... often with an initial read of a line from a string, then further parsing from a std::istringstream constructed with the line content.
const char* token_type(const std::string& token)
{
// if I was really doing this, I'd use templates to avoid near-identical code
// but this is an easier-to-understand starting point...
{
std::istringstream iss(token);
int i;
char c;
if (iss >> i && !(iss >> c)) return "Integer";
}
{
std::istringstream iss(token);
float f;
char c; // used to check there's no trailing characters that aren't part
// of the float value... e.g. "1Q" is not a float (rather, "word").
if (iss >> f && !(iss >> c)) return "Float";
}
return "Word";
}
const int maxSize = 100; // Standard C++ won't let you create an array unless const
char cstring[maxSize];
std::cout << "\nPlease enter a string: ";
if (std::cin.getline(cstring, maxSize, '\n'))
{
std::istringstream iss(cstring);
std::string token;
while (iss >> token) // by default, streaming into std::string takes a space-...
token_queue.push(token); // ...separated word at a time
for (token_queue::const_iterator i = token_queue.begin();
i != token_queue.end(); ++i)
std::cout << token_type(*i) << ": " << *i << '\n';
}

Related

Write a C++ code to count the number of a’s in a string [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I've written the code below, but it's giving a number of errors:
15 13 C:\Users\admin\Desktop\Untitled1.cpp [Error] no match for 'operator==' (operand types are 'std::string {aka std::basic_string<char>}' and 'char')
15 28 C:\Users\admin\Desktop\Untitled1.cpp [Error] no match for 'operator==' (operand types are 'std::string {aka std::basic_string<char>}' and 'char')
16 3 C:\Users\admin\Desktop\Untitled1.cpp [Error] expected ')' before 'count'
And some more.
#include<iostream>
#include<string>
using namespace std;
int main()
{
int len,i,count=0;
string str[len];
cout<<"Enter the length for your string:";
cin>>len;
cout<<"Enter the characters for your string:";
for(i=0;i<len;i++)
cin>>str[i];
for(i=0;i<len;i++)
{
if(str[i]=='a'||str[i]=='A')
count++;
}
cout<<"Number of 'a' and 'A' in your string is "<<count<<".";
return 0;
}
You're making this WAY too hard.
#include<iostream>
#include<string>
using namespace std;
int main()
{
int count=0;
string str;
cout<<"Enter the characters for your string:";
getline(cin, str);
for (char c: str) {
if (c == 'a' || c == 'A')
count++;
}
cout<<"Number of 'a' and 'A' in your string is "<<count<<"." << endl;
return 0;
}
My changes from yours:
I got rid of len and the index. You don't need them.
I used getline() to get an entire line. The loop is just silly.
I used a simpler form of a for-loop to loop through the characters.
And I added an endl to the final cout.
One major reason to favour std::string over plain character arrays is that std::string can resize easily. You need not tell a std::string its size beforehand.
This:
string str[len];
Is an array of strings. Its size is len, but len is uninitialized, hence your code has undefined behavior.
A single string is this:
std::string str;
You don't need to, but if you still want you can resize a string upfront. Though if you do that you still should not keep track of its size seperately from the string. It has a size() method and to loop all characters in the string you can use a range-based loop:
std::string str;
std::cout << "Enter the length for your string:";
std::cin >> len;
str.resize(len);
std::cout << "Enter the characters for your string:";
for(auto& c : str) std::cin >> c;
str[i] is then the i-th character in the string. In your code str[i] is the i-th string in the array. Thats why you get an error about mixing characters ('A') and strings (str[i]).
You are declaring an array of strings (and doing so incorrectly at that). Then you are filling the array with len number of strings not characters, and then trying to compare each string to a single character. But std::string does not have an operator== for that comparison, which is exactly what the first 2 errors are telling you.
Get rid of the array, you should be working with a single std::string instead, eg:
#include <iostream>
#include <string>
int main()
{
int len, i, count = 0;
char ch;
std::string str;
std::cout << "Enter the length for your string:";
std::cin >> len;
std::cout << "Enter the characters for your string:";
for (i = 0; i < len; ++i)
{
std::cin >> ch; // or: std::cin.get(ch)
str.push_back(ch);
}
for (i = 0; i < len; ++i)
{
if (str[i] == 'a' || str[i] == 'A')
++count;
}
std::cout << "Number of 'a' and 'A' in your string is " << count << ".";
return 0;
}
You can take that a step further by also getting rid of len too, let std::cin populate the string for you, eg:
#include <iostream>
#include <string>
int main()
{
int count = 0;
std::string str;
std::cout << "Enter your string:";
std::cin >> str; // or: std::getline(std::cin, str);
for (size_t i = 0; i < str.size(); ++i)
{
if (str[i] == 'a' || str[i] == 'A')
++count;
}
std::cout << "Number of 'a' and 'A' in your string is " << count << ".";
return 0;
}
And then you can get rid of the for loop too, by using the standard std::count_if() algorithm, eg:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string str;
std::cout << "Enter your string:";
std::cin >> str; // or: std::getline(std::cin, str);
size_t count = std::count_if(str.begin(), str.end(),
[](char ch){ return (ch == 'a' || ch == 'A'); }
);
std::cout << "Number of 'a' and 'A' in your string is " << count << ".";
return 0;
}
This declares an array of std::string's, not a single string with the length len:
string str[len];
Instead declare a std::string and use std::getline to read whatever it is that the user types in. You can then use std::ranges::count_if (or std::count_if prior to C++20) to count the number of a:s and A:s in the string:
#include <algorithm> // std::ranges::count_if, std::count_if
#include<iostream>
#include<string>
int main() {
std::string str;
std::cout << "Enter the characters for your string:";
std::getline(std::cin, str);
// a lambda to check if an individual character is an 'a' or 'A'
auto a_or_A_lambda = [](char ch) { return ch == 'a' || ch == 'A'; };
// use count_if and with the lambda
auto count = std::ranges::count_if(str, a_or_A_lambda);
// prior to C++20:
//auto count = std::count_if(str.begin(), str.end(), a_or_A_lambda);
std::cout << "Number of 'a' and 'A' in your string is "<< count << ".\n";
}

print 2nd word in a string with its size in C++

I am trying to make a program in which a user enters a string and i will print out the second word in the string with its size.
The delimiter's are space( ), comma(,) and tab( ).
I have used a character array and fgets to read from user and a character pointer that points to the first element of the array.
source code:
#include"iostream"
#include<stdio.h>
#include<string>
using namespace std;
// extract the 2nd word from a string and print it with its size(the number of characters in 2nd word)
int main()
{
char arr[30], arr1[30];
char *str = &arr1[0];
cout<<"Enter a string: ";
fgets(str, 30, stdin);
int i = 0, j, count = 1, p = 0; // count is used to find the second word
// j points to the next index where the first delimiter is found.
// p is used to store the second word found in character array 'arr'
while(*(str+i) != '\n')
{
if(*(str+i) == ' ' || *(str+i) == ',' || *(str+i) == ' ')
{
count++;
if(count == 2)
{
// stroing 2nd word in arr character array
j = i+1;
while(*(str+j) != ' ' || *(str+j) != ',' || *(str+j) != ' ')
{
arr[p] = *(str+j);
cout<<arr[p];
p++;
i++;
j++;
}
break;
}
}
i++;
}
arr[p+1] = '\0'; // insert NULL at end
i = 0;
while(arr[i] != '\0')
{
cout<<arr[i];
i++;
}
cout<<"("<<i<<")"<<endl;
return 0;
}
Help me out with this.
To start, don't use std::cin for testing. Just set a value in your code for consistency and ease of development. Use this page for a reference.
#include <iostream>
#include <string>
int main() {
std::string str("this and_that are the tests");
auto start = str.find_first_of(" ,\n", 0);
auto end = str.find_first_of(" ,\n", start + 1);
std::cout << str.substr(start, end - start);
return 0;
}
And this is still somewhat of a hack, it just depends where you are going. For instance the Boost library is rich with extended string manipulation. If you are going to parse out more than just one word it can still be done with string manipulations, but ad-hoc parsers can get out of hand. There are other tools like Boost Spirit to keep code under control.
The delimiters used when extracting from a stream depends on the locale currently in effect. One (cumbersome) way to change the extraction behaviour is to create a new locale with a special facet in which you specify your own delimiters. In the below example the new locale is used to imbue a std::stringstream instead of std::cin directly. The facet creation part is mostly copy/paste from other answers here on SO, so you'll find plenty of other examples.
#include <iostream>
#include <locale> // std::locale, std::ctype<char>
// https://en.cppreference.com/w/cpp/locale/ctype_char
#include <sstream> // std::stringstream
#include <algorithm> // std::copy_n
#include <vector> // a container to store stuff in
// facet to create our own delimiters
class my_facet : public std::ctype<char> {
mask my_table[table_size];
public:
my_facet(size_t refs = 0)
: std::ctype<char>(&my_table[0], false, refs)
{
// copy the "C" locales table to my_table
std::copy_n(classic_table(), table_size, my_table);
// and create our delimiter specification
my_table[' '] = (mask)space;
my_table['\t'] = (mask)space;
my_table[','] = (mask)space;
}
};
int main() {
std::stringstream ss;
// create a locale with our special facet
std::locale loc(std::locale(), new my_facet);
// imbue the new locale on the stringstream
ss.imbue(loc);
while(true) {
std::string line;
std::cout << "Enter sentence: ";
if(std::getline(std::cin, line)) {
ss.clear(); // clear the string stream from prior errors etc.
ss.str(line); // assign the line to the string stream
std::vector<std::string> words; // std::string container to store all words in
std::string word; // for extracting one word
while(ss>>word) { // extract one word at a time using the special facet
std::cout << " \"" << word << "\" is " << word.size() << " chars\n";
// put the word in our container
words.emplace_back(std::move(word));
}
if(words.size()>=2) {
std::cout << "The second word, \"" << words[1] << "\", is " << words[1].size() << " chars\n";
} else {
std::cout << "did not get 2 words or more...\n";
}
} else break;
}
}
#include"iostream"
#include<stdio.h>
#include<string>
#include <ctype.h>
using namespace std;
int main()
{
char c;
string str;
char emp = ' ';
cout<<"Enter a string: ";
getline (cin,str);
int j = 0, count = 1, counter = 0;
for (int i = 0; i < str.length() && count != 2; i++)
{
cout<< str[i] <<endl;
if( isspace(str[i]) || str[i] == ',' || str[i] == '\t' )
{
count++;
if(count == 2)
{
j = i+1;
while(j < str.length())
{
if (isspace(str[j]) || str[j] == ',' || str[j] == '\t')
{
break;
}
cout<<str[j];
counter++;
j++;
}
cout<<endl;
}
}
}
cout<<"size of the word: "<<counter<<endl;
return 0;
}
This is a simple answer to what you want, hope to help you.
// Paul Adrian P. Delos Santos - BS Electronics Engineering
// Exercise on Strings
#include <iostream>
#include <sstream>
using namespace std;
int main(){
// Opening Message
cout << "This program will display the second word and its length.\n\n";
// Ask for a string to the user.
string input;
cout << "Now, please enter a phrase or sentence: ";
getline(cin, input);
// Count the number of words to be used in making a string array.
int count = 0;
int i;
for (i=0; input[i] != '\0'; i++){
if (input[i] == ' ')
count++;
}
int finalCount = count + 1;
// Store each word in a string array.
string arr[finalCount];
int j = 0;
stringstream ssin(input);
while (ssin.good() && j < finalCount){
ssin >> arr[j];
j++;
}
// Display the second word and its length.
string secondWord = arr[1];
cout << "\nResult: " << arr[1] << " (" << secondWord.size() << ")";
return 0;
}

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;
}

How to make user input numbers only in C++?

So far, this is my code:
while(bet > remaining_money || bet < 100)
{
cout << "You may not bet lower than 100 or more than your current money. Characters are not accepted." << endl;
cout << "Please bet again: ";
cin >> bet;
}
It works fine but I'm trying to figure out how to make it loop if the user inputs anything that isn't a number as well.
When I press a letter or say a symbol/sign, the code just breaks.
Using the function
isdigit()
This function returns true if the argument is a decimal digit (0–9)
Don't forget to
#include <cctype>
I would use std::getline and std::string to read the whole line and then only break out of the loop when you can convert the entire line to a double.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}
A good way of doing this is to take the input as a string. Now find the length of the string as:
int length = str.length();
Make sure to include string and cctype. Now, run a loop that checks the whole string and sees if there is a character that is not a digit.
bool isInt = true;
for (int i = 0; i < length; i++) {
if(!isdigit(str[i]))
isInt = false;
}
If any character is not a digit, isInt will be false. Now, if your input(a string) is all digits, convert it back to an integer as:
int integerForm = stoi(str);
Store integerForm in your array.

reverse of the string using recursion

Hey guys i get stuck in the unusual situation. This is my code, it works perfectly for returning the reverse of the string but it gives output with including the space so I don't want that space to be included in my programme output so anyone has suggestions about this plz share it... by the way this is my code :
#include <iostream>
using namespace std;
string reverse(string str, int size) {
if (size == -1)
return "";
else
{
char a;
a = str[size];
return a + reverse(str, size - 1);
}
}
int main() {
int size;
cout << "the size of the string : ";
cin >> size;
string str;
cout << "enter the word : ";
cin >> str;
cout << reverse(str, size);
}
Since you use std::string, you don't need to specify the size of the string, but use the std::string::size() or std::string::length() member functions. Also, a = str[size]; is problematic when size equals to the size of the string, since you perform an out of bound access (remember that C++ uses zero-based indexing). You can simplify the code a lot, ending up with
#include <iostream>
#include <cstddef> // for std::size_t
using namespace std;
string reverse(string str, std::size_t pos) {
return (pos == 0 ? "" : str[pos - 1] + reverse(str, pos - 1));
}
int main() {
string str;
cout << "enter the word : ";
getline(cin, str); // allow for spaces in the string
cout << reverse(str, str.size()) << endl;
}
Here, instead of using cin >> str, I used getline(cin, str), since cin reads up to the first whitespace, whereas getline allows to read strings that containg spaces.
Change the implementation of the function reverse to the following.
string reverse(string str ,int size){
if (size==-1)
return "";
else
{
char a;
a=str[size];
if (' ' == a )
return reverse(str,size-1)
else
return a+reverse(str,size-1);
}
}
Alternatively, do some pre-processing on th input.