#include <cstdio>
#include <string>
#include <set>
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
int t, z;
scanf("%d", &t);
while (t--) {
string buf, str;
getline(cin, str);
stringstream ss(str);
int cnt = 0;
set<string> tokens;
while (ss >> buf) {
tokens.insert(buf);
}
for (set<string>::iterator it = tokens.begin(); it != tokens.end(); ++it) {
cnt++;
}
printf("%d\n", cnt);
}
return 0;
}
This code is just used for counting the number of different words present in a string. e.g for input
i am i
wil give output
2
But when i enter the test cases it first gives 0 as output neglecting the last test case..what is the reason for it?? and how can it be corrected??
Here is the link
Your scanf is only reading the integer - it doesn't read the end of line. So your first "line" is the rest of the line with "4" on it. Either read to the end of the line or use the solution from user3477950.
Sameer,
modify your code thus:
int main()
{
char eatNewline = '\0';
int t, z;
scanf("%d", &t);
eatNewline=getchar(); //Eat the enter key press.
while (t--)
{
string buf, str;
getline(cin, str);
stringstream ss(str);
int cnt = 0;
set<string> tokens;
while (ss >> buf)
{
tokens.insert(buf);
}
for (set<string>::iterator it = tokens.begin(); it != tokens.end(); ++it)
{
cnt++;
}
printf("%d\n", cnt);
}
return 0;
}
[root#saas ~]# ./tst
4
now do it now
3
now do it now
3
I am good boy
4
am am
1
Please let me know if that helps you! :)
because after you scanf("%d", &t), the tailing \n is still in the input string buffer.
To fix this problem, you can change it to:
scanf("%d ", &t); // add a space after %d to catch the '\n' character
or add
cin >> ws;
or use gets(...) etc.
Related
I am reading a file using fstream and getline functions. I want to give a starting position e.g. my file has 13 lines I want to start reading it from 7th line for example. Here is my code:
#include<iostream>
#include <stdlib.h>
#include <string>
#include <vector>
#include<iterator> // for iterators
#include<map>
using namespace std;
int main()
{
string line;
int start= 7;
unsigned long int index;
For( int z=1; z<=13; z++){
if (f_node.is_open())
{
getline(f_node, line);
if ((line.find("$EndNodes") != string::npos))
{
cout << "$EndNodes found file closed .... " << endl;
f_node.close();
return false;
}
// Point index.
int i = 0;
int j = line.find_first_of(" ", i);
index = strtoul((line.substr(i, j)).c_str(), NULL, 0);//
}
}
I am reading only indexes and I want to start it from 7th index How to do it?
To discard some number of lines, something like:
#include <fstream>
#include <string>
int main() {
std::ifstream infile{"myfile.txt"};
std::string line;
int starting_line = 7;
// Read and discard beginning lines
for (int n = 1; n < starting_line; n += 1) {
if (!std::getline(infile, line)) {
// Error or premature end of file! Handle appropriately.
}
}
while (std::getline(infile, line)) {
// Do something with the lines you care about.
}
return 0;
}
Except with actual error checking and handling and such.
"there is no way to tell code the starting position like seekg and tellg?" No. NL is just like any other character, it does not receive any special treatment.
You simply must scan the stream, counting the new-line character:
std::istream& seek_line(std::istream& is, const int n, std::ios_base::seekdir way = std::ios_base::beg)
{
is.seekg(0, way);
int i = 0;
char c;
while (is.get(c) && i < n)
if (c == '\n')
++i;
is.putback(c);
return is;
}
And this is how you use the above function:
int main()
{
using namespace std;
ifstream is{ "c:\\temp\\test.txt" };
if (!is)
return -1;
if (!seek_line(is, 3))
return -2;
string s;
getline(is, s);
cout << s << endl;
return 0;
}
I'm trying to do parsing to some input string reactions read from file at formula :2W+B=8A+10Z, I'm not interested in characters i need only to split and extract the integer values to put them in a vector i.e vector associated with the reaction here is :[2 1 8 10]
i thought about many things: std::strtok(),isdigital(),find_first_of() but they all didn't work for integer values ... can any body help ??
here my try:
int main()
{
std::string input;
std::getline(std::cin, input);
std::stringstream stream(input);
while(1) {
int n;
stream >> n;
char * pch;
pch = strtok (input," ");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.");
}
}
}
This will do what you want in this particular case. However, i suggest that you look into regex to parse your equation better. You may want to consider all possible cases for your input. This includes \,-,* and other operators that you may want to add in your equation. Also, I'm assuming variables in your equation has only one character.
int main()
{
string input;
getline(std::cin, input);
stringstream stream(input);
char tmp[256];
const char *in = input.c_str();
char str[256];
strcpy(str,in);
int x;
tmp[0]='\0';
char c;
vector<int> vec;
//Scan for the digit
//if it is, store the rest of the string back to str
//if it isn't, store the part of the string before a digit to tmp
while (sscanf(str,"%d%s",&x,str) || sscanf(str,"%[^0123456789]%s",tmp,str) > 1)
{
//check if tmp has the form [variable name]+[a string]
//a string can include another variable name and an operator, = in this case
while(sscanf(tmp,"%c+%[^0123456789]",&c,tmp) > 1)
vec.push_back(1);
if (tmp[0]=='\0')
vec.push_back(x);
tmp[0]='\0';
}
//just in case there're more special cases
while(sscanf(str,"%c+%[^0123456789]",&c,str) > 1)
vec.push_back(1);
for(int i = 0; i < vec.size(); i++)
cout << vec[i] << endl;
}
Output:
2
1
8
10
See comments for explanation.
EDIT
Be careful when you have a special case 2W+B=8A+10Z+C+D. Notice the last C D should both have coefficients 1. This could happen in the middle of the equation too.
Here is another solution:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string equ;
vector<int> digits;
cout << "enter your equation: \n";
cin >> equ;
for (auto i : equ)
{
if (isdigit(i))
{
digits.push_back(stoi(string{i}));
}
}
for (auto& i : digits)
{
cout << i << endl;
}
system("pause");
return 0;
}
You could simply do something like this, for comments see code
#include <iostream>
#include <string>
#include <vector>
std::vector<int> Split(std::string str)
{
std::vector<int> result; // will contain the different ints
// set pointer to first character in the string
char const* pch = str.c_str();
std::string digit; // buffer to keep digits if more than one
int sign = 1; // each number has a sign -1 or 1
for (; *pch; ++pch)
{
if (std::isdigit(*pch)) // if a digit, put in temp buffer
{
digit += *pch;
}
else if (std::isalpha(*pch)) // if not a digit evaluate the ones we have
{
if (digit.empty()) // none so assume 1 before letter e.g. W+2B
{
result.push_back(1*sign);
}
else
{
result.push_back(stoi(digit)*sign);
digit = "";
}
}
else // determine sign of number
{
digit = "";
if (*pch == '+')
{
sign = 1;
}
else if (*pch == '-')
{
sign = -1;
}
}
}
return result;
}
int main()
{
using namespace std;
string expr{"-2W+B=-8A+10Z"};
auto digits = Split(expr);
for (auto& digit : digits)
{
cout << digit << endl;
}
return 0;
}
I have been scratching my head to figure out why is my program is crashing. My aim was to scan a string and get frequency of each sub string !
The Real part where the program is crashing (M is a map of string,int type)
My Input: the string is "abab" and the program crashes when i=0 and j is equal to 3 just at the M[e]++ statement!
for(i=0;str[i];i++)
{
char temp[5001];
k=0;
cout<<str[i]<<endl;
for(j=i;str[j];j++)
{
temp[k]=(char)str[j];
k++;
temp[k]='\0';
string e(temp);
M[e]++;
cout<<j<<endl;
}
}
MAIN Method
int main()
{
ini();
int t,N,i,j,Q,buff,k=0;
char str[5001];
scanf("%d",&t);
map <string ,int > M;
map <string , int >::iterator ii;
for(;t--;)
{
scanf("%d%d",&N,&Q);
scanf(" %s",str);
for(i=0;str[i];i++)
{
char temp[5001];
k=0;
cout<<str[i]<<endl;
for(j=i;str[j];j++)
{
temp[k]=(char)str[j];
k++;
temp[k]='\0';
string e(temp);
M[e]++;
cout<<j<<endl;
}
}
for(ii=M.begin();ii!=M.end();++ii)
F[ii->second]++;
F2[N]=F[N]%MOD;
for(i=N;i>=1;i--)
if(F[i])
for(j=i-1;j>=1;j--)
F2[j]=(F[j]+((long long)F[i]%MOD*C(F[i],j)%MOD)%MOD)%MOD;
for(i=0;i<Q;i++)
{
scanf("%d",&buff);
printf("%d\n",F2[buff]);
}
}
return 0;
}
Note
int F[5001],F2[5001];
are declared globally too.
As requested:
#include <iostream>
#include <string>
#include <map>
#define MOD 10
using namespace std;
int C( int a, int b ){
return 5;
}
int F[5001],F2[5001];
int main()
{
int t,N,i,j,Q,buff,k=0;
string str(5001, ' ');
cin >> t;//scanf("%d",&t);
cin.ignore( 256, '\n' );
map <string ,int > M;
map <string , int >::iterator ii;
for(;t--;)
{
cin >> N;
cin.ignore( 256, '\n' );
cin >> Q;
cin.ignore( 256, '\n' );
//scanf(" %s",str);
getline(cin,str);
for(i=0;str[i];i++)
{
char temp[5001];
k=0;
cout<<str[i]<<endl;
for(j=i;str[j];j++)
{
temp[k]=(char)str[j];
k++;
temp[k]='\0';
string e(temp);
M[e]++;
cout<<j<<endl;
}
}
for(ii=M.begin();ii!=M.end();++ii)
F[ii->second]++;
F2[N]=F[N]%MOD;
for(i=N;i>=1;i--)
if(F[i])
for(j=i-1;j>=1;j--)
cout << "hello";F2[j]=(F[j]+((long long)F[i]%MOD*C(F[i],j)%MOD)%MOD)%MOD;
for(i=0;i<Q;i++)
{
scanf("%d",&buff);
printf("%d\n",F2[buff]);
}
}
return 0;
}
For testing purposes, because there was no MOD and C definitions given, for MOD I used a constant int and C an empty function that received those parameters and simply returned a value.
Instead of scanf, I used cin for the inputs and later cin.ignore() to clear the input buffer so that it won't skip the next cin. Changed str to type string. Used getline to get input for string, as this reads the enitre line from the input cin. And that is it for modifications.
for(i=0;str[i];i++)
{
for(j=0;str[j+i];j++)
{
M[str.substr(j,i+1)]++;
}
}
Replace internal two for loops with this and check whether it's crashing or not . If still that means you may be running this program on windows.In that case use this.
for(i=0;str[i];i++)
{
for(j=0;str[j+i];j++)
{
std::string sstr = str.substr(j,i+1);
if ( M.find ( sstr ) == M.end() ){
M.insert( std::make_pair ( sstr , 0 ) ) ;
}
else
M[str.substr(j,i+1)]++;
}
}
Using if and while/do-while, my job is to print following user's inputs (string value) in reverse order.
For example:
input string value : "You are American"
output in reverse order : "American are You"
Is there any way to do this?
I have tried
string a;
cout << "enter a string: ";
getline(cin, a);
a = string ( a.rbegin(), a.rend() );
cout << a << endl;
return 0;
...but this would reverse the order of the words and spelling while spelling is not what I'm going for.
I also should be adding in if and while statements but do not have a clue how.
The algorithm is:
Reverse the whole string
Reverse the individual words
#include<iostream>
#include<algorithm>
using namespace std;
string reverseWords(string a)
{
reverse(a.begin(), a.end());
int s = 0;
int i = 0;
while(i < a.length())
{
if(a[i] == ' ')
{
reverse(a.begin() + s, a.begin() + i);
s = i + 1;
}
i++;
}
if(a[a.length() - 1] != ' ')
{
reverse(a.begin() + s, a.end());
}
return a;
}
Here is a C-based approach that will compile with a C++ compiler, which uses the stack to minimize creation of char * strings. With minimal work, this can be adapted to use C++ classes, as well as trivially replacing the various for loops with a do-while or while block.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_LENGTH 1000
#define MAX_WORD_LENGTH 80
void rev(char *str)
{
size_t str_length = strlen(str);
int str_idx;
char word_buffer[MAX_WORD_LENGTH] = {0};
int word_buffer_idx = 0;
for (str_idx = str_length - 1; str_idx >= 0; str_idx--)
word_buffer[word_buffer_idx++] = str[str_idx];
memcpy(str, word_buffer, word_buffer_idx);
str[word_buffer_idx] = '\0';
}
int main(int argc, char **argv)
{
char *line = NULL;
size_t line_length;
int line_idx;
char word_buffer[MAX_WORD_LENGTH] = {0};
int word_buffer_idx;
/* set up line buffer - we cast the result of malloc() because we're using C++ */
line = (char *) malloc (MAX_LINE_LENGTH + 1);
if (!line) {
fprintf(stderr, "ERROR: Could not allocate space for line buffer!\n");
return EXIT_FAILURE;
}
/* read in a line of characters from standard input */
getline(&line, &line_length, stdin);
/* replace newline with NUL character to correctly terminate 'line' */
for (line_idx = 0; line_idx < (int) line_length; line_idx++) {
if (line[line_idx] == '\n') {
line[line_idx] = '\0';
line_length = line_idx;
break;
}
}
/* put the reverse of a word into a buffer, else print the reverse of the word buffer if we encounter a space */
for (line_idx = line_length - 1, word_buffer_idx = 0; line_idx >= -1; line_idx--) {
if (line_idx == -1)
word_buffer[word_buffer_idx] = '\0', rev(word_buffer), fprintf(stdout, "%s\n", word_buffer);
else if (line[line_idx] == ' ')
word_buffer[word_buffer_idx] = '\0', rev(word_buffer), fprintf(stdout, "%s ", word_buffer), word_buffer_idx = 0;
else
word_buffer[word_buffer_idx++] = line[line_idx];
}
/* cleanup memory, to avoid leaks */
free(line);
return EXIT_SUCCESS;
}
To compile with a C++ compiler, and then use:
$ g++ -Wall test.c -o test
$ ./test
foo bar baz
baz bar foo
This example unpacks the input string one word at a time,
and builds an output string by concatenating in reverse order.
`
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
string inp_str("I am British");
string out_str("");
string word_str;
istringstream iss( inp_str );
while (iss >> word_str) {
out_str = word_str + " " + out_str;
} // while (my_iss >> my_word)
cout << out_str << endl;
return 0;
} // main
`
This uses exactly one each of if and while.
#include <string>
#include <iostream>
#include <sstream>
void backwards(std::istream& in, std::ostream& out)
{
std::string word;
if (in >> word) // Read the frontmost word
{
backwards(in, out); // Output the rest of the input backwards...
out << word << " "; // ... and output the frontmost word at the back
}
}
int main()
{
std::string line;
while (getline(std::cin, line))
{
std::istringstream input(line);
backwards(input, std::cout);
std::cout << std::endl;
}
}
You might try this solution in getting a vector of string's using the ' ' (single space) character as a delimiter.
The next step would be to iterate over this vector backwards to generate the reverse string.
Here's what it might look like (split is the string splitting function from that post):
Edit 2: If you don't like vectors for whatever reason, you can use arrays (note that pointers can act as arrays). This example allocates a fixed size array on the heap, you may want to change this to say, double the size when the current word amount has reached a certain value.
Solution using an array instead of a vector:
#include <iostream>
#include <string>
using namespace std;
int getWords(string input, string ** output)
{
*output = new string[256]; // Assumes there will be a max of 256 words (can make this more dynamic if you want)
string currentWord;
int currentWordIndex = 0;
for(int i = 0; i <= input.length(); i++)
{
if(i == input.length() || input[i] == ' ') // We've found a space, so we've reached a new word
{
if(currentWord.length() > 0)
{
(*output)[currentWordIndex] = currentWord;
currentWordIndex++;
}
currentWord.clear();
}
else
{
currentWord.push_back(input[i]); // Add this character to the current word
}
}
return currentWordIndex; // returns the number of words
}
int main ()
{
std::string original, reverse;
std::getline(std::cin, original); // Get the input string
string * arrWords;
int size = getWords(original, &arrWords); // pass in the address of the arrWords array
int index = size - 1;
while(index >= 0)
{
reverse.append(arrWords[index]);
reverse.append(" ");
index--;
}
std::cout << reverse << std::endl;
return 0;
}
Edit: Added includes, main function, while loop format
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
// From the post
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
return split(s, delim, elems);
}
int main ()
{
std::string original, reverse;
std::cout << "Input a string: " << std::endl;
std::getline(std::cin, original); // Get the input string
std::vector<std::string> words = split(original, ' ');
std::vector<std::string>::reverse_iterator rit = words.rbegin();
while(rit != words.rend())
{
reverse.append(*rit);
reverse.append(" "); // add a space
rit++;
}
std::cout << reverse << std::endl;
return 0;
}
This code here uses string libraries to detect the blanks in the input stream and rewrite the output sentence accordingly
The algorithm is
1. Get the input stream using getline function to capture the spacecs. Initialize pos1 to zero.
2. Look for the first space in the input stream
3. If no space is found, the input stream is the output
4. Else, get the position of the first blank after pos1, i.e. pos2.
5. Save the sub-string bewteen pos1 and pos2 at the beginning of the output sentence; newSentence.
6. Pos1 is now at the first char after the blank.
7. Repeat 4, 5 and 6 untill no spaces left.
8. Add the last sub-string to at the beginning of the newSentence. –
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string sentence;
string newSentence;
string::size_type pos1;
string::size_type pos2;
string::size_type len;
cout << "This sentence rewrites a sentence backward word by word\n"
"Hello world => world Hello"<<endl;
getline(cin, sentence);
pos1 = 0;
len = sentence.length();
pos2 = sentence.find(' ',pos1);
while (pos2 != string::npos)
{
newSentence = sentence.substr(pos1, pos2-pos1+1) + newSentence;
pos1 = pos2 + 1;
pos2 = sentence.find(' ',pos1);
}
newSentence = sentence.substr(pos1, len-pos1+1) + " " + newSentence;
cout << endl << newSentence <<endl;
return 0;
}
I have a string currentLine="12 23 45"
I need to extract 12, 23, 45 from this string without using Boost libraries. Since i am using string, strtok fails for me. I have tried a number of things still no success.
Here is my last attempt
while(!inputFile.eof())
while(getline(inputFile,currentLine))
{
int countVar=0;
int inputArray[10];
char* tokStr;
tokStr=(char*)strtok(currentLine.c_str()," ");
while(tokstr!=NULL)
{
inputArray[countVar]=(int)tokstr;
countVar++;
tokstr=strtok(NULL," ");
}
}
}
the one without strtok
string currentLine;
while(!inputFile.eof())
while(getline(inputFile,currentLine))
{
cout<<atoi(currentLine.c_str())<<" "<<endl;
int b=0,c=0;
for(int i=1;i<currentLine.length();i++)
{
bool lockOpen=false;
if((currentLine[i]==' ') && (lockOpen==false))
{
b=i;
lockOpen=true;
continue;
}
if((currentLine[i]==' ') && (lockOpen==true))
{
c=i;
break;
}
}
cout<<b<<"b is"<<" "<<c;
}
Try this:
#include <sstream>
std::string str = "12 34 56";
int a,b,c;
std::istringstream stream(str);
stream >> a >> b >> c;
Read a lot about c++ streams here: http://www.cplusplus.com/reference/iostream/
std::istringstream istr(your_string);
std::vector<int> numbers;
int number;
while (istr >> number)
numbers.push_back(number);
Or, simpler (though not really shorter):
std::vector<int> numbers;
std::copy(
std::istream_iterator<int>(istr),
std::istream_iterator<int>(),
std::back_inserter(numbers));
(Requires the standard headers <sstream>, <algorithm> and <iterator>.)
You can also opt for Boost tokenizer ......
#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <boost/tokenizer.hpp>
using namespace std;
using namespace boost;
int main(int argc, char** argv)
{
string str= "India, gold was dear";
char_separator<char> sep(", ");
tokenizer< char_separator<char> > tokens(str, sep);
BOOST_FOREACH(string t, tokens)
{
cout << t << "." << endl;
}
}
stringstream and boost::tokenizer are two possibilities. Here is a more explicit solution using string::find and string::substr.
std::list<std::string>
tokenize(
std::string const& str,
char const token[])
{
std::list<std::string> results;
std::string::size_type j = 0;
while (j < str.length())
{
std::string::size_type k = str.find(token, j);
if (k == std::string::npos)
k = str.length();
results.push_back(str.substr(j, k-j));
j = k + 1;
}
return results;
}
Hope this helps. You can easily turn this into an algorithm that writes the tokens to arbitrary containers or takes a function handle that processes the tokens.