Reading series of chars without arrays or strings - c++

i am struggling with one problem in my program. For input I am given ID that is series of 3 upper case letters, like ABC.
The problem is I have to read them somehow without using any other header file than <iostream> and I cannot use string nor any array types, such as char[] or string[]. How can I read series of multiple letters? Can I split them somehow into three chars?
The ID is needed later for implementation of the list - the three letters is an ID of a specific list and there will be also other lists, and the program basically will have to perform some operations on them such as adding elements, merging etc.
Thanks you for your help!

Strange requirements but just read them one at a time into separate variables.
char a = cin.get();
char b = cin.get();
char c = cin.get();
get reads a single character.

U can use scanf() or printf() methods.

Related

Write a function that crosses out up to n-1 signs of a n-letter word, and returns the amount of unique strings created that way

Let's say we have the string* abcd, which I will refer to as "word". The program should return the amount of unique strings* that are made by crossing out zero or more letters from "abcd". In this particular example, these unique strings* are "abcd", "abc", "abd", "acd", "bcd", "ab", "ac", "ad", "bc", "bd", "cd", "a", "b", "c", "d". Therefore, in this case, the program should return 15. Using vectors and strings in this assignment is forbidden, so I will have to use char[] arrays instead. The use of the word string* above is to avoid complicating the already complicated task. By string I mean char[].
So far my idea is to create arrays that store the strings with the same length. The number of such strings I find using the binomial formula. (For example the number of 3-letter strings from a 4-letter word is C(3,4). So in a for-loop I create the required arrays to accomodate the strings and add only those strings that aren't already in that array. Then I return the number of elements in the array.
//size is the size of the word, i is the number of crossed out letters
int total=0; //stores number of all possible little strings
for(int i=1; i<size; i++){
int sizeOfSubstring=binomial(size-i, size);
char substrings[sizeOfSubstring][size-i];
//populate the substrings array and return the number of char[] arrays added to it.
//Then add that number to total.
}
However, as you can clearly see, this problem is already complicated. I bypass the C++ requirement for constant array sizes by using GCC. But it gets even worse, when you have to populate the array of strings. For example, we need to add "abc", "abd", "acd", "bcd" to substrings[4][3]. And then the same procedure for substrings[6][2] etc. This will require a function like
void addSubstring(char crossedOutIndexes[], char word[], char substr[][]){
//I haven't implemented that yet
}
I am asking this question because I already have great difficulties with this problem and I don't know how to implement the addSubstring() function. Is this even the right idea to solve the problem?
I recommend first solving the problem without the complicated cases. For instance, assume your input will never have repeated letters. Then solve it manually on paper for a string of 2 characters, then 3, then 4, until you see a pattern develop as to an algorithm you manually use when doing it by hand. Then code that, and get it working. Once that's working. Solve the next problem, duplicates. Well there's a couple options there. Don't add a word if it's already in your list or remove all duplicates from the list.
As to variable length arrays, your initial solution of using a compiler that supports variable length arrays is fine for the first version. Another possibility is simply over allocating an array of strings. For instance an array of 10000 filled with empty strings. While memory inefficient, it's fine for learning. Once you have a working solution you can always move to a standard container like std::vector.
One thing that happens here is that learners often get great advice. But they're still learning so the advice just overwhelms them. There's nothing wrong with using a compiler that supports variable length arrays, it just locks you in to that tool.
I do recommend finding a development environment with a great debugger. One that will let you step through the code line by line and see what's happening. Visual Studio Community is the free one, that I'm familiar with. But I know there are others. I just don't know what they are.

C++ string copy() gives me extra characters at the end, why is that?

I am studying c++, In a blog they introduced the concept of copy function. When I tried the same in my system, the result is not matching to what I expected. Please let me know what I did wrong here in the below code.
#include <iostream>
main(){
std::string statement = "I like to work in Google";
char compName[6];
statement.copy(compName, 6, 18);
std::cout<<compName;
}
I expected Google but actual output is Googlex
I am using windows - (MinGW.org GCC-6.3.0-1)
You are confusing a sequence of characters, C style string, and std::string. Let's break them down:
A sequence of characters is just that, one character after another in some container (in your case a C style array). To a human being several characters may look like a string, but there is nothing in your code to make it such.
C style string is an array of characters terminated by a symbol \0. It is a carry over from C, as such a compiler will assume that if even if you don't tell it otherwise the array of characters may potentially be such a string.
C++ string (std::string) is a template class that stores strings. There is no need to worry how it does so internally. Although there are functions for interoperability with the first two categories, it is a completely different thing.
Now, let's figure out how a compiler sees your code:
char compName[6];
This creates an array of characters with enough space to store 6 symbols. You can write C style strings into it as long as they are 5 symbols or less, since you will need to also write '\0' at the end. Since in C++ C style arrays are unsafe, they will allow you to write more characters into them, but you cannot predict in advance where those extra characters will be written into memory (or even if your program will continue to execute). You can also potentially read more characters from the array... But you cannot even ask the question where that data will be coming from, unless you are simply playing around with your compiler. Never do that in your code.
statement.copy(compName, 6, 18);
This line writes 6 characters. It does not make it into a C style string, it is simply 6 characters in an array.
std::cout<<compName;
You are trying to output to the console a C style string... which you have not provided to a compiler. So a an operator<< receives a char [], and it assumes that you knew what you were doing and works as if you gave it C string. It displays one character after another until it reaches '\0'. When will it get such a character? I have no idea, since you never gave it one. But due to C style arrays being unsafe, it will have no problem trying to read characters past the end of an array, reading some memory blocks and thinking that they are a continuation of your non-existent C style sting.
Here you got "lucky" and you only got a single byte that appeared as an 'x', and then you got a byte with 0 written in it, and the output stopped. If you run your program at a different time, with a different compiler, or compiled with different optimisations you might get a completely different data displayed.
So what should you have done?
You can try this:
#include <iostream>
#include <string>
int main()
{
std::string statement = "I like to work in Google";
char compName[7]{};
statement.copy(compName, 6, 18);
std::cout<<compName;
return 0;
}
What did i change? I made an array able to hold 7 characters (leaving enough space for a C style string of 6 characters) and i have provided an empty initialisation list {}, which will fill the array with \0 characters. This means that when you will replace the first 6 of them with your data, there will be a terminating character in the very end.
Another approach would be to do this:
#include <iostream>
#include <string>
int main()
{
std::string statement = "I like to work in Google";
char compName[7];
auto length = statement.copy(compName, 6, 18);
compName[length] = '\0';
std::cout<<compName;
return 0;
}
Here i do not initialise the array, but i get the length of the data that is written there with a .copy method and then add the needed terminator in the correct position.
What approach is best depends on your particular application.
When inserting pointer to a character into the stream insertion operator, the pointer is required to point to null terminated string.
compName does not contain the null terminator character. Therefore inserting inserting (a pointer to an element of) it into a character stream violates the requirement above.
Please let me know what I did wrong here
You violate the requirement above. As a consequence, the behaviour of your program is undefined.
I expected Google but actual output is Googlex
This is because the behaviour of the program is undefined.
How to terminate it?
Firstly, make sure that there is room in the array for the null terminator character:
char compName[7];
Then, assign the null terminator character:
compName[6] = '\0';

Is it possible to initialize characters to a number, n, based on how many characters the user inputs?

I had a homework question where I had to ask the user for a character and use that character to create the image of the letter C. It sparked an interest and I wanted to try and make a program that asks the user for a letter, word, or sentence of their choice and have it create the letter, word, or sentence out of a character they choose. For exmaple if the user inputs "Hi" with the character X, the out put would be:
X X X
X X
XXXX X
X X X
X X X
This is probably beyond my league because I'm a newbie to c++ and coding in general, however I enjoy messing around with code so its something I wanted to try.
My idea is to make a switch statement that loops through every letter and replaces each letter with the corresponding letter output. However I can't figure out how I would initialize the infinite amount of possible characters the user inputs.
Is there a way to make the input a string and then translate the string into individual char types? From then I can just loop through each character and use the switch statement to switch it out. Also is there a way to count how many characters there are so I can use that to make the loop? For example in python I could just use len("string") and it would give an integer value. Is there anything like that in C++?
I know there is probably a lot simpler and cleaner ways to go about this project, but I'm very limited to the little knowledge I know right now.
Any input would be awesome, thanks.
Is there a way to make the input a string
Yes, and it sounds like you already know how to do this part.
and then translate the string into individual char types?
Yes, if str is a variable holding the string, and i is the index of the character you want to get, then str[i] is that character. (Remember the first character is at index 0)
Also is there a way to count how many characters there are so I can use that to make the loop?
Yes, if str is a variable holding the string, then use str.length() (assuming it's a string rather than a C-style array of characters).
For example in python I could just use len("string") and it would give an integer value. Is there anything like that in C++?
See above.

Fast way to get two first and last characters of a string from the input

I need to read a string from the input
a string has its length from 2 letters up to 1000 letters
I only need 2 first letters, 2 last letters, and the size of the entire string
Here is my way of doing it, HOWEVER, I do believe there is a smarter way, which is why I am asking this question. Could you please tell me, unexperienced and new C++ programmer, what are possible ways of doing this task better?
Thank you.
string word;
getline(cin, word);
// results - I need only those 5 numbers:
int l = word.length();
int c1 = word[0];
int c2 = word[1];
int c3 = word[l-2];
int c4 = word[l-1];
Why do I need this? I want to encode a huge number of really long strings, but I figured out I really need only those 5 values I mentioned, the rest is redundant. How many words will be loaded? Enough to make this part of code worth working on :)
I will take you at your word that this is something that is worth optimizing to an extreme. The method you've shown in the question is already the most straight-forward way to do it.
I'd start by using memory mapping to map chunks of the file into memory at a time. Then, loop through the buffer looking for newline characters. Take the first two characters after the previous newline and the last two characters before the one you just found. Subtract the address of the second newline from the first to get the length of the line. Rinse, lather, and repeat.
Obviously some care will need to be taken around boundaries, where one newline is in the previous mapped buffer and one is in the next.
The first two letters are easy to obtain and fast.
The issue is with the last two letters.
In order to read a text line, the input must be scanned until it finds an end-of-line character (usually a newline). Since your text lines are variable, there is no fast solution here.
You can mitigate the issue by reading in blocks of data from the file into memory and searching memory for the line endings. This avoids a call to getline, and it avoids a double search for the end of line (once by getline and the other by your program).
If you change the input to be fixed with, this issue can be sped up.
If you want to optimize this (although I can't imagine why you would want to do that, but surely you have your reasons), the first thing to do is to get rid of std::string and read the input directly. That will spare you one copy of the whole string.
If your input is stdin, you will be slowed down by the buffering too. As it has already been said, the best speed woukd be achieved by reading big chunks from a file in binary mode and doing the end of line detection yourself.
At any rate, you will be limited by the I/O bandwidth (disk access speed) in the end.

Properties of a string class in C++

I am working through C++ program design by Cohoon and Davidson. This is what it says about string class attributes (3rd Edition, Page 123):
Characters that comprise the string
The number of characters in the string
My question is: If we know the characters in the string, does not it implies we already know about number of characters in the string? What is the need to explicitly specify the second attribute?
You are right but length is required in many places like counting, or knowing the length/end of malloc memory so it is better to store length as additional property to make your program run fast.
Consider what will happen if the program needs to count the chars all the way just to tell you how many are there in it. Moreover when this feature is accessed frequently.
So it simply saves time storing length too.
So all actual implementations of string classes do store length of the string.
If we know the characters in the string, does not it implies we already know about number of characters in the string?
Well in C we know the number of elements because we can count up to the NULL terminal. But think how expensive it is to get the length of a string? It takes walking the entire string. For such a common operation, why wouldn't we want this to be a constant-time operation?