C++ Adding any character inside string array - c++

This is my first time I ask , so please can help. My question is how can I Add any character between any string like , mean adding dot after every c (small letter) , but I dont want to use any function , I want to write my own void function with passing only one parameter that should be an array of char , Can help please?
I learn how to check every character in the string with
while(*p!='\0')
{
/// What should I write here to check if there is any dot , then add after it
/// a small c
p++;
}

If you are going to do it the C way, I'd suggest you try something like this:
void adjust_string(char*output_p, int output_space, const char* input_p)
{
//while (there is still input left, and room in output buffer) {
while (*input_p!='\0' && output_space>2) {
//copy input character to output
//update the output pointer
//update the amount of room left in the output buffer
//if (its a special character) {
//add the extra character to output
//update the output pointer
//update the amount of room left in the output buffer
}
//update the input pointer
input_p++;
}
//null-terminate the output string
}
In the function that calls this function, you need to provide an array for the output to be placed into and specify its length, so you can't get a buffer overrun.
Note: in checking for room in the output buffer you need to take into account the possibility of adding the extra character in, and the room for the terminating null character.

Related

Why a "no matching function" error for call by reference with literal number?

The problem asks to create a program that asks the user to enter some text and that text will be surrounded by asterisks depending on the width of the screen for example if the user inputs "Hello world" the output should be:
****************
* Hello World! *
****************
I've tried to create the functions but I'm stuck becaus of a compiler error with the shown minimal code.
Question: Why does it tell me no matching function for within_width(text, 80)?
Some of the code I have is below:
#include <iostream>
#include <string>
void display_header (std::string &header) {
std::string text;
header = text;
}
bool within_width (std::string& text, unsigned short int& max_width) {
}
int main() {
std::string text;
std::cout << "Please enter header text: ";
std::getline(std::cin, text);
if (within_width(text, 80)) {
// call the display_header function and pass in the text
// inputted by the user
} else {
std::cout << text;
}
return 0;
}
This declaration of the function
bool within_width (std::string& text, unsigned short int& max_width)
asks for an unsigned short int variable, because it has a reference parameter, see the second &.
To satisfy it, you need to put the value 80 into a variable and give the variable as parameter.
unsigned short int MyWidth=80;
if (within_width(text, MyWidth))
Alternatively (but I assume you are not allowed) you can use a call by value parameter
bool within_width (std::string& text, unsigned short int max_width)
Then you could call as shown.
I won't give a full answer to the exercise here, just some clues.
the display_header() and within_width() functions need to know the string given in parameters but may not modify it ; thus the type of this parameter should be const std::string & (the const was missing).
the second parameter of the within_width() function is just an integer that will be compared to the length of the string ; you don't need to pass it by reference (or at least const), rather by value. Here, the (non-const) reference prevents from passing the literal constant 80.
(it seems to be the main concern of the question after edition)
You need to reason step by step.
all of this depends on the size of the string (12 for Hello World!) ; this information is available via size(text) (or text.size())
(https://en.cppreference.com/w/cpp/iterator/size)
(https://en.cppreference.com/w/cpp/string/basic_string/size)
This size will have to be compared to max_width
Displaying the line with header will require 4 more characters because * will be prepended and * will be appended.
Thus the two surrounding lines will have the length size(header)+4 too.
In order to create such a string made of *, you could use a constructor of std::string taking two parameters : the count of characters and the character to be repeated.
(https://en.cppreference.com/w/cpp/string/basic_string/basic_string)
Send all of this to std::cout in the correct order.
Edit: Just noticing that this answer probably goes far beyond the scope of the task you have been given (just filling in some skeleton that has been provided by your teacher).
I'll still leave it here to illustrate what could be done with arbitrary input. Maybe you want to experiment a little further than what you have been asked...
bool within_width(...)
Pretty simple: string.length() <= max – just wait a second, you need to consider asterisks and spaces at beginning and end of output, so: max - 4
But you can do better, you can split the string, best at word boundaries. That's a bit difficult more difficult, though:
std::vector<std::string> lines;
// we'll be starting with an initially empty line:
auto lineBegin = text.begin();
auto lineEnd = text.begin();
for(auto i = text.begin(); i != text.end(); ++)
// stop condition empty: we'll stop from inside the loop...
{
// ok, we need to find next whitespace...
// we might try using text.find_first_of("..."), but then we
// need to know any whitespace characters ourselves, so I personally
// would rather iterate manually and use isspace function to determine;
// advantage: we can do other checks at the same time, too
auto distance = std::distance(lineBegin, i);
if(std::distance(lineBegin, i) > maxLineLength)
{
if(lineEnd == lineBegin)
{
// OK, now we have a problem: the word itself is too long
// decide yourself, do you want to cut the word somewhere in the
// middle (you even might implement syllable division...)
// or just refuse to print (i. e. throw an exception you catch
// elsewhere) - decide yourself...
}
else
{
lines.emplace_back(lineBegin, lineEnd);
lineBegin = lineEnd; // start next line...
}
}
// OK, now handle current character appropriately
// note: no else: we need to handle the character in ANY case,
// if we terminated the previous line or not
if(std::isspace(static_cast<unsigned char>(*i)))
{
lineEnd = i;
}
// otherwise, we're inside a word and just go on
}
// last line hasn't been added!
lines.emplace_back(lineBegin, lineEnd);
Now you can calculate maximum length over all the strings contained. Best: Do this right when adding a new line to the vector, then you don't need a separate loop...
You might have noticed that I didn't remove whitespace at the end of the strings, so you wouldn't need to add you own one, apart, possibly, from the very last string (so you might add a lines.back() += ' ';).
The ugly part, so far, is that I left multiple subsequent whitespace. Best is removing before splitting into lines, but be aware that you need to leave at least one. So:
auto end = text.begin();
bool isInWord = false; // will remove leading whitespace, if there is
for(auto c : text)
{
if(std::isspace(static_cast<unsigned char>(c)))
{
if(isInWord)
{
*end++ = ' '; // add a single space
isInWord = false;
}
}
else
{
*end++ = c;
isInWord = true;
}
}
This would have moved all words towards the beginning of the string, but we yet to drop the surplus part of the string yet contained:
text.erase(end, text.end());
Fine, the rest is pretty simple:
iterate over maximum length, printing a single asterisk in every loop
iterate over all of your strings in the vector: std::cout << "* " << line << "*\n";
repeat the initial loop to print second line of asterisks
Finally: You introduced a fix line limit of 80 characters. If console is larger, you just won't be using the entire available width, which yet might be acceptable, if it is smaller, you will get lines broken at the wrong places.
You now could (but that's optional) try to detect the width of the console – which has been asked before, so I won't go any deeper into.
Final note: The code presented above is untested, so no guarantee to be bugfree!

Creating an array of characters (user-input) through recursion

I'm creating a program (whose functions must be recursive) which accepts a series of characters from the user, terminated by a period, and displays the characters backwards on the screen. A sample run should give:
Enter a character: H
Enter a character: i
Enter a character: .
iH
I made a function that reverses an array which takes a character array and its size as parameters.
void print_backwards(char a[], int size){
int i = size-1;
cout << a[i];
i--;
if(i >= 0){
print_backwards(a, i);
}
}
I have a problem, however, with initializing the character array using recursion. How can I solve this problem?
This sounds like a homework problem, so I'm not going to solve the problem for you. However, I can give you a push in the right direction.
Make a function that takes a character array by reference and an offset.
On the first call of the function, give it an offset of zero and pass it the empty array.
The function itself should read a single character from the user.
If the character is a ., write a null byte to the current position and return the current offset, else, write the supplied character to the current position, then call the function again with offset+1.
The function will return the length of the input.
The function body will look something like
// Get character from user
if ( c == '.' ) {
input[offset] = '\0';
return offset;
} else {
input[offset] = c;
return thisFunction(input, offset+1);
}

How to ignore \n for istream strings

Does anyone have any suggestions on how I can ignore the "\n" coming in from istream? I'm trying to extract data from txt file where in some "cells", text has been written in such that there are "\n" coming in from when the user pressed Enter.
My goal is to take in some parts of this text and output it with " ; " separating the parts. However, in doing so, sometimes a "\n" gets sucked in and the output cell starts continuing downwards instead of just line going from right to left (which is preferred).
Any advice would be much appreciated!
string vectorToString(vector<size_t> positionVector, string mainString,
string outputString, int numLetters)
{
//Check how many different positions were found and make that the length
//of the vector that will store all the strings for each finding
int positionVectorLength = positionVector.size();
//foundPos is the position of the cursor along the foundPositions vector
int vectorPosition=0;
while (vectorPosition < positionVectorLength)
{
//define local variable that will store the value along the vector
size_t vectorPositionValue = positionVector.at(vectorPosition);
//append the numLetters after the positionValue in string frameNum
outputString.append(mainString, vectorPositionValue, numLetters);
outputString.append(" ; ");
//reiterate until all the positions have been recorded
vectorPosition+=1;
}
//return the string of frame numbers
return(outputString);
}
You can use this to remove all the \n from your string:
mainString.erase(std::remove(mainString.begin(),mainString.end(),'\n'),mainString.end());

Incrementing characters being read

I am trying to decode an input file that looks something like this:
abbaabbbbaababbaabababaabababaabbababaabababababababa...
and compare it to a makeshift mapping I have made using two arrays
int secretNumber[10];
string coding[10];
coding[0]="abb";
coding[1]="aabbbba";
coding[2]="abab";
...
I am not sure how I can start off by reading the first character which is 'a' then check if it's in the coding array. If it is print out the secretCoding and move the next character b. Else if it's not in the array then add the next character to the first in a string and check to see if "ab" is in the array and if that isn't either add the next character which makes "abb" and so on.
Something like this:
while (!(readFile.eof()) ){
for(int i=0; i<10; i++){
if(stringOfChars==coding[i]){
cout << secretNumber[i] <<endl;
//Now increment to next char
}
else{
//combine the current string with the next character
}
}
}
Question: How do I go about reading in a character if its a match move to next character if not combine current character and the next character until there's a match.
You sould use a design pattern called interpreter.
Here is a link to a c++ version.
If you want a solution that works for arbitrary input sizes, i.e. which doesn't store the entire input in memory, then you can use a queue (e.g. std::deque<char>) to read in a handful of characters at a time, pushing data in from the back. Then you check if the queue still has three, four or five characters left, and if so compare them to your patterns; if there's a match, you pop the corresponding characters off from the front of the queue.
I'm not sure but perhaps it seems like you are trying to implement the LZW compression algorithm. If that is the case, then you would have to change your approach a little. If you have decided that your secret code are integers, then you would have to assign a code to all the elements of the initial contents of the dictionary. The initial dictionary is basically all the strings in your source alphabet of size 1. In your case it would be "a to z", or only "a" and "b" if you are keeping it simple.
The other thing is that you need to look through your dictionary for any existing string which has been assigned a code. The best way to do that is to use STL map container which could map strings to integers in your case. Also, its a good idea to place a restriction on the size to which the dictionary could grow as new strings continue to be added to it.
Overall,
Use std::map< std::string, int > dictionary; as your dictionary for strings such as a, b, aa, ab, aab, etc... and the matching code for it.
The coding[0], coding[1] would not be required as they strings would serve as the key in this dictionary.
The secretNumber[0], secretNumber[1] also would not be needed as the value would for a key would give the secretNumber.
Here is what it may look like:
std::map< std::string, int > dictionary;
int iWordCount = 0;
/*
Initialize the dictionary with the code for strings of length 1 in your source alphabet.
*/
dictionary["a"] = 0;
dictionary["b"] = 1;
iWordCount = 2; // We would be incrementing this as we keep on adding more strings to the dictionary.
std::string newWord = "", existingWord = "";
while (!(readFile.eof()) ){
/*
I'm assuming the next character is read in the variable "ch".
*/
newWord += ch;
if ( dictionary.count(newWord) != 0 ) { // Existing word.
/*
Do something
*/
}
else { // We encountered this word for the first time.
/*
Do something else
*/
}
}

ASCII and isalpha if statement issue

I am writing a program that takes a user inputted character, such as A, and a user inputted number, such as 7. The program checks the validity of the character, if true runs thru till it gets to this loop inside of a function. I am using ascii decimal for this loop inside of a function. This loop needs to check isalpha and if it is run the code inside the {}'s, it's doing that correctly. The else is not working the way I want and am not sure how to correct it. I need the else (is not alpha) to add a 1 back to the counter in the loop and increase the ascii by 1. If I run it as so, it gives off a retry/ignore/abort error. If I run it without the num++; it runs and stops after the loop ends. So, if you put in a Z and choose 3, it runs thru the loop 3 times and outputs just a Z. Any thoughts on how to fix this?
I need it to output something like: Input: Z Input: 4 it should output: Z A B C to the screen. It needs to ignore other ascii non alpha characters.
Thanks
string buildSeries(char A, int num)
{
//builds the output with the info the
//user inputted
stringstream str1;
string outted;
int DeC=(int)A, i = 0;
//loop builds the output
for(i=0;i<num;i++)
{
if (isalpha(DeC))
{
//converts the decimal to a letter
str1<<(char)DeC;
//adds a space
str1<<" ";
//increases the decimal
DeC++;
}
else
{
num++;
DeC++;
}
}
//builds the sstream and puts it in
//variable "outted"
outted = str1.str();
return outted;
}
If you need to loop back to 'A' at Z change your DeC++ to
if DecC == 'Z'
DecC = 'A'
else
DecC++;
Or you could get fancy and use the modulus operator
Edit
I think the problem may be that this stringstream insertion operator, >>, doesn't have an overload that handles a char. It's converting the char to a short or an int then inserting it. Try using string::append(size_t size, char c) instead. That should handle inserting a char.
That is replace you calls to str1<<(char)DeC; with outted.append(1, (char)DeC) and remove your use of the string stream
What is DeC? The phrase "ascii list" makes me suspect it's a 'C' string, in which case you are calling isAlpha() on the pointer not on the value in the string.
edit: If for example you have
char DeC[40];
// read in a string form somewhere
// DeC is a pointer to some memory it has a value of a 32 or 64bit number
if ( isAlpha(DeC) {
// what you might have meant is
if ( isAlpha(*DeC) { // the character value at the current position in DeC