ASCII and isalpha if statement issue - c++

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

Related

Trying to read a single character at a time into an array of indefinite size

I am a CS student working on a c++ project. We have been instructed to declare a struct and use it to read in an array of chars and keep a tally of how many letters are used in the string. We are not allowed to use a string; it MUST be an array of our declared struct.
The input must be as long as the user wants; the code has to be able to accept new lines of input and be terminated by '.'
I'm really struggling here. I don't even know where to begin. I've thrown together some code as best-guess for what to do, but it crashes after pressing "." then enter, and I don't know why.
//declare struct
struct data
{
int tally = 0;
char letter;
};
//size of string to read in at a time
const int SIZE_OF_CHUNK = 11;
int main()
{
//input chunk of struct
data input[SIZE_OF_CHUNK];
int placemark,
length;
cout << "Enter sequence of characters, '.' to terminate:" << endl;
do
{
for (int index = 0; (input[index].letter != '\0') && (input[index - 1].letter != '.'); index++)
{
cin >> input[index].letter;
placemark++;
}
//I intend to put something here to handle if the code
needs to read in another chunk, but I want to fix the crashing
problem first
}
while (input[placemark].letter != '.');
//print out what was read in, just to check
for (int index = 0; input[index].letter != '\0'; index++)
{
cout << input[index].letter;
}
return 0;
}
I've tried looking up how to read in a single character but haven't found anything helpful to my circumstances so far. Any tips on what I'm doing wrong, or where I can find helpful resources, would be very much appreciated.
Are you sure you must use a declared struct?
If you just want to count the number of times a character has appeared, you don't need to store the character; you just need to store the number of times it appeared. So just unsigned lettersCount[26], and each index maps to a letter (i.e. index 0 means a, index 1 means b). Whenever a letter appears, just increase the count of that index.
You can map a letter to the index by making use of ASCII. Every letter is represented by a decimal number that you can look it up at ASCII table. For example, the letter a is represented by the decimal value 97, b is 98 and so on. The number increases successively, which we can make use of. So if you want to map a letter to an index, all you need to do is just value - 97 or value - 'a'. For example, if you read in the letter a, take away 97 from that and you'll get 0, which is what you want. After getting the index, it's just a simple ++ to increment the count of that letter.
Regarding the treatment of uppercase and lowercase (i.e. treat them the same or differently), it'll be up to you to figure it out how to do it (which should be fairly simple if you can understand what I've explained).

Null terminator carrying through when indexing string

I am trying pull specific characters from a string array, and assign them to defined indices in a new variable. I am having issues with what I expect is the null terminator, as there appear to be random assortment of undefined characters at the end of my strings.
I am new to coding in C++, and lower level programming in general. Note that the function "charBi" works perfectly, but it no longer works when assigning the output of "charBi" to the variable "binar" in the "strBi" function. I realize the code is probably not great, but any help is welcome, especially as it relates to getting rid of the random characters at the end of my "binar" string.
Thanks!
#include <iostream>
#include <array>
using namespace std;
//Program meant to output a string of binary for an input word or phrase
//library of letter and binary pairs
char letterNumber[27][10]={"A01000001","B01000010","C01000011","D01000100","E01000101","F01000110","G01000111",
"H01001000","I01001001","J01001010","K01001011","L01001100","M01001101","N01001110",
"O01001111","P01010000","Q01010001","R01010010","S01010011","T01010100","U01010101",
"V01010110","W01010111","X01011000","Y01011001","Z01011010"," 01011111"};
//finds binary number associated with input character. One character input
string charBi(char inputVar){ //WHY DOES THIS ONLY WORK IF THE FUNCTION IS A STRING?
//loop setup
int n=0;
int last=sizeof(letterNumber)/sizeof(letterNumber[0]); // equal 27
//loops through each of the strings in letterNumber
while (n!=last) {
if (letterNumber[n][0]==inputVar){ // if the letter is equal to input letter
char bina[8]; //number of numbers following a letter
for(int i=1;i<9;i++){ // writes the number associated with the letter to bina
bina[i-1]=letterNumber[n][i]; // assigns number to specific index
}
return bina; //BINA DEFINED AS CHAR, BUT OUTPUTTING AS STRING
}
n++;
}
}
//forms binary string of numbers for input phrase
string strBi(string strg){ //WHY DOES THIS ONLY WORK IF THE FUNCTION IS A STRING?
char binar[8*strg.length()]; //binary for each character is 8 numbers long
for(int i=0;i<strg.length();i++){ // for every letter in the input phrase
string chbi=charBi(strg[i]); //gets binary for individual letter from charBi function
cout<<"charbi sends: "<<chbi<<endl; //for debugging
for(int n=0;n<8;n++){ //for every 1 or 0 in the binary for an idividual letter
binar[(8*i)+n]=chbi[n]; // assign in order to string binar
}
cout<<"binar updates to: "<<binar<<endl; //for debugging
getchar(); //for debugging
}
return binar; //BINAR DEFINED AS CHAR, BUT OUTPUTTING AS STRING
}
int main(){
cout<<"final string is: "<<strBi("HELLO WORLD");
return 0;
}
Since you didn't properly terminate your arrays, the program is undefined.
In order to store a k-letter string, you need to use a k+1-element array and terminate it – char bina[9] = {}; and char binar[8*strg.length() + 1] = {}; should do the trick.
But you can simplify things a bit by leaving C behind:
std::map<char, std::string> letterNumber =
{{'A', "01000001"},
{'B', "01000010"},
// ...
{' ', "01011111}"}};
//forms binary string of numbers for input phrase
std::string strBi(const std::string& strg)
{
std::string binar;
binar.reserve(8 * strg.size());
std::for_each(strg.begin(), strg.end(), [&binar](char c) { binar += letterNumber[c]; });
return binar;
}
Make binar one character longer (char binar [8 * strg.length() + 1];) and set the last character to NUL (just before returning, do binar[8 * strg.length()] = '\0';)

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);
}

