C++ take a letter from a file - c++

I'm working on a C++ file. And this is what I've got: The user has to type the name of a file, e.g. file1.txt, and I have to count the letters in that file.
All of this is working but: after "x" letters, I have to take the next letter and show it on the screen. I don't really know how to do this?
I think it has to be an if-statement and it has to start like this:
if (count_letters = x){
}
But I'm really lost after that.
Thanks !

It should be
if (count_letters >= x)
Note that the == operator compares two values, whilst = assigns a value to a variable. Then in your if body you'd probably just do something along the lines of
std::cout << letters[x] << std::endl;

Related

How can I preserve leading zeros when reading a number and printing it later?

I want to cout an integer starting 0. For example, 0123456789.
But when I print it out, it only display 123456789 instead of 0123456789.
How can I solve this problem?
Below is my sample code:
sample.txt
0125961349
01359395930
019349130
I parse 1 of the contact number into an object, eg: 019349130. hence:
cout << cp.contactNum << endl;
and the final result is
19349130
This is not the result I want. And you can see I have different length for the integer, I cannot use the leading zero solution to solve it or else it will become something like 0019349130.
you must parse the numbers into a string or const char* else you lose information about the heading 0. So the type of contactNum should be std::string instead of int.

How to determine user input commands

I am starting to write a command line converter and the only concern I have is user input (rest wont be hard). The program will have few commands like (convert 2 m to km), so when the user enters that, the program will output the converted value. My question is, what is the best way to parse user input and determine the command that user entered?. Should I divide user input into array of words and then pass to a function, so it can do something or there is another way?
I have written a few types of "simple parsers" (and several more advanced ones). From what you describe, if the commands are "convert 2 m to km", then you would simply need to split things on spaces.
Of course, if you allow "convert2mtokm" and "convert 2m to km" it gets a bit more difficult to deal with. Sticking to a "strict rule of there has to be a(t least one) space between words" makes life a lot easier.
At that point, you will have a vector<string> cmd that can be dealt with. So for example:
if (cmd[0] == "convert")
{
convert(cmd);
}
...
void convert(vector<string> cmd)
{
double dist = stod(cmd[1]);
string unit_from = cmd[2];
string unit_to = cmd[4];
if(cmd[3] != "to")
{
... print some error ...
}
double factor = unit_conversion(unit_from, unit_to);
cout << "that becomes " << dist * factor << " in " << unit_to << endl;
}
If you only have a few commands, it will be best to just strtok(input, ' '), which just splits up a string into an array of words in the command (assuming your command words are all separated by spaces). Then you can do some simple if/switch checks to see which command the user entered. For a larger number of commands (where some may be similar), you will probably need to implement or at least write out a DFA (deterministic finite automata).
An array of structures will be fine. The structure may be like this:
struct cmd
{
char **usrcmd;
void (*fc)();
};
Then you just have to iterate the array and compare the user input and the usrcmd[0] field (I assume the command is the first word).
However this solution is not the best way to go if you have a lot of user commands to handle.

c++ ignoring same number in an array

I have an array of random numbers, for example
6 5 4 4 8
I need to sort it and remove/ignore the same numbers while printing afterwards, so what I did is I sorted everything with bubble sorth algorithm and got something like this
4 4 5 6 8
Now in order to print only different numbers I wrote this for loop
for(int i=0;i<n;i++){
if(mrst[i]!=mrst[i-1] && mrst[i]>0){
outFile << mrst[i] << " ";
}
}
My question is, the array I have is at the interval of [0:12], though the first time when I call it, it checks an array index of -1 to see if there was the same number before, but it doesn't really exist, but the value stored in there usually is a huge one, so is there a possibility that there may be stored 4 and because of it, the first number won't be printed out. If so, how to prevent it, rewrite the code so it would be optimal?
Perhaps, you're looking for std::unique algorithm:
std::sort(mrst, mrst + n);
auto last = std::unique(mrst, mrst + n);
for(auto elem = mrst; elem != last; ++elem)
outFile << *elem << " ";
Well, as you noted already, you cannot do the check mrst[i] != mrst[i-1] in case i == 0. So I'm sure you can think of a way of not doing that check in exactly this case ... (This looks very much like a homework assignment, so I'm not really willing to give you a complete solution, but I guess I hinted enough)
Note also that it's undefined behaviour to access memory outside the boundaries of an array, so what you're doing there can do anything from working correctly to crashing your program, entirely at the discretion of the compiler.
Basically you can read from any place in heap. So mrst[-1] may give you some garbage from the memory. But you really should avoid doing this. In your case you can just change "mrst[i]!=mrst[i-1] && mrst[i]>0" to "i==0 || mrst[i]!=mrst[i-1]".
In c++ "A || B" don't execute "B" if the "A" is ok.

substitution cipher in c++

