Important note: string (C++ object) and any other library such as array or vectors that could store unlimited characters cannot be used.
For my question:
We are given input 1, which is a sentence of unlimited characters. eg. Life is Beautiful.
Input 2: character who's location we have to find using the reference point (the middle character in input 1 after it is sorted and repeating characters are deleted) taken as zero. eg. fee.
An example:
Input 1: Life is beautiful
Input 2: see
Output: 2, -2, -2
Explanation: So firstly, we remove any spaces from input 1 and make all lowercase, then sort it in ascending order after which we find the reference letter (For above example, it's 'i'). We remove the repeating characters and then finally, put positions to character in input 1.
Example 2
Input 1: abcde
Input 2: aad
Output: -2, -2, 1
If the input 2 contains reference point, then the code returns zero.
Eg.
An example:
Input 1: abcde
Input 2: cab
Output: 0
The input1 is always odd and input2 is always 10 character max.
The problem I have is that I am not sure how to store these inputs without using strings, array etc. And even if I know how to store them, I cannot compare the inputs like input1[1] = input2[1] because we cannot use arrays/strings.
Is list an useful option with regards to important note?
I have mostly done it with the use of array but not sure how to approach it without the array. I tried to loop a character but it only stores the first character.
My practice code:
#include <iostream>
using namespace std;
int main() {
char input1;
for(int i =0; i < 3; i++ ) //for chacking whether the loops work or not.
{
cin >> input1;
}
cout<< input1;
char input2;
}
Please add any relevant tags.
I hope all the edits help.
KushanMehta proposed a C-ish solution. A more C++ one would be to implement a class wrapping a dynamic array of elements. In C++ it could be:
template <class T>
class MyArr {
protected:
T *arr; // a pointer to the dynamic array
size_t len; // the used length
size_t capacity; // the allocated capacity
...
As it contains a pointer to dynamic array, you cannot rely on default members, and should implement copy and move constructor and assignation operator and a destructor.
In order to be able to use all the goodies of C++ algorithm library, you should declare [c]begin() and [c]end() functions pointing to beginning of array and one past last element.
const T* cbegin() const {
return arr;
}
const T* cend() const {
return arr + len;
}
Then you need a subclass for characters implementing some methods to convert all characters to lower case and remove spaces, sort the array and remove duplicates. You should write io specializations for operator << and >> to be able to input strings from stdin and output them
The MyArr class can be used directly to store the resul value: just derive a specialization for int elements and implement the required specifications.
That may not be really easy, but you will learn C++ that way (not C)
You could do one thing to store the sentences by the use of dynamic memory for each character (sounds absurd but it is the only possible thing without actually worrying about the size of the input)
Meaning you take input till the user wants, in the meanwhile you can use malloc and realloc() for each new character, incrementing the size of your pointer to char for every new character.
(This is probably the way vector etc works on the naive level - not sure of this though)
Code snippet for the same:
#include <iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
int main() {
char temp;
char *sentence = (char*) malloc(2*sizeof(char));
int counter = 0;
while( cin>>temp ){
sentence[counter++] = temp;
sentence = (char*) realloc(sentence, (counter+2)*sizeof(char));
}
sentence[counter] = '\0';
cout<<"The sentence is"<<endl<<strlen(sentence)<<endl<<sentence;
}
Related
I'm learning about vectors in c++. On printing address of two adjacent vector<string> elements I'm getting result which is confusing me a little bit.
Program
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<string> word;
//Enter any two words
string ch;
for(int i=1;i<3;i++)
{
getline(cin,ch);
word.push_back(ch);
}
//Display the words
for(auto i:word)
{
cout<<i<<" ";
}
cout<<endl;
//Display address of first two elements
cout<<word.data()<<" "<<(word.data()+1)<<endl;
return 0;
}
INPUT Data: hello
world
OUTPUT : hello world
0x1b9f060 0x1b9f080
What I'm not getting is that there are only 10 character in total(5 in first input and another five in second)and each character take 1 byte space.So why there is gap of 20 bytes between both vector elements?
I checked with vector<int> but the gap was only of four bytes.
First of all, the actual "gap" is 32 bytes since the addresses are hexadecimal values 0x1b9f080 - 0x1b9f060 = 0x20 = 32.
This is the size of the element of the vector which in this case is std::string. Most importantly std::string is a class and its size is roughly determined by the sizes of its members just like any other class.
What are the actual members of std::string and what size does it have as the result is dependent on the implementation of the standard library you are currently using. The most important thing, however, is that the size of std::string doesn't depend at all on the length of the actual string it's storing because it only holds a pointer to it and the string itself is located elsewhere (on the heap).
A string is not an array of characters, it's a pointer to an allocated space (of given size) that contains what you think is the string. There is usually also additional information like the actual size of the string (because C++ strings can have a \0 character in them), the allocated space perhaps...
There are exceptions, like Small Array Optimizations, but let's say it's not your actual string for the sake of clarity.
The int in your vector<int> has a size of 4, that's what we expect indeed.
I wrote a piece of code to count how many 'e' characters are in a bunch of words.
For example, if I type "I read the news", the counter for how many e's are present should be 3.
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char s[255],n,i,nr=0;
cin.getline(s,255);
for(i=1; i<=strlen(s); i++)
{
if(s[i-1]=='e') nr++;
}
cout<<nr;
return 0;
}
I have 2 unclear things about characters in C++:
In the code above, if I replace strlen(s) with 255, my code just doesn't work. I can only type a word and the program stops. I have been taught at school that strlen(s) is the length for the string s, which in this case, as I declared it, is 255. So, why can't I just type 255, instead of strlen(s)?
If I run the program above normally, it doesn't show me a number, like it is supposed to do. It shows me a character (I believe it is from the ASCII table, but I'm not sure), like a heart or a diamond. It is supposed to print the number of e's from the words.
Can anybody please explain these to me?
strlen(s) gives you the length of the string held in the s variable, up to the first NULL character. So if you input "hello", the length will be 5, even though s has a capacity of 255....
nr is displayed as a character because it's declared as a char. Either declare it as int, for example, or cast it to int when cout'ing, and you'll see a number.
strlen() counts the actual length of strings - the number of real characters up to the first \0 character (marking end of string).
So, if you input "Hello":
sizeof(s) == 255
strlen(s) == 5
For second question, you declare your nr as char type. std::cout recognizes char as a single letter and tries it print it as such. Declare your variable as int type or cast it before printing to avoid this.
int nr = 42;
std::cout << nr;
//or
char charNr = 42;
std::cout << static_cast<int>(charNr);
Additional mistakes not mentioned by others, and notes:
You should always check whether the stream operation was successful before trying to use the result.
i is declared as char and cannot hold values greater than 127 on common platforms. In general, the maximum value for char can be obtained as either CHAR_MAX or std::numeric_limits<char>::max(). So, on common platforms, i <= 255 will always be true because 255 is greater than CHAR_MAX. Incrementing i once it has reached CHAR_MAX, however, is undefined behavior and should never be done. I recommend declaring i at least as int (which is guaranteed to have sufficient range for this particular use case). If you want to be on the safe side, use something like std::ptrdiff_t (add #include <cstddef> at the start of your program), which is guaranteed to be large enough to hold any valid array size.
n is declared but never used. This by itself is harmless but may indicate a design issue. It can also lead to mistakes such as trying to use n instead of nr.
You probably want to output a newline ('\n') at the end, as your program's output may look odd otherwise.
Also note that calling a potentially expensive function such as strlen repeatedly (as in the loop condition) can have negative performance implications (strlen is typically an intrinsic function, though, and the compiler may be able to optimize most calls away).
You do not need strlen anyway, and can use cin.gcount() instead.
Nothing wrong with return 0; except that it is redundant – this is a special case that only applies to the main function.
Here's an improved version of your program, without trying to change your code style overly much:
#include <iostream>
#include <cstring>
#include <cstddef>
using namespace std;
int main()
{
char s[255];
int nr=0;
if ( cin.getline(s,255) )
{ // only if reading was successful
for(int i=0; i<cin.gcount(); i++)
{
if(s[i]=='e') nr++;
}
cout<<nr<<'\n';
}
return 0;
}
For exposition, the following is a more concise and expressive version using std::string (for arbitrary length input), and a standard algorithm. (As an interviewer, I would set this, modulo minor stylistic differences, as the canonical answer i.e. worth full credit.)
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
if ( getline(cin, s) )
{
cout << std::count(begin(s), end(s), 'e') << '\n';
}
}
I have 2 unclear things about characters in C++: 1) In the code above,
if I replace the "strlen(s)" with 255, my code just doesn't work, I
can only type a word and the program stops, and I have been taught at
school that "strlen(s)" is the length for the string s, wich in this
case, as I declared it, is 255. So, why can't I just type 255, instead
of strlen(s);
That's right, but strings only go the null terminator, even if there's more space allocated. Consider this, per example:
char buf[32];
strcpy(buf, "Hello World!");
There's 32 chars worth of space, but my string is only 12 characters long. That's why strlen returns 12 in this example. It's because it doesn't know how long the buffer is, it only knows the address of the string and parses it until it finds the null terminator.
So if you enter 255, you're going past what was set by cin and you'll read the rest of the buffer. Which, in this case, is uninitialized. That's undefined behavior - in this case it will most likely read some rubbish values, and those might coincidentally have the 'e' value and thus give you a wrong result.
2) If you run the program above normaly, it doesn't show you a number,
like it's supposed to do, it shows me a character(I believe it's from
the ASCII table but I'm not sure), like a heart or a diamond, but it
is supposed to print the number of e's from the words. So can anybody
please explain these to me?
You declared nr as char. While that can indeed hold an integer value, if you print it like this, it will be printed as a character. Declare it as int instead or cast it when you print it.
I am new to C++, but very familiar with Python. Trivial tasks in Python seem to be much more complex in C++. I am attempting to make a simple game where a word in a foreign language is printed on screen, the user guesses the value, if correct they are awarded a point and continue guessing what the value of other numbers printed on screen are. The problem I am facing that for the course I am taking we are not allowed to use strings only character arrays. The reason for this has not been explained by the instructor.
In Python, I would create a tuple of strings for the foreign word numbers:
foreignWords = ('een', 'twee', 'drie'....)
index 0 would be the word for one in Dutch, index 1 would be the word for two in Dutch, etc. I would use a function to randomly select a number between 0 and the length of foreignWords, print it on screen, etc. Very simple to do.
I thought I could simply create a structure array and strcopy the char arrays into the struct array.
struct numbers
{
char numberWord[7];
};
int main()
{
numbers numberChoices[10];
strcpy(numberChoices[0].numberWord, 'een');
strcpy(numberChoices[1].numberWord, 'twee');
strcpy(numberChoices[2].numberWord, 'drie');
strcpy(numberChoices[3].numberWord, 'vier');
strcpy(numberChoices[4].numberWord, 'vijf'):
strcpy(numberChoices[5].numberWord, 'zes');
etc.
That doesn't work though. It produces an error:
string.h:129:14: error: initializing argument 2 of ‘char* strcpy(char*, const char*)’ [-fpermissive]
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
^
However, if I create a for-loop and input the char array via cin >> the structure array will store my entries and they can be called by index.
Essentially, what I would like to do is make an array of char arrays that way I can an index get the value back and trivially keep track of the numerical value of the word (numberChoices[i].numberWord, i+1 = numerical value of the printed word). I don't know if this appropriate approach or not, but I am trying to be efficient, because the structure array would be referenced quite a bit to read what is stored in memory, save that value to a new variable and manipulate the referenced char array by deleting characters randomly and having the user guess what value the printed words.
What is the correct way to go about making an array of char arrays where the char array elements are hard coded?
Your code syntax is worng. You must represent char arrays as "abc", but not like 'abc'.
So your code must be like:
numbers numberChoices[10];
strcpy(numberChoices[0].numberWord, "een");
strcpy(numberChoices[1].numberWord, "twee");
strcpy(numberChoices[2].numberWord, "drie");
strcpy(numberChoices[3].numberWord, "vier");
strcpy(numberChoices[4].numberWord, "vijf"):
strcpy(numberChoices[5].numberWord, "zes");
Secondly you must remember that char arrays like "een" have extra char called null terminate '\0' so you must define array with enough size to store your characters and that extra character. That concept is called 'null terminating string'.
'\0' character is required to properly define your string size in functions like strcpy, strlen e. t. c. because you can not know about array size only by pointer to its first element (all array literals are considered like pointers in C/C++).
In C++ there is a distinction between single and double quotes: single quotes denote a single character literal, e.g. 'a', '0', '\n' while double quotes are used for c-strings, e.g. "a.u.b".
So replace
strcpy(numberChoices[0].numberWord, 'een');
with
strcpy(numberChoices[0].numberWord, "een");
In addition to the quote mix-up pointed out by others, you can take advantage static initialization to make some of that work go away.
struct numbers
{
char numberWord[7];
};
numbers numberChoices[10] =
{
{"een"},
{"twee"},
{"drie"},
{"vier"},
{"vijf"},
{"zes"},
...
};
int main()
{
std::cout << numberChoices[1].numberWord << std::endl;
}
And if possible within the constraints of your assignment, a further simplification:
const char * numberChoices[] =
{
"een",
"twee",
"drie",
"vier",
"vijf",
"zes",
...
};
int main()
{
std::cout << numberChoices[1] << std::endl;
}
It would seem that std::string is off the table for you. Pity. Use it where possible. It will save you a lot of trouble.
avoid c-style strings. use the c++ concepts:
#include <string>
#include <array>
struct numbers
{
std::string numberWord;
};
int main()
{
numbers numberChoices[] = {
{ "een" },
{ "twee" },
{ "drie" },
{ "vier" },
{ "vijf" },
{ "zes" },
// ... etc
};
}
Let's ignore your course requirestments for a moment;
You shouldn't use any magic indexes! use map instead, with meaningful keys;
With a proper map and string usage your code could look similar to this example:
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
using foreign_word = std::string;
using foreign_words = std::vector<foreign_word>;
using language = std::string;
using language_words_map = std::unordered_map<language, foreign_words>;
int main() {
language_words_map lwm = {
{ "deutch", {"een", "twee", "drie"} },
/* ... and so on */
};
return 0;
}
see: http://ideone.com/BI6QjL
The following code seems to be running when it shouldn't. In this example:
#include <iostream>
using namespace std;
int main()
{
char data[1];
cout<<"Enter data: ";
cin>>data;
cout<<data[2]<<endl;
}
Entering a string with a length greater than 1 (e.g., "Hello"), will produce output as if the array were large enough to hold it (e.g., "l"). Should this not be throwing an error when it tried to store a value that was longer than the array or when it tried to retrieve a value with an index greater than the array length?
The following code seems to be running when it shouldn't.
It is not about "should" or "shouldn't". It is about "may" or "may not".
That is, your program may run, or it may not.
It is because your program invokes undefined behavior. Accessing an array element beyond the array-length invokes undefined behavior which means anything could happen.
The proper way to write your code is to use std::string as:
#include <iostream>
#include <string>
//using namespace std; DONT WRITE THIS HERE
int main()
{
std::string data;
std::cout<<"Enter data: ";
std::cin>>data; //read the entire input string, no matter how long it is!
std::cout<<data<<std::endl; //print the entire string
if ( data.size() > 2 ) //check if data has atleast 3 characters
{
std::cout << data[2] << std::endl; //print 3rd character
}
}
It can crash under different parameters in compilation or compiled on other machine, because running of that code giving undefined result according to documentaton.
It is not safe to be doing this. What it is doing is writing over the memory that happens to lie after the buffer. Afterwards, it is then reading it back out to you.
This is only working because your cin and cout operations don't say: This is a pointer to one char, I will only write one char. Instead it says: enough space is allocated for me to write to. The cin and cout operations keep reading data until they hit the null terminator \0.
To fix this, you can replace this with:
std::string data;
C++ will let you make big memory mistakes.
Some 'rules' that will save you most of the time:
1:Don't use char[]. Instead use string.
2:Don't use pointers to pass or return argument. Pass by reference, return by value.
3:Don't use arrays (e.g. int[]). Use vectors. You still have to check your own bounds.
With just those three you'll be writing some-what "safe" code and non-C-like code.
I have a task to implement "void makeAmbigram(char*)" that will print on screen ambigram of latin string or return something like 'ambigram not possible'. Guess it's just about checking if string contains only of SNOXZHI and printing string backwards. Or am I wrong ?
I'm a complete noob when dealing with cpp so that's what I've created :
#include <iostream>
using namespace std;
char[]words;
char[]reversed;
char[] ret_str(char* s)
{
if(*s != '\0')
ret_str(s+1);
return s;
}
void makeAmbigram(char* c)
{
/* finding chars XIHNOZS and printing ambigram */
}
int main()
{
cin>>words;
reversed = ret_str(words);
makeAmbigram(reversed);
return 0;
}
I can reverse string but how to check if my reversed string contains only needed chars ?
I've found some function but it's hard or even imposible to implement it for greater amount of chars : www.java2s.com/Code/C/String/Findcharacterinstringhowtousestrchr.htm
You need to allocate space in your arrays or use std::vector. The arrays word and reversed are just pointers and no space is allocated. The C++ language does not support dynamic arrays; however, the STL provides std::vector which dynamically allocates space as required.
Change:
char[]words;
char[]reversed;
To:
#define MAX_LETTERS 64
char words[MAX_LETTERS + 1]; // + 1 for terminating nul character ('\0')
char reversed[MAX_LETTERS + 1];
Or:
#include <string>
std::string words;
std::string reversed;
Or:
#include <vector>
std::vector<char> words;
std::vector<char> reversed;
As far as the ambigram rules go, you need to talk to your instructor. Also, if this is homework, add a tag indicating so.
Hint: The std::string data type has some reverse iterators which may be of use to you.
std::string has an entire family of member functions along the lines of find_first_of. You can pass in a string containing all the letters your ambigram test requires, and they'll find whether any of those letters are present in the source string.
The complete list of string functions is available here.
As for the definition of ambigrams, given the wiki page you've included in the question...you need to check if a letter is legible if viewed upside down, for eg. u/n, w/m, d/p, q/b and so on. There are of course more complex rules was well, for eg. 'ui' can resemble 'm' if viewed upside down.
However, if you're only required to check if your string contains only SNOXZHI, you can look into a regular expression (regex) for the same, and compare input string character-wise to your regex.