capitalizing characters, how toupper works?

I need to use a character array and take the characters in the array and capitalize and lower case them as necessary. I was looking at the toupper and its example, but I'm confused about how this works. Looking from the example given on cplusplus.com I wrote
int main(){
int i = 0;
char str[] = "This is a test.";
while(str[i]){
putchar(toupper(str[i]));
i++;
}
for(int i = 0; i < 15; i++){
cout << str[i];
}
}
and there are two things I don't understand about this. The first is that without the cout at the bottom, the program prints out THIS IS A TEST. Does putchar print to the screen? (the use of putchar is not explained on the example). But my second more important question is why does the cout at the bottom still print out This is a test.? Does it not change the chars in str[]? Is there another way I should be doing this (keeping in mind I need to use character arrays)?
Yes, putchar() prints a character to the program's standard output. That is its purpose. It is the source of the uppercase output.
The cout at the bottom of the program prints the original string because you never modified it. The toupper() function doesn't -- indeed can't -- modify its argument. Instead, it returns the uppercased char.
putchar writes a single character to output: http://www.cplusplus.com/reference/cstdio/putchar/
As a result, the first while loop converts each character from str one at a time to upper case and outputs them. HOWEVER, it does not change the contents of str - this explains the lower case output from the second loop.
Edit:
I've expanded the first loop:
// Loop until we've reached the end of the string 'str'
while(str[i]){
// Convert str[i] to upper case, but then store that elsewhere. Do not modify str[i].
char upperChar = toupper(str[i]);
// Output our new character to the screen
putchar(upperChar);
i++;
}

C++: Checking whether a string character is a digit using isdigit. .

I am reading input for my program in a loop using getline.
string temp(STR_SIZE, ' ');
string str_num(STR_SIZE, ' ');
...
getline(cin, temp, '\n');
After which, I use a function to find the next delimiter(white space) and assign all the characters before the white space to str_num. Looks something like this:
str_num.assign(temp, 0, next_white_space(0));
I have verified that this works well. The next step in my solution would be to convert str_num to an int(this part also works well), but I should check to make sure each character in str_num is a digit. Here's the best of what I've tried:
if(!isdigit(str_num[0] - '0')) {
cout << "Error: Not an appropriate value\n";
break; /* Leave control structure */
}
For some reason, This always prints the error message and exits the structure.
Why is that?
I've used operator[] for string objects before, and it seemed to work well. But, here, it's totally messing me up.
Thanks.
std::isdigit takes a char's integer value and checks it.
So, remove the - '0' and just pass str_num[index] to isdigit().
Note: because this function comes from C, the old style of treating chars as integers shows through in the method taking an int. However, chars can promote to int values, so a char becomes an int just fine and this works.