As I'm familiarizing myself with the I/O aspect of C++, I'm trying to write a program to read some lines of integers from std::cin. Say the input looks like this:
1 2 3
4 5 6
7 8 9
10 11 12
How can I read the above lines into a 2D vector?
vector<vector<int>> nums;
/*
... some code here and nums will look like the following:
nums = {
{1,2,3},
{4,5,6},
{7,8,9},
{10,11,12}
}
*/
I've also tried to read the above lines of integers to a 1D vector, but I'm having some issues dealing with the '\n' character. My code is:
string rawInput;
vector<int> temp;
while(getline(cin, rawInput, ' ') ){
int num = atoi( rawInput.c_str() );
temp.push_back(num);
}
And the final result I got by printing out all the elements in the "temp" vector is:
1 2 3 5 6 8 9 11 12 // 4, 7, 10 went missing
Any help is appreciated. Thank you.
First use getline to grab an entire line, then you can use a istringstream to create a stream of ints just for that line.
At that point it's just a matter of creating each subvector of ints using the vector constructor that takes two iterators. An istream_iterator<int> on your istringstream gets this done:
std::vector<std::vector<int>> nums;
std::string line;
while (std::getline(std::cin, line)) {
std::istringstream ss(line);
nums.emplace_back(std::istream_iterator<int>{ss}, std::istream_iterator<int>{});
}
What is happening is since you are using only ' '(space) as deliminator, the input happens to be
1
2
3\n4 //<------ Newline also comes with the input
...
So, you are passing 3\n4, 6\n7 etc to atoi it returns 3,6 etc(atoi parses the input till first non-digit input) and the 4,7 is lost.
To achieve want you want you can use getline with istringstream (keeping the default deliminator as newline)
string rawInput;
vector<vector<int>> temp;
while(getline(cin, rawInput) ){
istringstream bufferInput(rawInput);
temp.push_back(vector<int>{std::istream_iterator<int>{bufferInput}, std::istream_iterator<int>{}});
}
you can use stringstream
string rawInput;
vector<int> temp;
stringstream ss;
while(getline(cin,rawInput)){
ss<<rawInput;
vector<int> temp;
int x;
while(ss>>x){
temp.push_back(x);
}
num.push_back(temp)
}
I recently wrote an answer to another question but with a few adaptations it achieves exactly what you are looking for (I hope):
#ifndef _IOSTREAM_H
#include <iostream>
#endif
#ifndef _STRING_H
#include <string>
#endif
#ifndef _VECTOR_H
#include <vector>
#endif
using namespace std;
enum XYZ { X = 0, Y = 1, Z = 2 };
struct Vector {
float x, y, z;
Vector(float _x=0, float _y=0, float _z=0) {
x = _x;
y = _y;
z = _z;
}
float& operator[](size_t index) {
if (index == XYZ::X) return x;
if (index == XYZ::Y) return y;
if (index == XYZ::Z) return z;
throw new exception;
}
};
#define min(a, b) (((a) < (b)) ? (a) : (b))
bool isCharNumeric(char c) {
const char* numbers = "0123456789";
for (size_t index = 0; index < strlen(numbers); index++)
if (c == numbers[index]) return true; return false;
}
vector<Vector> parseNumbers(string str_in) {
str_in += " "; //safe, no out of bounds
vector<Vector> results = {};
char currentChar;
char skipChar = ' ';
bool found_period = false;
size_t count_len = 0;
Vector vector_buffer(0,0,0);
XYZ current_axis = (XYZ)0;
for (size_t index = 0; index < str_in.length(); index++) {
currentChar = str_in[index];
if (currentChar == skipChar || currentChar == '\n' || currentChar == '\t')
continue;
else if (isCharNumeric(currentChar)) {
string word = ""; //word buffer
size_t word_len = min(min(str_in.find_first_of(' ', index + 1) - (index), str_in.find_first_of('\n', index + 1) - (index)), str_in.find_first_of('\t', index + 1) - (index)); //whatever char comes first; newline, tab or space
//append chars of following word checking if it is still valid number char
if (word_len > 0) {
size_t count_word_len = 0;
for (count_word_len = 0; count_word_len < word_len; count_word_len++)
if (isCharNumeric(str_in[index + count_word_len])) {
word += str_in[index + count_word_len];
}
else if (str_in[index + count_word_len] == '.' && isCharNumeric(str_in[index + count_word_len + 1])) {
//Floating-point numbers
word += '.';
found_period = true;
continue;
}
else {
word = "";
continue;
}
vector_buffer[current_axis] = stof(word);
if (current_axis == XYZ::Z) {
current_axis = XYZ::X;
results.push_back(vector_buffer);
}
else {
current_axis = (XYZ)(current_axis + 1);
}
index += count_word_len;
word = "";
continue;
}
}
}
return results;
}
Example implementation:
int main(int argc, char** argv) {
string user_input;
cin >> user_input;
vector<Vector> numbers = parseNumbers(user_input);
for each (Vector v in numbers) {
cout << "X=" << v.X << "\n";
cout << "Y=" << v.Y << "\n";
cout << "Z=" << v.Z << "\n\n";
}
}
Suprisingly none of the answers use the istream stream operator:
http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
When stream is empty eofbit is set, so run a while loop on that.
Works great for all types, and can be overloaded for custom types (such as 2D texture).
Related
I just began learning C++ and had a rookie question.
Suppose I am given an input separated by spaces ex 2 4 56 or 2 1 10 15 or hi bye ok.
How can I store the values in an array as the length of input is not know.
Read up on std::vector. It can grow to the size needed.
search for spaces and split the string in each space as the following
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> GetInputs(string s)
{
vector<size_t> foundSpacesPositions;
vector<string> results;
for (size_t i = 0; i < s.length(); i++)
{
if (isspace(s[i]))
{
foundSpacesPositions.push_back(i);
}
}
size_t start = 0;
for (size_t i = 0; i < foundSpacesPositions.size(); i++)
{
if (foundSpacesPositions[i] == start)
{
++start;
continue;
}
results.push_back(s.substr(start, foundSpacesPositions[i] - start));
start = foundSpacesPositions[i] + 1;
}
if (start < s.length() - 1)
results.push_back(s.substr(start, s.length() - 1));
return results;
}
int _tmain(int argc, _TCHAR* argv[])
{
string s = "a dd 8 ll ehh fd $%^ & 89 . ";
vector<string> results = GetInputs(s);
for (auto& res : results)
{
cout << res << endl;
}
cin.get();
return 0;
}
/* OUTPUT
a
dd
8
ll
ehh
fd
$%^
&
89
.
*/
Well, if the input is given as a string, you can easily use a std::istringstream. If the input is given in stdin, you can just use the std::cin stream. std::istream's operator<< will take integers from a string using spaces as a default delimiter. Once you've read all the input on the stream, std::istream's operator bool will return false, and you can stop reading.
An example implementation would be:
vector<int> getIntsFromString(const string& s) {
istringstream ss(s);
int i;
vector<int> result;
while (ss >> i) result.push_back(i);
return move(result);
}
Suppose you are getting multiple lines with a variable number of integers from stdin, and you want to store them in vector<int>'s. You can do something similar to:
string buf;
while (getline(cin, buf)) {
auto v = getIntsFromString(buf);
for (auto i : v) cout << i << ' ';
cout << endl;
}
I am trying to write a function that reads in individual lines from a text file. Each line has two or three columns. I am want to know most elegant/clean approach for it. I am need the function to work with different separators (\t,\n,' ',',',';').
My approach works correctly except for different separators.
E.g. Input:
6
0 0
1 1
2 2
3 3
4 4
5 5
10
0 1 0.47
2 0 0.67
3 0 0.98
4 0 0.12
2 1 0.94
3 1 0.05
4 1 0.22
3 2 0.24
4 2 0.36
4 3 0.69
Pattern Input:
[total number of vertices]
[id-vertex][\separetor][name-vertex]
...
[total number of edges]
[id-vertex][\separator][id-neighbor][\separetor][weight]
...
*\separetor=\t|\n|' '|','|';'
My approach:
void readStream(istream& is, const char separator) {
uint n, m;
is >> n;
cout << n << endl;
string name;
uint vertexId, neighborId;
float weight;
while(!is.eof()) {
for(uint i = 0; i < n; i++) {
is >> vertexId >> name;
cout << vertexId;
cout << " " << name << endl;
}
is >> m;
cout << m << endl;
for(uint j = 0; j < n; j++) {
is >> vertexId >> neighborId >> weight;
cout << vertexId;
cout << " " << neighborId;
cout << " " << weight << endl;
}
break;
}
}
Overview:
Problem: Different separators.
Others elegantes solutions: In general, someone have other elegant/clean solutions to the problem?
You may use boost split it can split a string on multiple separators that you can specify.
std::string = line;
std::vector<std::string> parts;
boost::split(parts, line, boost::is_any_of("\t\n,; "));
If you are sure the separator is not white space, you can just throw them into a garbage string (e.g. separator in the case follow)
is >> vertexId >> separator >> neighborId >> separator >> weight;
The following code may be useful:
int t1,t2;
double t3;//global variables...
void parse_Vertex_Line(char *str)
{
int tmp=0;
char *p=str;
//extract the vertex-id
while(*p >='0' && *p <='9')
tmp = tmp*10 + *(p++) -'0';
t1=tmp;
tmp=0;
p++;
//now extract the vertex-name..
while(*p >='0' && *p <='9')
tmp = tmp*10 + *(p++) -'0';
t2=tmp;
return;
}
void parse_Edge_Line(char *str)
{
//extracting the first two numbers is just the same...
int tmp=0;
char *p=str;
//extract the first vertex-id
while(*p >='0' && *p <='9')
tmp = tmp*10 + *(p++) -'0';
t1=tmp;
tmp=0;
p++;
//now extract the second vertex-id..
while(*p >='0' && *p <='9')
tmp = tmp*10 + *(p++) -'0';
t2=tmp;
p++;
//but extracting a double value is a bit different...
//extract the weight...
int before_decimal=0, after_decimal=0;
while(*p!='.')
before_decimal = before_decimal*10 + *(p++) -'0';
p++;
int no_of_digits=0;
while(*p>='0' && *p<='9')
{
after_decimal = after_decimal*10 + *(p++) -'0';
no_of_digits++;
}
//assign it to the global double variable...
t3 = before_decimal + (after_decimal/pow(10.0, no_of_digits));
}
Now what you do is first get the number of vertices(n). Next read each of the n lines.
Calling the function parse_Vertex_Line each time. Then read the number of edges and similarly call parse_Edge_Line each time. Extract the values and Store them.
This code works for almost any delimiters. Hope this looks elegant to you.
You could use(Considering that your file will always be in the above mentioned format)
fstream file;
file.open("abc.txt",ios::in);
int numOfVertices;
string line;
getline(file, line);
numOfVertices = stoi(line);
vector<int> xCoord;
vector<int> yCoord;
while((--numOfVertices)>=0)
{
string line;
getline(file, line);
std::size_t prev = 0, pos;
pos = line.find_first_of(" ';", prev);
xCoord.push_back(stoi(line.substr(prev, pos-prev)));
prev = pos+1;
pos = line.find_first_of(" ';", prev); //considering some of the delimiters
yCoord.push_back(stoi(line.substr(prev, pos-prev)));
}
This is to add the vertices. Similarly you may extract the edges as well.
I modified my other posting for this scenario: Override istream operator >> and modify delimiter (The explanation for this is first variant of the accepted solution here for a possible implementation).
In general one way you could possibly deal with the unwanted separators is to turn them into spaces!
My approach enables the use of new delimiters for operations '>>' from istream:
struct delimiterIsSpace : ctype<char> {
delimiterIsSpace() : ctype<char>(get_table()) {}
static mask const* get_table() {
static mask rc[table_size];
rc[';'] = ctype_base::space;
rc[','] = ctype_base::space;
rc[' '] = ctype_base::space;
rc['\t'] = ctype_base::space;
rc['\n'] = ctype_base::space;
return &rc[0];
}
};
How to use:
cin.imbue(locale(cin.getloc(), new delimiterIsSpace));
for (int a, b; cin >> a >> b; ) {
cout << "a=" << a << " b=" << b << "\n";
}
I'm a beginner and am stuck on such a simple problem whilst working through Stroustrup's Principles and Practices.
Using only basic elements
#include "std_lib_facilities.h"
int main()
{
double highest = 0;
double lowest = 100;
int i=0;
double sum = 0;
vector <double> inputlist;
double input;
string unit;
cout<<"Type in a number followed by it's unit \n";
while(cin>>input>>unit){
inputlist.push_back(input);
sum += inputlist[i];
if (input >= lowest && input <= highest){
cout<<input<<" \n";
++i;
}
else if (input < lowest){
lowest = input;
cout<<"\nLowest Number so far \n"<<lowest;
++i;
}
else if (input > highest){
highest = input;
cout<<"\nHighest number so far \n"<< highest;
++i;
}
else
cout<<"Lowest is: \n"<<lowest<<"\n\n Highest is: \n"<<highest<<" \n\n and the total is: \n"<<sum;
if (unit == "ft", "m", "in","cm")
cout<<unit<<"\n";
else
cout<<"cannot recognize unit";
}
keep_window_open();
return 0;
}
I need the program to show the user the sum and highest and lowest value when the character "|" is entered. Problem is: i need this entered where the Integer value should be entered.
NOTE: I don't know much about conversions but tried a few and they didn't work.
If I understood you correctly, you want to read int from std::cin, but:
int i;
if (std::cin >> i) {
...
doesn't suite your needs since there might be '|' sign as a signal for termination of reading.
Here's what you could do: read input word by word (std::string) and parse these words separately using temporary std::istringstream:
std::string word;
if (std::cin >> word) {
if (word == "|")
...
// else:
std::istringstream is(word);
int i;
if (is >> i) {
// integer successfully retrieved from stream
}
}
just #include <sstream>
Read the value with string. if it doesn't match | convert it to double using the following function:
double toDouble(string s)
{
int sign = 1, i=0;
if (s[0]=='-')
sign = -1, i=1;
double result = 0, result2 = 0;
for (; i < s.size(); i++)
if (s[i] == '.')
break;
else
result = result * 10 + (s[i] - '0');
for (i = s.size()-1 ; i>=0 ; i--)
if (s[i] == '.')
break;
else
result2 = result2 / 10 + (s[i] - '0');
if (i>=0)
result += result2/10;
return result * sign;
}
Summing meters with inches does not make much sense. Therefore, you should consider to translate the units into scaling factors. You could use a map to get the scaling factors.
Even if this is somewhat overshoot you might use regular expressions to parse the user input. If the regex does not match you can test for stuff like "|".
In the new c++-standard (http://en.wikipedia.org/wiki/C%2B%2B11) a regex library is defined for this purpose. Pityingly, the g++ regex library is buggy. But you can use boost (http://www.boost.org/doc/libs/1_54_0/libs/regex/doc/html/boost_regex/).
Here is an example:
#include <iostream>
#include <vector>
#include <map>
#include <boost/regex.hpp> //< Pittyingly std::regex is buggy.
using namespace std; ///< Avoid this in larger projects!
using namespace boost;
int main() {
const string strReFloat("([-+]?[[:digit:]]*\\.?[[:digit:]]+(?:[eE][-+]?[[:digit:]]+)?)");
const string strReUnit("([[:alpha:]]+)");
const string strReMaybeBlanks("[[:blank:]]*");
const string strReFloatWithUnit(strReMaybeBlanks+strReFloat+strReMaybeBlanks+strReUnit+strReMaybeBlanks);
const regex reFloatWithUnit(strReFloatWithUnit);
const map<const string,double> unitVal= {
{"m", 1.0},
{"in", 0.0254},
{"ft", 0.3048},
{"cm", 0.01}
};
double highest = 0;
double lowest = 100;
int i=0;
double sum = 0;
vector <double> inputlist;
double input;
double unitToMeter;
string unit;
string str;
while( (cout<<"\nType in a number followed by it's unit \n", getline(cin,str), str != "") ){
smatch parts;
if( regex_match(str,parts,reFloatWithUnit) ) {
unit = parts[2].str();
auto found = unitVal.find(unit);
if( found != unitVal.end() ) {
cout<<unit<<"\n";
input = found->second * atof(parts[1].str().c_str());
} else {
cout << "Unit \"" << unit << "\" not recognized. Using meters.\n";
}
inputlist.push_back(input);
sum += inputlist[i];
if (input >= lowest && input <= highest){
cout<<input<<" \n";
++i;
}
else if (input < lowest){
lowest = input;
cout<<"\nLowest Number so far \n"<<lowest;
++i;
}
else if (input > highest){
highest = input;
cout<<"\nHighest number so far \n"<< highest;
++i;
}
} else if( str == "|" ) {
cout << "sum:" << sum << "\n";
} else {
cout << "Input not recognized.\n";
}
}
return 0;
}
The program below I came up with for checking whether two strings are anagrams. Its working fine for small string but for larger strings ( i tried : listened , enlisted ) Its giving me a 'no !'
Help !
#include<iostream.h>
#include<string.h>
#include<stdio.h>
int main()
{
char str1[100], str2[100];
gets(str1);
gets(str2);
int i,j;
int n1=strlen(str1);
int n2=strlen(str2);
int c=0;
if(n1!=n2)
{
cout<<"\nThey are not anagrams ! ";
return 0;
}
else
{
for(i=0;i<n1;i++)
for(j=0;j<n2;j++)
if(str1[i]==str2[j])
++c;
}
if(c==n1)
cout<<"yes ! anagram !! ";
else
cout<<"no ! ";
system("pause");
return 0;
}
I am lazy, so I would use standard library functionality to sort both strings and then compare them:
#include <string>
#include <algorithm>
bool is_anagram(std::string s1, std::string s2)
{
std::sort(s1.begin(), s1.end());
std::sort(s2.begin(), s2.end());
return s1 == s2;
}
A small optimization could be to check that the sizes of the strings are the same before sorting.
But if this algorithm proved to be a bottle-neck, I would temporarily shed some of my laziness and compare it against a simple counting solution:
Compare string lengths
Instantiate a count map, std::unordered_map<char, unsigned int> m
Loop over s1, incrementing the count for each char.
Loop over s2, decrementing the count for each char, then check that the count is 0
The algorithm also fails when asked to find if aa and aa are anagrams. Try tracing the steps of the algorithm mentally or in a debugger to find why; you'll learn more that way.
By the way.. The usual method for finding anagrams is counting how many times each letter appears in the strings. The counts should be equal for each letter. This approach has O(n) time complexity as opposed to O(n²).
bool areAnagram(char *str1, char *str2)
{
// Create two count arrays and initialize all values as 0
int count1[NO_OF_CHARS] = {0};
int count2[NO_OF_CHARS] = {0};
int i;
// For each character in input strings, increment count in
// the corresponding count array
for (i = 0; str1[i] && str2[i]; i++)
{
count1[str1[i]]++;
count2[str2[i]]++;
}
// If both strings are of different length. Removing this condition
// will make the program fail for strings like "aaca" and "aca"
if (str1[i] || str2[i])
return false;
// Compare count arrays
for (i = 0; i < NO_OF_CHARS; i++)
if (count1[i] != count2[i])
return false;
return true;
}
I see 2 main approaches below:
Sort then compare
Count the occurrences of each letter
It's interesting to see that Suraj's nice solution got one point (by me, at the time of writing) but a sort one got 22. The explanation is that performance wasn't in people's mind - and that's fine for short strings.
The sort implementation is only 3 lines long, but the counting one beats it square for long strings. It is much faster (O(N) versus O(NlogN)).
Got the following results with 500 MBytes long strings.
Sort - 162.8 secs
Count - 2.864 secs
Multi threaded Count - 3.321 secs
The multi threaded attempt was a naive one that tried to double the speed by counting in separate threads, one for each string. Memory access is the bottleneck and this is an example where multi threading makes things a bit worse.
I would be happy to see some idea that would speed up the count solution (think by someone good with memory latency issues, caches).
#include<stdio.h>
#include<string.h>
int is_anagram(char* str1, char* str2){
if(strlen(str1)==strspn(str1,str2) && strlen(str1)==strspn(str2,str1) &&
strlen(str1)==strlen(str2))
return 1;
return 0;
}
int main(){
char* str1 = "stream";
char* str2 = "master";
if(is_anagram(str1,str2))
printf("%s and %s are anagram to each other",str1,str2);
else
printf("%s and %s are not anagram to each other",str1,str2);
return 0;
}
#include<iostream>
#include<unordered_map>
using namespace std;
int checkAnagram (string &str1, string &str2)
{
unordered_map<char,int> count1, count2;
unordered_map<char,int>::iterator it1, it2;
int isAnagram = 0;
if (str1.size() != str2.size()) {
return -1;
}
for (unsigned int i = 0; i < str1.size(); i++) {
if (count1.find(str1[i]) != count1.end()){
count1[str1[i]]++;
} else {
count1.insert(pair<char,int>(str1[i], 1));
}
}
for (unsigned int i = 0; i < str2.size(); i++) {
if (count2.find(str2[i]) != count2.end()) {
count2[str2[i]]++;
} else {
count2.insert(pair<char,int>(str2[i], 1));
}
}
for (unordered_map<char, int>::iterator itUm1 = count1.begin(); itUm1 != count1.end(); itUm1++) {
unordered_map<char, int>::iterator itUm2 = count2.find(itUm1->first);
if (itUm2 != count2.end()) {
if (itUm1->second != itUm2->second){
isAnagram = -1;
break;
}
}
}
return isAnagram;
}
int main(void)
{
string str1("WillIamShakespeare");
string str2("IamaWeakishSpeller");
cout << "checkAnagram() for " << str1 << "," << str2 << " : " << checkAnagram(str1, str2) << endl;
return 0;
}
It's funny how sometimes the best questions are the simplest.
The problem here is how to deduce whether two words are anagrams - a word being essentially an unsorted multiset of chars.
We know we have to sort, but ideally we'd want to avoid the time-complexity of sort.
It turns out that in many cases we can eliminate many words that are dissimilar in linear time by running through them both and XOR-ing the character values into an accumulator. The total XOR of all characters in both strings must be zero if both strings are anagrams, regardless of ordering. This is because anything xored with itself becomes zero.
Of course the inverse is not true. Just because the accumulator is zero does not mean we have an anagram match.
Using this information, we can eliminate many non-anagrams without a sort, short-circuiting at least the non-anagram case.
#include <iostream>
#include <string>
#include <algorithm>
//
// return a sorted copy of a string
//
std::string sorted(std::string in)
{
std::sort(in.begin(), in.end());
return in;
}
//
// check whether xor-ing the values in two ranges results in zero.
// #pre first2 addresses a range that is at least as big as (last1-first1)
//
bool xor_is_zero(std::string::const_iterator first1,
std::string::const_iterator last1,
std::string::const_iterator first2)
{
char x = 0;
while (first1 != last1) {
x ^= *first1++;
x ^= *first2++;
}
return x == 0;
}
//
// deduce whether two strings are the same length
//
bool same_size(const std::string& l, const std::string& r)
{
return l.size() == r.size();
}
//
// deduce whether two words are anagrams of each other
// I have passed by const ref because we may not need a copy
//
bool is_anagram(const std::string& l, const std::string& r)
{
return same_size(l, r)
&& xor_is_zero(l.begin(), l.end(), r.begin())
&& sorted(l) == sorted(r);
}
// test
int main() {
using namespace std;
auto s1 = "apple"s;
auto s2 = "eppla"s;
cout << is_anagram(s1, s2) << '\n';
s2 = "pppla"s;
cout << is_anagram(s1, s2) << '\n';
return 0;
}
expected:
1
0
Try this:
// Anagram. Two words are said to be anagrams of each other if the letters from one word can be rearranged to form the other word.
// From the above definition it is clear that two strings are anagrams if all characters in both strings occur same number of times.
// For example "xyz" and "zxy" are anagram strings, here every character 'x', 'y' and 'z' occur only one time in both strings.
#include <map>
#include <string>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
bool IsAnagram_1( string w1, string w2 )
{
// Compare string lengths
if ( w1.length() != w2.length() )
return false;
sort( w1.begin(), w1.end() );
sort( w2.begin(), w2.end() );
return w1 == w2;
}
map<char, size_t> key_word( const string & w )
{
// Declare a map which is an associative container that will store a key value and a mapped value pairs
// The key value is a letter in a word and the maped value is the number of times this letter appears in the word
map<char, size_t> m;
// Step over the characters of string w and use each character as a key value in the map
for ( auto & c : w )
{
// Access the mapped value directly by its corresponding key using the bracket operator
++m[toupper( c )];
}
return ( m );
}
bool IsAnagram_2( const string & w1, const string & w2 )
{
// Compare string lengths
if ( w1.length() != w2.length() )
return false;
return ( key_word( w1 ) == key_word( w2 ) );
}
bool IsAnagram_3( const string & w1, const string & w2 )
{
// Compare string lengths
if ( w1.length() != w2.length() )
return false;
// Instantiate a count map, std::unordered_map<char, unsigned int> m
unordered_map<char, size_t> m;
// Loop over the characters of string w1 incrementing the count for each character
for ( auto & c : w1 )
{
// Access the mapped value directly by its corresponding key using the bracket operator
++m[toupper(c)];
}
// Loop over the characters of string w2 decrementing the count for each character
for ( auto & c : w2 )
{
// Access the mapped value directly by its corresponding key using the bracket operator
--m[toupper(c)];
}
// Check to see if the mapped values are all zeros
for ( auto & c : w2 )
{
if ( m[toupper(c)] != 0 )
return false;
}
return true;
}
int main( )
{
string word1, word2;
cout << "Enter first word: ";
cin >> word1;
cout << "Enter second word: ";
cin >> word2;
if ( IsAnagram_1( word1, word2 ) )
cout << "\nAnagram" << endl;
else
cout << "\nNot Anagram" << endl;
if ( IsAnagram_2( word1, word2 ) )
cout << "\nAnagram" << endl;
else
cout << "\nNot Anagram" << endl;
if ( IsAnagram_3( word1, word2 ) )
cout << "\nAnagram" << endl;
else
cout << "\nNot Anagram" << endl;
system("pause");
return 0;
}
In this approach I took care of empty strings and repeated characters as well. Enjoy it and comment any limitation.
#include <iostream>
#include <map>
#include <string>
using namespace std;
bool is_anagram( const string a, const string b ){
std::map<char, int> m;
int count = 0;
for (int i = 0; i < a.length(); i++) {
map<char, int>::iterator it = m.find(a[i]);
if (it == m.end()) {
m.insert(m.begin(), pair<char, int>(a[i], 1));
} else {
m[a[i]]++;
}
}
for (int i = 0; i < b.length(); i++) {
map<char, int>::iterator it = m.find(b[i]);
if (it == m.end()) {
m.insert(m.begin(), pair<char, int>(b[i], 1));
} else {
m[b[i]]--;
}
}
if (a.length() <= b.length()) {
for (int i = 0; i < a.length(); i++) {
if (m[a[i]] >= 0) {
count++;
} else
return false;
}
if (count == a.length() && a.length() > 0)
return true;
else
return false;
} else {
for (int i = 0; i < b.length(); i++) {
if (m[b[i]] >= 0) {
count++;
} else {
return false;
}
}
if (count == b.length() && b.length() > 0)
return true;
else
return false;
}
return true;
}
Check if the two strings have identical counts for each unique char.
bool is_Anagram_String(char* str1,char* str2){
int first_len=(int)strlen(str1);
int sec_len=(int)strlen(str2);
if (first_len!=sec_len)
return false;
int letters[256] = {0};
int num_unique_chars = 0;
int num_completed_t = 0;
for(int i=0;i<first_len;++i){
int char_letter=(int)str1[i];
if(letters[char_letter]==0)
++num_unique_chars;
++letters[char_letter];
}
for (int i = 0; i < sec_len; ++i) {
int c = (int) str2[i];
if (letters[c] == 0) { // Found more of char c in t than in s.
return false;
}
--letters[c];
if (letters[c] == 0) {
++num_completed_t;
if (num_completed_t == num_unique_chars) {
// it’s a match if t has been processed completely
return i == sec_len - 1;
}
}
}
return false;}
#include <iostream>
#include <string.h>
using namespace std;
const int MAX = 100;
char cadA[MAX];
char cadB[MAX];
bool chrLocate;
int i,m,n,j, contaChr;
void buscaChr(char [], char []);
int main() {
cout << "Ingresa CadA: ";
cin.getline(cadA, sizeof(cadA));
cout << "Ingresa CadB: ";
cin.getline(cadB, sizeof(cadA));
if ( strlen(cadA) == strlen(cadB) ) {
buscaChr(cadA,cadB);
} else {
cout << "No son Anagramas..." << endl;
}
return 0;
}
void buscaChr(char a[], char b[]) {
j = 0;
contaChr = 0;
for ( i = 0; ( (i < strlen(a)) && contaChr < 2 ); i++ ) {
for ( m = 0; m < strlen(b); m++ ) {
if ( a[i] == b[m]) {
j++;
contaChr++;
a[i] = '-';
b[m] = '+';
} else { contaChr = 0; }
}
}
if ( j == strlen(a)) {
cout << "SI son Anagramas..." << endl;
} else {
cout << "No son Anagramas..." << endl;
}
}
Your algorithm is incorrect. You're checking each character in the first word to see how many times that character appears in the second word. If the two words were 'aaaa', and 'aaaa', then that would give you a count of 16. A small alteration to your code would allow it to work, but give a complexity of N^2 as you have a double loop.
for(i=0;i<n1;i++)
for(j=0;j<n2;j++)
if(str1[i]==str2[j])
++c, str2[j] = 0; // 'cross off' letters as they are found.
I done some tests with anagram comparisons. Comparing two strings of 72 characters each (the strings are always true anagrams to get maximum number of comparisons), performing 256 same-tests with a few different STL containers...
template<typename STORAGE>
bool isAnagram(const string& s1, const string& s2, STORAGE& asciiCount)
{
for(auto& v : s1)
{
asciiCount[v]++;
}
for(auto& v : s2)
{
if(--asciiCount[static_cast<unsigned char>(v)] == -1)
{
return false;
}
}
return true;
}
Where STORAGE asciiCount =
map<char, int> storage; // 738us
unordered_map<char, int> storage; // 260us
vector<int> storage(256); // 43us
// g++ -std=c++17 -O3 -Wall -pedantic
This is the fastest I can get.
These are crude tests using coliru online compiler + and std::chrono::steady_clock::time_point for measurements, however they give a general idea of performance gains.
vector has the same performance, uses only 256 bytes, although strings are limited to 255 characters in length (also change to: --asciiCount[static_cast(v)] == 255 for unsigned char counting).
Assuming vector is the fastest. An improvement would be to just allocate a C style array unsigned char asciiCount[256]; on the stack (since STL containers allocate their memory dynamically on the heap)
You could probably reduce this storage to 128 bytes, 64 or even 32 bytes (ascii chars are typically in range 0..127, while A-Z+a-z 64.127, and just upper or lower case 64..95 or 96...127) although not sure what gains would be found from fitting this inside a cache line or half.
Any better ways to do this? For Speed, Memory, Code Elegance?
1. Simple and fast way with deleting matched characters
bool checkAnagram(string s1, string s2) {
for (char i : s1) {
unsigned int pos = s2.find(i,0);
if (pos != string::npos) {
s2.erase(pos,1);
} else {
return false;
}
}
return s2.empty();
}
2. Conversion to prime numbers. Beautiful but very expensive, requires special Big Integer type for long strings.
// https://en.wikipedia.org/wiki/List_of_prime_numbers
int primes[255] = {2, 3, 5, 7, 11, 13, 17, 19, ... , 1613};
bool checkAnagramPrimes(string s1, string s2) {
long c1 = 1;
for (char i : s1) {
c1 = c1 * primes[i];
}
long c2 = 1;
for (char i : s2) {
c2 = c2 * primes[i];
if (c2 > c1) {
return false;
}
}
return c1 == c2;
}
string key="listen";
string key1="silent";
string temp=key1;
int len=0;
//assuming both strings are of equal length
for (int i=0;i<key.length();i++){
for (int j=0;j<key.length();j++){
if(key[i]==temp[j]){
len++;
temp[j] = ' ';//to deal with the duplicates
break;
}
}
}
cout << (len==key.length()); //if true: means the words are anagrams
Instead of using dot h header which is deprecated in modern c++.
Try this solution.
#include <iostream>
#include <string>
#include <map>
int main(){
std::string word_1 {};
std::cout << "Enter first word: ";
std::cin >> word_1;
std::string word_2 {};
std::cout << "Enter second word: ";
std::cin >> word_2;
if(word_1.length() == word_2.length()){
std::map<char, int> word_1_map{};
std::map<char, int> word_2_map{};
for(auto& c: word_1)
word_1_map[std::tolower(c)]++;
for(auto& c: word_2)
word_2_map[std::tolower(c)]++;
if(word_1_map == word_2_map){
std::cout << "Anagrams" << std::endl;
}
else{
std::cout << "Not Anagrams" << std::endl;
}
}else{
std::cout << "Length Mismatch" << std::endl;
}
}
#include <bits/stdc++.h>
using namespace std;
#define NO_OF_CHARS 256
int main()
{ bool ans = true;
string word1 = "rest";
string word2 = "tesr";
unordered_map<char,int>maps;
for(int i = 0 ; i <5 ; i++)
{
maps[word1[i]] +=1;
}
for(int i = 0 ; i <5 ; i++)
{
maps[word2[i]]-=1 ;
}
for(auto i : maps)
{
if(i.second!=0)
{
ans = false;
}
}
cout<<ans;
}
Well if you don't want to sort than this code will give you perfect output.
#include <iostream>
using namespace std;
int main(){
string a="gf da";
string b="da gf";
int al,bl;
int counter =0;
al =a.length();
bl =b.length();
for(int i=0 ;i<al;i++){
for(int j=0;j<bl;j++){
if(a[i]==b[j]){
if(j!=bl){
b[j]=b[b.length()-counter-1];
bl--;
counter++;
break;
}else{
bl--;
counter++;
}
}
}
}
if(counter==al){
cout<<"true";
}
else{
cout<<"false";
}
return 0;
}
Here is the simplest and fastest way to check for anagrams
bool anagram(string a, string b) {
int a_sum = 0, b_sum = 0, i = 0;
while (a[i] != '\0') {
a_sum += (int)a[i]; // (int) cast not necessary
b_sum += (int)b[i];
i++;
}
return a_sum == b_sum;
}
Simply adds the ASCII values and checks if the sums are equal.
For example:
string a = "nap" and string b = "pan"
a_sum = 110 + 97 + 112 = 319
b_sum = 112 + 97 + 110 = 319
I created a program in C++ that remove commas (,) from a given integer. i.e. 2,00,00 would return 20000. I am not using any new space. Here is the program I created:
void removeCommas(string& str1, int len)
{
int j = 0;
for (int i = 0; i < len; i++)
{
if (str1[i] == ',')
{
continue;
}
else
{
str1[j] = str1[i];
j++;
}
}
str1[j] = '\0';
}
void main()
{
string str1;
getline(cin, str1);
int i = str1.length();
removeCommas(str1, i);
cout << "the new string " << str1 << endl;
}
Here is the result I get:
Input : 2,000,00
String length =8
Output = 200000 0
Length = 8
My question is that why does it show the length has 8 in output and shows the rest of string when I did put a null character. It should show output as 200000 and length has 6.
Let the standard library do the work for you:
#include <algorithm>
str1.erase(std::remove(str1.begin(), str1.end(), ','), str1.end());
If you don't want to modify the original string, that's easy too:
std::string str2(str1.size(), '0');
str2.erase(std::remove_copy(str1.begin(), str1.end(), str2.begin(), ','), str2.end());
You need to do a resize instead at the end.
Contrary to popular belief an std::string CAN contain binary data including 0s. An std::string 's .size() is not related to the string containing a NULL termination.
std::string s("\0\0", 2);
assert(s.size() == 2);
The answer is probably that std::strings aren't NUL-terminated. Instead of setting the end+1'th character to '\0', you should use str.resize(new_length);.
Edit: Also consider that, if your source string has no commas in it, then your '\0' will be written one past the end of the string (which will probably just happen to work, but is incorrect).
The std::srting does not terminate with \0, you are mixing this with char* in C. So you should use resize.
The solution has already been posted by Fred L.
In a "procedural fashion" (without "algorithm")
your program would look like:
void removeStuff(string& str, char character)
{
size_t pos;
while( (pos=str.find(character)) != string::npos )
str.erase(pos, 1);
}
void main()
{
string str1;
getline(cin, str1);
removeStuff(str1, ',');
cout<<"the new string "<<str1<<endl;
}
then.
Regards
rbo
EDIT / Addendum:
In order to adress some efficiency concerns of readers,
I tried to come up with the fastest solution possible.
Of course, this should kick in on string sizes over
about 10^5 characters with some characters to-be-removed
included:
void fastRemoveStuff(string& str, char character)
{
size_t len = str.length();
char *t, *buffer = new char[len];
const char *p, *q;
t = buffer, p = q = str.data();
while( p=(const char*)memchr(q, character, len-(p-q)) ) {
memcpy(t, q, p-q);
t += p-q, q = p+1;
}
if( q-str.data() != len ) {
size_t tail = len - (q-str.data());
memcpy(t, q, tail);
t += tail;
}
str.assign(buffer, t-buffer);
delete [] buffer;
}
void main()
{
string str1 = "56,4,44,55,5,55"; // should be large, 10^6 is good
// getline(cin, str1);
cout<<"the old string " << str1 << endl;
fastRemoveStuff(str1, ',');
cout<<"the new string " << str1 << endl;
}
My own procedural version:
#include <string>
#include <cassert>
using namespace std;
string Remove( const string & s, char c ) {
string r;
r.reserve( s.size() );
for ( unsigned int i = 0; i < s.size(); i++ ) {
if ( s[i] != c ) {
r += s[i];
}
}
return r;
}
int main() {
assert( Remove( "Foo,Bar,Zod", ',' ) == "FooBarZod" );
}
Here is the program:
void main()
{
int i ;
char n[20] ;
clrscr() ;
printf("Enter a number. ") ;
gets(n) ;
printf("Number without comma is:") ;
for(i=0 ; n[i]!='\0' ; i++)
if(n[i] != ',')
putchar(n[i]) ;
getch();
}
For detailed description you can refer this blog: http://tutorialsschool.com/c-programming/c-programs/remove-comma-from-string.php
The same has been discussed in this post: How to remove commas from a string in C
Well, if youre planing to read from a file using c++. I found a method, while I dont think thats the best method though, but after I came to these forums to search for help before, I think its time to contribute with my effort aswell.
Look, here is the catch, what I'm going to present you is part of the source code of the map editor Im building on right now, that map editor obviously has the purpose to create maps for a 2D RPG game, the same style as the classic Pokemon games for example. But this code was more towards the development of the world map editor.
`int strStartPos = 0;
int strSize = 0;
int arrayPointInfoDepth = 0;
for (int x = 0; x < (m_wMapWidth / (TileSize / 2)); x++) {
for (int y = 0; y < (m_wMapHeight / (TileSize / 2)); y++) {
if (ss >> str) {
for (int strIterator = 0; strIterator < str.length(); strIterator++) {
if (str[strIterator] == ',') {`
Here we need to define the size of the string we want to extract after the previous comma and before the next comma
`strSize = strIterator - strStartPos;`
And here, we do the actual transformation, we give to the vector that is a 3D vector btw the string we want to extract at that moment
`m_wMapPointInfo[x][y][arrayPointInfoDepth] = str.substr(strStartPos, strSize);`
And here, we just define that starting position for the next small piece of the string we want to extract, so the +1 means that after the comma we just passed
strStartPos = strIterator + 1;
Here, well since my vector has only 6 postions that is defined by WorldMapPointInfos we need to increment the third dimension of the array and finally do a check point where if the info has arrived the number 6 then break the loop
arrayPointInfoDepth++;
if (arrayPointInfoDepth == WorldMapPointInfos) {
strStartPos = 0;
arrayPointInfoDepth = 0;
break;
}
}
}
}
}
}
Either way on my code, think abt that the vector is just a string, thats all you need to know, hope this helps though :/
Full view:
int strStartPos = 0;
int strSize = 0;
int arrayPointInfoDepth = 0;
for (int x = 0; x < (m_wMapWidth / (TileSize / 2)); x++) {
for (int y = 0; y < (m_wMapHeight / (TileSize / 2)); y++) {
if (ss >> str) {
for (int strIterator = 0; strIterator < str.length(); strIterator++) {
if (str[strIterator] == ',') {
strSize = strIterator - strStartPos;
m_wMapPointInfo[x][y][arrayPointInfoDepth] = str.substr(strStartPos, strSize);
strStartPos = strIterator + 1;
arrayPointInfoDepth++;
if (arrayPointInfoDepth == WorldMapPointInfos) {
strStartPos = 0;
arrayPointInfoDepth = 0;
break;
}
}
}
}
}
}