I have generate a random text file
A B C D E F G H
T W G X Z R L N
I want to encode my message so that A = T , B = W , C = G and so on..
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int
main ()
{
string getmsg;
ifstream openfile ("random.txt");
if (openfile.is_open ()) {
while (! openfile.eof ()) {
getline (openfile,getmsg); //read from random.txt
cout << getmsg << endl;
}
}
}
Am quite of stuck here.
eg. when i input the word "HAD" it will display "NTX" and by using the same random text file I can input "NTX" and give me back the "HAD"
While others have pointed out Map, I would have used a simple array (subs), of size 26 (If there are only capital alphabets).
Initialize the array with 0s. Read all the chars and their mapping. Store it something like this subs[char-'A'] = mapped_char. I will leave the reading to you.
EDIT-
If you are ready to pay for extra memory usage, just make the size of subs as 123 (ASCII for z + 1).
This will also simplify the logic to subs[char] = mapped_char
Since this feels like homework I'll give you guidance rather than a solution.
You want to create a bijectional map between an input character and a corresponding character to output.
One solid way to do that is with a Map. Create a Map that has as its key the input character e.g. 'A' and as its value the output character e.g. 'T'.
For each character that you read in from your file, use the Map to lookup the corresponding output character.
You will need to read input one character at a time (simplest), or read one line at a time (as you do now) and run through each line, character by character, to do the translation with the Map.
Update
To clarify a point in the comments, this is a bijectional function because there is exactly one encoded character for each original character. If the text does not have to be decoded, a Map will do for the software representation of the function. If decoding is needed, a Bimap is more appropriate.
Injective Function
Bijective Function
http://en.wikipedia.org/wiki/Injective_function
one way to do it is if you
take a look at std::map<> (map<char,char> in your case)
using it you can setup a map of character pairs, then when you read one character from your file/buffer you look it up in the map and retrieve the corresponding character.
another, more verbose way, would be to have a switch statement
char ch;
ch << openfile
switch(ch)
{
case 'A': ch = 'T'; break;
...
}
cout << ch;
there are other ways as well, see if you can find one more involving an array.

How to capture 0-2 groups in C++ regular expressions and print them?

Edit 3
I went to the good'ol custom parsing approach as I got stuck with the regular expression. It didn't turn out to be that bad, as the file contents can be tokenized quite neatly and the tokens can be parsed in a loop with a very simple state machine. Those who want to check, there's a snippet of code doing this with range-for, ifstream iterators and custom stream tokenizer at my other question in Stackoverflow here. These techniques lessen considerably the complexity of doing a custom parser.
I'd like to tokenize file contents in first part in capture groups of two and then just line by line. I have like a semi-functional solution, but I'd like to learn how to make this better. That is, without "extra processing" to make-up my lack of knowledge with capture groups. Next some preliminaries and in the end a more exact question (the line
const std::regex expression("([^:]+?)(^:|$)");
...is the one I'd like to ask about in combination with processing the results of it).
The files which are basically defined like this:
definition_literal : value_literal
definition_literal : value_literal
definition_literal : value_literal
definition_literal : value_literal
HOW TO INTERPRET THE FOLLOWING SECTION OF ROWS
[DATA ROW 1]
[DATA ROW 2]
...
[DATA ROW n]
Where each of the data rows consists of a certain number of either integers or floating point numbers separated by whitespace. Each row having as many numbers as the others (e.g. each row could have four integers). So, the "interpretation section" basically tells this format in plain text in one row.
I have an almost working solution that reads such files like this:
int main()
{
std::ifstream file("xyz", std::ios_base::in);
if(file.good())
{
std::stringstream file_memory_buffer;
file_memory_buffer << file.rdbuf();
std::string str = file_memory_buffer.str();
file.close();
const std::regex expression("([^:]+?)(^:|$)");
std::smatch result;
const std::sregex_token_iterator end;
for(std::sregex_token_iterator i(str.begin(), str.end(), expression); i != end; ++i)
{
std::cout << (*i) << std::endl;
}
}
return EXIT_SUCCESS;
}
With the regex defined expression, it now prints the <value> parts of the definition file, then the interpretation part and then the data rows one by one. If I change the regex to
"([^:]+?)(:|$)"
...it prints all the lines tokenized in groups of one, almost like I would like to, but how tokenize the first part in groups of two and the rest line by line?
Any pointers, code, explanations are truly welcomed. Thanks.
EDIT:
As noted to Tom Kerr already, but some additional points, this is also a rehearsal, or coding kata if you will, to not to write a custom parser, but to see if I could -- or we could :-) -- accomplish this with regex. I know regex isn't the most efficient thing to do here, but it doesn't matter.
What I'd hope to have is something like a list of tuples of header information (tuple of size 2), then the INTERPRET line (tuple of size 1), which I could use to choose a function on what to do with the data lines (tuple of size 1).
Yep, the "HOW TO INTERPRET" line is contained in a set of well-defined strings and I could just read line by line from the beginning, splitting strings along the way, until one of the INTERPRET lines is met. This regex solution is not the most efficient method, I know, but more like coding kata to get myself to write something else than customer parsers (and it's quite some time I've write in C++ the last time, so this is rehearsing otherwise too).
EDIT 2
I have managed to get access to the tuples (in the context of this question) by changing the iterator type, like so
const std::sregex_iterator end;
for(std::sregex_iterator i(str.begin(), str.end(), expression); i != end; ++i)
{
std::cout << "0: " << (*i)[0] << std::endl;
std::cout << "1: " << (*i)[1] << std::endl;
std::cout << "2: " << (*i)[2] << std::endl;
std::cout << "***" << std::endl;
}
Though this is still way off what I'd like to have, there's something wrong with the regular expression I'm trying ot use. In any event, this new find, another kind of iterator, helps too.
I believe the re you are attempting is this:
TEST(re) {
static const boost::regex re("^([^:]+) : ([^:]+)$");
std::string str = "a : b";
CHECK(boost::regex_match(str, re));
CHECK(!boost::regex_match("a:a : bbb", re));
CHECK(!boost::regex_match("aaa : b:b", re));
boost::smatch what;
CHECK(boost::regex_match(str, what, re, boost::match_extra));
CHECK_EQUAL(3, what.size());
CHECK_EQUAL(str, what[0]);
CHECK_EQUAL("a", what[1]);
CHECK_EQUAL("b", what[2]);
}
I'm not sure I would recommend regex in this instance though. I think you'll find simply reading a line at a time, splitting on :, and then trimming the spaces more manageable.
I guess if you can't depend the below line as a sentinel, then it would be more difficult. Usually I would expect a format like this to be obvious from that line, not the format of each line of the header.
HOW TO INTERPRET THE FOLLOWING SECTION OF ROWS